mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
ANDROID: KVM: arm64: Specify stage-2-protected regions in DT
Parse the devicetree during pKVM init to find nodes with the
"pkvm,protected-region" compatible string. These nodes specify a
physical address range in reg that must alway be mapped as invalid in
the host stage-2 page table when running under pKVM.
Example DT:
pkvm_prot_reg: pkvm_prot_reg@80000000 {
compatible = "pkvm,protected-region";
reg = <0x00 0x80000000 0x00 0x200000>;
};
Bug: 244543039
Bug: 244373730
Change-Id: I102cd16c91d96e5283cdd1a4fa58836cc4834eac
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
@@ -244,6 +244,7 @@ static inline int pkvm_get_max_wrps(void)
|
||||
|
||||
enum pkvm_moveable_reg_type {
|
||||
PKVM_MREG_MEMORY,
|
||||
PKVM_MREG_PROTECTED_RANGE,
|
||||
};
|
||||
|
||||
struct pkvm_moveable_reg {
|
||||
|
||||
@@ -60,7 +60,8 @@ enum pkvm_component_id {
|
||||
PKVM_ID_HYP,
|
||||
PKVM_ID_GUEST,
|
||||
PKVM_ID_FFA,
|
||||
PKVM_ID_MAX = PKVM_ID_FFA,
|
||||
PKVM_ID_PROTECTED,
|
||||
PKVM_ID_MAX = PKVM_ID_PROTECTED,
|
||||
};
|
||||
|
||||
extern unsigned long hyp_nr_cpus;
|
||||
@@ -87,6 +88,7 @@ bool addr_is_memory(phys_addr_t phys);
|
||||
int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot,
|
||||
bool update_iommu);
|
||||
int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, enum pkvm_component_id owner_id);
|
||||
int host_stage2_protect_pages_locked(phys_addr_t addr, u64 size);
|
||||
int host_stage2_unmap_reg_locked(phys_addr_t start, u64 size);
|
||||
int kvm_host_prepare_stage2(void *pgt_pool_base);
|
||||
int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd);
|
||||
|
||||
@@ -2235,3 +2235,16 @@ bool __pkvm_check_ioguard_page(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int host_stage2_protect_pages_locked(phys_addr_t addr, u64 size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hyp_assert_lock_held(&host_mmu.lock);
|
||||
|
||||
ret = __host_check_page_state_range(addr, size, PKVM_PAGE_OWNED);
|
||||
if (!ret)
|
||||
ret = host_stage2_set_owner_locked(addr, size, PKVM_ID_PROTECTED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -303,6 +303,23 @@ static int fix_hyp_pgtable_refcnt(void)
|
||||
&walker);
|
||||
}
|
||||
|
||||
static int unmap_protected_regions(void)
|
||||
{
|
||||
struct pkvm_moveable_reg *reg;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < pkvm_moveable_regs_nr; i++) {
|
||||
reg = &pkvm_moveable_regs[i];
|
||||
if (reg->type != PKVM_MREG_PROTECTED_RANGE)
|
||||
continue;
|
||||
ret = host_stage2_protect_pages_locked(reg->start, reg->size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __noreturn __pkvm_init_finalise(void)
|
||||
{
|
||||
struct kvm_host_data *host_data = this_cpu_ptr(&kvm_host_data);
|
||||
@@ -344,6 +361,10 @@ void __noreturn __pkvm_init_finalise(void)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = unmap_protected_regions();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = hyp_ffa_init(ffa_proxy_pages);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/sort.h>
|
||||
@@ -97,6 +98,7 @@ static void __init sort_moveable_regs(void)
|
||||
static int __init register_moveable_regions(void)
|
||||
{
|
||||
struct memblock_region *reg;
|
||||
struct device_node *np;
|
||||
int i = 0;
|
||||
|
||||
for_each_mem_region(reg) {
|
||||
@@ -107,6 +109,30 @@ static int __init register_moveable_regions(void)
|
||||
moveable_regs[i].type = PKVM_MREG_MEMORY;
|
||||
i++;
|
||||
}
|
||||
|
||||
for_each_compatible_node(np, NULL, "pkvm,protected-region") {
|
||||
struct resource res;
|
||||
u64 start, size;
|
||||
int ret;
|
||||
|
||||
if (i >= PKVM_NR_MOVEABLE_REGS)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
start = res.start;
|
||||
size = resource_size(&res);
|
||||
if (!PAGE_ALIGNED(start) || !PAGE_ALIGNED(size))
|
||||
return -EINVAL;
|
||||
|
||||
moveable_regs[i].start = start;
|
||||
moveable_regs[i].size = size;
|
||||
moveable_regs[i].type = PKVM_MREG_PROTECTED_RANGE;
|
||||
i++;
|
||||
}
|
||||
|
||||
kvm_nvhe_sym(pkvm_moveable_regs_nr) = i;
|
||||
sort_moveable_regs();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user