From 27448ab5655bf129c5bc7e0448e4e7f57f5d7c47 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 7 Jul 2022 15:49:01 +0100 Subject: [PATCH] Revert "ANDROID: KVM: arm64: Remove unused IOMMU hooks, kvm_iommu_ops" This reverts commit 6122181d638aafdabe2fedc99685bd70b4457783. Bug: 233587962 Signed-off-by: Will Deacon Change-Id: I2978dfcba76e8b4e0a3cf7b6bc450b05123ede3e --- arch/arm64/include/asm/kvm_host.h | 4 ++++ arch/arm64/include/asm/kvm_hyp.h | 3 ++- arch/arm64/kvm/arm.c | 15 ++++++++++++--- arch/arm64/kvm/hyp/include/nvhe/iommu.h | 14 ++++++++++++++ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 7 ++++++- arch/arm64/kvm/hyp/nvhe/setup.c | 23 ++++++++++++++++++++++- 6 files changed, 60 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index baa5b35b0e33..a8ea58a4dc10 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -375,6 +375,10 @@ extern s64 kvm_nvhe_sym(hyp_physvirt_offset); extern u64 kvm_nvhe_sym(hyp_cpu_logical_map)[NR_CPUS]; #define hyp_cpu_logical_map CHOOSE_NVHE_SYM(hyp_cpu_logical_map) +enum kvm_iommu_driver { + KVM_IOMMU_DRIVER_NONE, +}; + enum pkvm_iommu_driver_id { PKVM_IOMMU_DRIVER_S2MPU, PKVM_IOMMU_NR_DRIVERS, diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index dc9c66f3c94c..2f99074111aa 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -110,7 +110,8 @@ void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr, void __pkvm_init_switch_pgd(phys_addr_t phys, unsigned long size, phys_addr_t pgd, void *sp, void *cont_fn); int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus, - unsigned long *per_cpu_base, u32 hyp_va_bits); + unsigned long *per_cpu_base, u32 hyp_va_bits, + enum kvm_iommu_driver iommu_driver); void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt); #endif diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 1341bcd0d278..f7e33e8d60a8 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1902,6 +1902,11 @@ static bool init_psci_relay(void) return true; } +static int init_stage2_iommu(void) +{ + return KVM_IOMMU_DRIVER_NONE; +} + static int init_subsystems(void) { int err = 0; @@ -1961,7 +1966,7 @@ static void teardown_hyp_mode(void) } } -static int do_pkvm_init(u32 hyp_va_bits) +static int do_pkvm_init(u32 hyp_va_bits, enum kvm_iommu_driver iommu_driver) { void *per_cpu_base = kvm_ksym_ref(kvm_arm_hyp_percpu_base); int ret; @@ -1970,7 +1975,7 @@ static int do_pkvm_init(u32 hyp_va_bits) cpu_hyp_init_context(); ret = kvm_call_hyp_nvhe(__pkvm_init, hyp_mem_base, hyp_mem_size, num_possible_cpus(), kern_hyp_va(per_cpu_base), - hyp_va_bits); + hyp_va_bits, iommu_driver); cpu_hyp_init_features(); /* @@ -2002,7 +2007,11 @@ static int kvm_hyp_init_protection(u32 hyp_va_bits) if (ret) return ret; - ret = do_pkvm_init(hyp_va_bits); + ret = init_stage2_iommu(); + if (ret < 0) + return ret; + + ret = do_pkvm_init(hyp_va_bits, (enum kvm_iommu_driver)ret); if (ret) return ret; diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h index 2367fe153ad3..c8907c911673 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/iommu.h +++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h @@ -82,4 +82,18 @@ void pkvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end, extern const struct pkvm_iommu_ops pkvm_s2mpu_ops; +struct kvm_iommu_ops { + int (*init)(void); + bool (*host_smc_handler)(struct kvm_cpu_context *host_ctxt); + bool (*host_mmio_dabt_handler)(struct kvm_cpu_context *host_ctxt, + phys_addr_t fault_pa, unsigned int len, + bool is_write, int rd); + void (*host_stage2_set_owner)(phys_addr_t addr, size_t size, pkvm_id owner_id); + int (*host_stage2_adjust_mmio_range)(phys_addr_t addr, phys_addr_t *start, + phys_addr_t *end); +}; + +extern struct kvm_iommu_ops kvm_iommu_ops; +extern const struct kvm_iommu_ops kvm_s2mpu_ops; + #endif /* __ARM64_KVM_NVHE_IOMMU_H__ */ diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index fae3dd83bbdf..5d7a3654af46 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -47,6 +47,8 @@ static DEFINE_PER_CPU(struct pkvm_loaded_state, loaded_state); DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); +struct kvm_iommu_ops kvm_iommu_ops; + void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt); typedef void (*shadow_entry_exit_handler_fn)(struct kvm_vcpu *, struct kvm_vcpu *); @@ -906,6 +908,7 @@ static void handle___pkvm_init(struct kvm_cpu_context *host_ctxt) DECLARE_REG(unsigned long, nr_cpus, host_ctxt, 3); DECLARE_REG(unsigned long *, per_cpu_base, host_ctxt, 4); DECLARE_REG(u32, hyp_va_bits, host_ctxt, 5); + DECLARE_REG(enum kvm_iommu_driver, iommu_driver, host_ctxt, 6); /* * __pkvm_init() will return only if an error occurred, otherwise it @@ -913,7 +916,7 @@ static void handle___pkvm_init(struct kvm_cpu_context *host_ctxt) * with the host context directly. */ cpu_reg(host_ctxt, 1) = __pkvm_init(phys, size, nr_cpus, per_cpu_base, - hyp_va_bits); + hyp_va_bits, iommu_driver); } static void handle___pkvm_cpu_set_vector(struct kvm_cpu_context *host_ctxt) @@ -1089,6 +1092,8 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt) bool handled; handled = kvm_host_psci_handler(host_ctxt); + if (!handled && kvm_iommu_ops.host_smc_handler) + handled = kvm_iommu_ops.host_smc_handler(host_ctxt); if (!handled) handled = kvm_host_ffa_handler(host_ctxt); if (!handled) diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c index 18638652f06d..be2bc8170877 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -280,6 +280,16 @@ static int fix_hyp_pgtable_refcnt(void) &walker); } +static int select_iommu_ops(enum kvm_iommu_driver driver) +{ + switch (driver) { + case KVM_IOMMU_DRIVER_NONE: + return 0; + } + + return -EINVAL; +} + void __noreturn __pkvm_init_finalise(void) { struct kvm_host_data *host_data = this_cpu_ptr(&kvm_host_data); @@ -309,6 +319,12 @@ void __noreturn __pkvm_init_finalise(void) }; pkvm_pgtable.mm_ops = &pkvm_pgtable_mm_ops; + if (kvm_iommu_ops.init) { + ret = kvm_iommu_ops.init(); + if (ret) + goto out; + } + ret = fix_host_ownership(); if (ret) goto out; @@ -337,7 +353,8 @@ out: } int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus, - unsigned long *per_cpu_base, u32 hyp_va_bits) + unsigned long *per_cpu_base, u32 hyp_va_bits, + enum kvm_iommu_driver iommu_driver) { struct kvm_nvhe_init_params *params; void *virt = hyp_phys_to_virt(phys); @@ -360,6 +377,10 @@ int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus, if (ret) return ret; + ret = select_iommu_ops(iommu_driver); + if (ret) + return ret; + update_nvhe_init_params(); /* Jump in the idmap page to switch to the new page-tables */