From 25dfae84598b9cafae657f8702ed52ca744e4b20 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Thu, 17 Aug 2023 21:44:05 +0000 Subject: [PATCH] ANDROID: iommu/arm-smmu-v3-kvm: Support EL1 compiling as module This includes - Loading of EL2 code - Using module token to get hyp va Bug: 357781595 Bug: 384432312 Change-Id: I70cb6b1f848042bf9d98afd671400afa5fe15f78 Signed-off-by: Mostafa Saleh --- arch/arm64/kvm/iommu.c | 2 ++ arch/arm64/kvm/pkvm.c | 1 + .../iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c | 33 ++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/iommu.c b/arch/arm64/kvm/iommu.c index c6e884617bf1..8993be58895f 100644 --- a/arch/arm64/kvm/iommu.c +++ b/arch/arm64/kvm/iommu.c @@ -25,6 +25,7 @@ int kvm_iommu_register_driver(struct kvm_iommu_driver *kern_ops) */ return cmpxchg_release(&iommu_driver, NULL, kern_ops) ? -EBUSY : 0; } +EXPORT_SYMBOL(kvm_iommu_register_driver); int kvm_iommu_init_hyp(struct kvm_iommu_ops *hyp_ops) { @@ -51,6 +52,7 @@ int kvm_iommu_init_driver(void) return iommu_driver->init_driver(); } +EXPORT_SYMBOL(kvm_iommu_init_driver); void kvm_iommu_remove_driver(void) { diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index e8dce9673945..adecade32903 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -1140,3 +1140,4 @@ int __pkvm_topup_hyp_alloc_mgt_gfp(unsigned long id, unsigned long nr_pages, return ret; } +EXPORT_SYMBOL(__pkvm_topup_hyp_alloc_mgt_gfp); diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c index f85ad155b418..850332182024 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c @@ -45,6 +45,18 @@ struct kvm_arm_smmu_domain { #define to_kvm_smmu_domain(_domain) \ container_of(_domain, struct kvm_arm_smmu_domain, domain) +#ifdef MODULE +static unsigned long pkvm_module_token; + +#define ksym_ref_addr_nvhe(x) \ + ((typeof(kvm_nvhe_sym(x)) *)(pkvm_el2_mod_va(&kvm_nvhe_sym(x), pkvm_module_token))) + +int kvm_nvhe_sym(smmu_init_hyp_module)(const struct pkvm_module_ops *ops); +#else +#define ksym_ref_addr_nvhe(x) \ + ((typeof(kvm_nvhe_sym(x)) *)(kern_hyp_va(lm_alias(&kvm_nvhe_sym(x))))) +#endif + static size_t kvm_arm_smmu_cur; static size_t kvm_arm_smmu_count; static struct hyp_arm_smmu_v3_device *kvm_arm_smmu_array; @@ -959,6 +971,15 @@ static int kvm_arm_smmu_v3_init_drv(void) goto err_free; } +#ifdef MODULE + ret = pkvm_load_el2_module(kvm_nvhe_sym(smmu_init_hyp_module), + &pkvm_module_token); + + if (ret) { + pr_err("Failed to load SMMUv3 IOMMU EL2 module: %d\n", ret); + return ret; + } +#endif /* * These variables are stored in the nVHE image, and won't be accessible * after KVM initialization. Ownership of kvm_arm_smmu_array will be @@ -967,7 +988,7 @@ static int kvm_arm_smmu_v3_init_drv(void) kvm_hyp_arm_smmu_v3_smmus = kvm_arm_smmu_array; kvm_hyp_arm_smmu_v3_count = kvm_arm_smmu_count; - ret = kvm_iommu_init_hyp(kern_hyp_va(lm_alias(&kvm_nvhe_sym(smmu_ops)))); + ret = kvm_iommu_init_hyp(ksym_ref_addr_nvhe(smmu_ops)); if (ret) return ret; return kvm_arm_smmu_v3_post_init(); @@ -995,5 +1016,15 @@ static int kvm_arm_smmu_v3_register(void) return kvm_iommu_register_driver(&kvm_smmu_v3_ops); }; +/* + * Register must be run before de-privliage before kvm_iommu_init_driver + * for module case, it should be loaded using pKVM early loading which + * loads it before this point. + * For builtin drivers we use core_initcall + */ +#ifdef MODULE +module_init(kvm_arm_smmu_v3_register); +#else core_initcall(kvm_arm_smmu_v3_register); +#endif MODULE_LICENSE("GPL v2");