mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ANDROID: KVM: arm64: Unmap S2MPU MMIO registers from host stage-2
The S2MPU driver needs to protect its MMIO registers from the host.
Implement the host_stage2_adjust_mmio_range callback and restrict
the address range that is about to be mapped in to avoid the known
S2MPU MMIO regions.
Test: builds, boots
Bug: 190463801
Change-Id: Ib46f5dd651b9368c31940035e4c28a7324fc4160
Signed-off-by: David Brazdil <dbrazdil@google.com>
(cherry picked from commit 8f23406153)
Signed-off-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
committed by
Quentin Perret
parent
877e4ee079
commit
8c2b04dc1b
@@ -270,6 +270,34 @@ static void s2mpu_host_stage2_set_owner(phys_addr_t addr, size_t size, u32 owner
|
||||
hyp_spin_unlock(&s2mpu_lock);
|
||||
}
|
||||
|
||||
static int s2mpu_host_stage2_adjust_mmio_range(phys_addr_t addr, phys_addr_t *start,
|
||||
phys_addr_t *end)
|
||||
{
|
||||
struct s2mpu *dev;
|
||||
phys_addr_t dev_start, dev_end, int_start, int_end;
|
||||
|
||||
/* Find the PA interval in the non-empty, sorted list of S2MPUs. */
|
||||
int_start = 0;
|
||||
for_each_s2mpu(dev) {
|
||||
dev_start = dev->pa;
|
||||
dev_end = dev_start + S2MPU_MMIO_SIZE;
|
||||
int_end = dev_start;
|
||||
|
||||
if (dev_start <= addr && addr < dev_end)
|
||||
return -EPERM;
|
||||
|
||||
if (int_start <= addr && addr < int_end)
|
||||
break;
|
||||
|
||||
int_start = dev_end;
|
||||
int_end = PA_MAX;
|
||||
}
|
||||
|
||||
*start = max(*start, int_start);
|
||||
*end = min(*end, int_end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool s2mpu_host_smc_handler(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(u64, fn, host_ctxt, 0);
|
||||
@@ -432,4 +460,5 @@ const struct kvm_iommu_ops kvm_s2mpu_ops = (struct kvm_iommu_ops){
|
||||
.host_smc_handler = s2mpu_host_smc_handler,
|
||||
.host_mmio_dabt_handler = s2mpu_host_mmio_dabt_handler,
|
||||
.host_stage2_set_owner = s2mpu_host_stage2_set_owner,
|
||||
.host_stage2_adjust_mmio_range = s2mpu_host_stage2_adjust_mmio_range,
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include <asm/kvm_s2mpu.h>
|
||||
@@ -279,6 +280,13 @@ static void free_s2mpu_array(struct s2mpu *array)
|
||||
free_pages((unsigned long)array, order);
|
||||
}
|
||||
|
||||
static int cmp_s2mpu(const void *p1, const void *p2)
|
||||
{
|
||||
const struct s2mpu *a = p1, *b = p2;
|
||||
|
||||
return (a->pa > b->pa) - (a->pa < b->pa);
|
||||
}
|
||||
|
||||
static int create_s2mpu_array(struct s2mpu **array)
|
||||
{
|
||||
struct s2mpu_list_entry *entry, *tmp;
|
||||
@@ -297,6 +305,9 @@ static int create_s2mpu_array(struct s2mpu **array)
|
||||
}
|
||||
WARN_ON(i != kvm_hyp_nr_s2mpus);
|
||||
|
||||
/* Searching through the list assumes that it is sorted. */
|
||||
sort(*array, kvm_hyp_nr_s2mpus, sizeof(struct s2mpu), cmp_s2mpu, NULL);
|
||||
|
||||
kvm_hyp_s2mpus = kern_hyp_va(*array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user