From 60707bba73b923c72d0ea9a3e726d80b8e397a50 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Wed, 16 Aug 2023 15:02:44 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Add functions needed by EL2 modules in module ops EL2 IOMMU moduels need extra functions from module ops, to map memory, interact with the IOMMU layer and use the hyp allocator. Also, export ___pkvm_host_donate_hyp, instead of a function that always accept MMIO, as modules would use this function for both memory and MMIO. Bug: 357781595 Bug: 384432312 Change-Id: If3b807ef2181a0e9465599fdf260ba2904000f45 Signed-off-by: Mostafa Saleh --- arch/arm64/include/asm/kvm_pkvm_module.h | 40 ++++++++++++++++++++++-- arch/arm64/kvm/hyp/nvhe/modules.c | 22 +++++++++---- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h index 78349877e3c2..b0533e548d7d 100644 --- a/arch/arm64/include/asm/kvm_pkvm_module.h +++ b/arch/arm64/include/asm/kvm_pkvm_module.h @@ -8,6 +8,9 @@ #include typedef void (*dyn_hcall_t)(struct user_pt_regs *); +struct kvm_hyp_iommu; +struct iommu_iotlb_gather; +struct kvm_hyp_iommu_domain; #ifdef CONFIG_MODULES enum pkvm_psci_notification { @@ -105,6 +108,8 @@ enum pkvm_psci_notification { * is called before remasking SErrors. * @host_donate_hyp: The page @pfn is unmapped from the host and * full control is given to the hypervisor. + * @host_donate_hyp_prot: As host_donate_hyp_prot, but this variant sets + * the prot of the hyp. * @hyp_donate_host: The page @pfn whom control has previously been * given to the hypervisor (@host_donate_hyp) is * given back to the host. @@ -127,6 +132,19 @@ enum pkvm_psci_notification { * @hyp_va: Convert a physical address into a virtual one. * @kern_hyp_va: Convert a kernel virtual address into an * hypervisor virtual one. + * @hyp_alloc: Allocate memory in hyp VA space. + * @hyp_alloc_errno: Error in case hyp_alloc() returns NULL. + * @hyp_free: Free memory allocated from hyp_alloc(). + * @iommu_donate_pages: Allocate memory from IOMMU pool. + * @iommu_reclaim_pages: Reclaim memory from iommu_donate_pages() + * @iommu_request: Fill a request that is returned from the entry HVC (see hyp-main.c). + * @iommu_init_device: Initialize common IOMMU fields. + * @udelay: Delay in us. + * @hyp_alloc_missing_donations: + Missing donations if allocator returns NULL + * @__list_add_valid_or_report: Needed if the code uses linked lists. + * @__list_del_entry_valid_or_report: + Needed if the code uses linked lists. */ struct pkvm_module_ops { int (*create_private_mapping)(phys_addr_t phys, size_t size, @@ -154,7 +172,8 @@ struct pkvm_module_ops { int (*register_psci_notifier)(void (*cb)(enum pkvm_psci_notification, struct user_pt_regs *)); int (*register_hyp_panic_notifier)(void (*cb)(struct user_pt_regs *)); int (*register_unmask_serror)(bool (*unmask)(void), void (*mask)(void)); - int (*host_donate_hyp)(u64 pfn, u64 nr_pages); + int (*host_donate_hyp)(u64 pfn, u64 nr_pages, bool accept_mmio); + int (*host_donate_hyp_prot)(u64 pfn, u64 nr_pages, bool accept_mmio, enum kvm_pgtable_prot prot); int (*hyp_donate_host)(u64 pfn, u64 nr_pages); int (*host_share_hyp)(u64 pfn); int (*host_unshare_hyp)(u64 pfn); @@ -169,7 +188,24 @@ struct pkvm_module_ops { void* (*tracing_reserve_entry)(unsigned long length); void (*tracing_commit_entry)(void); void (*tracing_mod_hyp_printk)(u8 fmt_id, u64 a, u64 b, u64 c, u64 d); - + void * (*hyp_alloc)(size_t size); + int (*hyp_alloc_errno)(void); + void (*hyp_free)(void *addr); + u8 (*hyp_alloc_missing_donations)(void); + void * (*iommu_donate_pages)(u8 order, int flags); + void (*iommu_reclaim_pages)(void *p, u8 order); + int (*iommu_init_device)(struct kvm_hyp_iommu *iommu); + void (*udelay)(unsigned long usecs); + void (*iommu_iotlb_gather_add_page)(struct kvm_hyp_iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, + size_t size); + int (*pkvm_host_unuse_dma)(phys_addr_t phys_addr, size_t size); +#ifdef CONFIG_LIST_HARDENED + /* These 2 functions change calling convention based on CONFIG_DEBUG_LIST. */ + typeof(__list_add_valid_or_report) *list_add_valid_or_report; + typeof(__list_del_entry_valid_or_report) *list_del_entry_valid_or_report; +#endif ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(3); diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c index e160cddeaea4..128bcde56b3b 100644 --- a/arch/arm64/kvm/hyp/nvhe/modules.c +++ b/arch/arm64/kvm/hyp/nvhe/modules.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -79,11 +81,6 @@ void __pkvm_close_module_registration(void) */ } -static int __pkvm_module_host_donate_hyp(u64 pfn, u64 nr_pages) -{ - return ___pkvm_host_donate_hyp(pfn, nr_pages, true); -} - static void tracing_mod_hyp_printk(u8 fmt_id, u64 a, u64 b, u64 c, u64 d) { #ifdef CONFIG_TRACING @@ -130,7 +127,8 @@ const struct pkvm_module_ops module_ops = { .register_psci_notifier = __pkvm_register_psci_notifier, .register_hyp_panic_notifier = __pkvm_register_hyp_panic_notifier, .register_unmask_serror = __pkvm_register_unmask_serror, - .host_donate_hyp = __pkvm_module_host_donate_hyp, + .host_donate_hyp = ___pkvm_host_donate_hyp, + .host_donate_hyp_prot = ___pkvm_host_donate_hyp_prot, .hyp_donate_host = __pkvm_hyp_donate_host, .host_share_hyp = __pkvm_host_share_hyp, .host_unshare_hyp = __pkvm_host_unshare_hyp, @@ -145,6 +143,18 @@ const struct pkvm_module_ops module_ops = { .tracing_reserve_entry = tracing_reserve_entry, .tracing_commit_entry = tracing_commit_entry, .tracing_mod_hyp_printk = tracing_mod_hyp_printk, + .hyp_alloc = hyp_alloc, + .hyp_alloc_errno = hyp_alloc_errno, + .hyp_free = hyp_free, + .hyp_alloc_missing_donations = hyp_alloc_missing_donations, + .iommu_donate_pages = kvm_iommu_donate_pages, + .iommu_reclaim_pages = kvm_iommu_reclaim_pages, + .iommu_init_device = kvm_iommu_init_device, + .udelay = pkvm_udelay, +#ifdef CONFIG_LIST_HARDENED + .list_add_valid_or_report = __list_add_valid_or_report, + .list_del_entry_valid_or_report = __list_del_entry_valid_or_report, +#endif }; int __pkvm_init_module(void *module_init)