ANDROID: KVM: arm64: Allow skipping module page donation

__pkvm_map_module_page() currently goes through a full host-to-hyp
donation for every module page being mapped. However, in order to allow
mapping protected pages as modules, let's make this behaviour optional.

Bug: 264070847
Change-Id: Ic3b1b68f11283c215bc8c6e1352f91bcf52a3935
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Quentin Perret
2023-01-06 17:40:37 +00:00
parent 4b9c372d29
commit 63ad198da8
4 changed files with 13 additions and 13 deletions

View File

@@ -20,7 +20,7 @@ struct pkvm_module_ops {
enum kvm_pgtable_prot prot,
unsigned long *haddr);
void *(*alloc_module_va)(u64 nr_pages);
int (*map_module_page)(u64 pfn, void *va, enum kvm_pgtable_prot prot);
int (*map_module_page)(u64 pfn, void *va, enum kvm_pgtable_prot prot, bool is_protected);
int (*register_serial_driver)(void (*hyp_putc_cb)(char));
void (*puts)(const char *str);
void (*putx64)(u64 num);

View File

@@ -31,7 +31,7 @@ int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr);
void pkvm_remove_mappings(void *from, void *to);
int __pkvm_map_module_page(u64 pfn, void *va, enum kvm_pgtable_prot prot);
int __pkvm_map_module_page(u64 pfn, void *va, enum kvm_pgtable_prot prot, bool is_protected);
void __pkvm_unmap_module_page(u64 pfn, void *va);
void *__pkvm_alloc_module_va(u64 nr_pages);
#endif /* __KVM_HYP_MM_H */

View File

@@ -1177,7 +1177,7 @@ static void handle___pkvm_map_module_page(struct kvm_cpu_context *host_ctxt)
DECLARE_REG(void *, va, host_ctxt, 2);
DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3);
cpu_reg(host_ctxt, 1) = (u64)__pkvm_map_module_page(pfn, va, prot);
cpu_reg(host_ctxt, 1) = (u64)__pkvm_map_module_page(pfn, va, prot, false);
}
static void handle___pkvm_unmap_module_page(struct kvm_cpu_context *host_ctxt)

View File

@@ -142,24 +142,24 @@ void *__pkvm_alloc_module_va(u64 nr_pages)
return (void *)addr;
}
int __pkvm_map_module_page(u64 pfn, void *va, enum kvm_pgtable_prot prot)
int __pkvm_map_module_page(u64 pfn, void *va, enum kvm_pgtable_prot prot, bool is_protected)
{
unsigned long addr = (unsigned long)va;
int ret;
assert_in_mod_range(addr);
ret = __pkvm_host_donate_hyp(pfn, 1);
if (ret)
return ret;
ret = __pkvm_create_mappings(addr, PAGE_SIZE, hyp_pfn_to_phys(pfn), prot);
if (ret) {
WARN_ON(__pkvm_hyp_donate_host(pfn, 1));
return ret;
if (!is_protected) {
ret = __pkvm_host_donate_hyp(pfn, 1);
if (ret)
return ret;
}
return 0;
ret = __pkvm_create_mappings(addr, PAGE_SIZE, hyp_pfn_to_phys(pfn), prot);
if (ret && !is_protected)
WARN_ON(__pkvm_hyp_donate_host(pfn, 1));
return ret;
}
void __pkvm_unmap_module_page(u64 pfn, void *va)