mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
ANDROID: KVM: arm64: Expose linear map APIs to pKVM modules
pKVM modules may need to temporarily map large-ish physically contiguous regions of memory when bootstrapping themselves. In order to support this use-case, introduce two new APIs in the module_ops struct allowing to map and unmap pages in pKVM's linear map range. Since pKVM's page ownership infrastructure relies on linear map PTEs, this needs to be done with special care. To avoid any problem, let's count the number of pages mapped by modules and unsure they have been unmapped before reaching the point of deprivilege. Bug: 244373730 Change-Id: I4aecb93f5c9ba08d9f830d1f0976704688b98509 Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
committed by
Treehugger Robot
parent
abafa1328b
commit
2529c7a2bd
@@ -23,6 +23,8 @@ struct pkvm_module_ops {
|
||||
void (*putx64)(u64 num);
|
||||
void *(*fixmap_map)(phys_addr_t phys);
|
||||
void (*fixmap_unmap)(void);
|
||||
void *(*linear_map_early)(phys_addr_t phys, size_t size, enum kvm_pgtable_prot prot);
|
||||
void (*linear_unmap_early)(void *addr, size_t size);
|
||||
void (*flush_dcache_to_poc)(void *addr, size_t size);
|
||||
int (*register_host_perm_fault_handler)(int (*cb)(struct kvm_cpu_context *ctxt, u64 esr, u64 addr));
|
||||
int (*protect_host_page)(u64 pfn, enum kvm_pgtable_prot prot);
|
||||
|
||||
@@ -36,11 +36,51 @@ bool pkvm_modules_enabled(void)
|
||||
return __pkvm_modules_enabled;
|
||||
}
|
||||
|
||||
static u64 early_lm_pages;
|
||||
static void *__pkvm_linear_map_early(phys_addr_t phys, size_t size, enum kvm_pgtable_prot prot)
|
||||
{
|
||||
void *addr = NULL;
|
||||
int ret;
|
||||
|
||||
if (!PAGE_ALIGNED(phys) || !PAGE_ALIGNED(size))
|
||||
return NULL;
|
||||
|
||||
pkvm_modules_lock();
|
||||
if (!__pkvm_modules_enabled)
|
||||
goto out;
|
||||
|
||||
addr = __hyp_va(phys);
|
||||
ret = pkvm_create_mappings(addr, addr + size, prot);
|
||||
if (ret)
|
||||
addr = NULL;
|
||||
else
|
||||
early_lm_pages += size >> PAGE_SHIFT;
|
||||
out:
|
||||
pkvm_modules_unlock();
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void __pkvm_linear_unmap_early(void *addr, size_t size)
|
||||
{
|
||||
pkvm_modules_lock();
|
||||
pkvm_remove_mappings(addr, addr + size);
|
||||
early_lm_pages -= size >> PAGE_SHIFT;
|
||||
pkvm_modules_unlock();
|
||||
}
|
||||
|
||||
int __pkvm_close_module_registration(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pkvm_modules_lock();
|
||||
/*
|
||||
* Page ownership tracking might go out of sync if there are stale
|
||||
* entries in pKVM's linear map range, so they must really be gone by
|
||||
* now.
|
||||
*/
|
||||
WARN_ON(early_lm_pages);
|
||||
|
||||
ret = __pkvm_modules_enabled ? 0 : -EACCES;
|
||||
if (!ret) {
|
||||
void *addr = hyp_fixmap_map(__hyp_pa(&__pkvm_modules_enabled));
|
||||
@@ -60,6 +100,8 @@ const struct pkvm_module_ops module_ops = {
|
||||
.putx64 = hyp_putx64,
|
||||
.fixmap_map = hyp_fixmap_map,
|
||||
.fixmap_unmap = hyp_fixmap_unmap,
|
||||
.linear_map_early = __pkvm_linear_map_early,
|
||||
.linear_unmap_early = __pkvm_linear_unmap_early,
|
||||
.flush_dcache_to_poc = __kvm_flush_dcache_to_poc,
|
||||
.register_host_perm_fault_handler = hyp_register_host_perm_fault_handler,
|
||||
.protect_host_page = hyp_protect_host_page,
|
||||
|
||||
Reference in New Issue
Block a user