mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +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 Signed-off-by: David Brazdil <dbrazdil@google.com> Change-Id: Id30eb44c23a153fc3aaabebff8b33d1c7192e95e
This commit is contained in:
@@ -271,6 +271,34 @@ static void s2mpu_host_stage2_set_owner(phys_addr_t addr, size_t size, u8 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);
|
||||
@@ -438,4 +466,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