From 47dfb4dc1f2ab40ce3d836c7cd2ac2186dde839d Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Fri, 3 Feb 2023 13:27:16 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Allow tweaking HCR_EL2 from modules pKVM modules may need to enable additional traps on top of what pKVM already enables. To allow this use-case, expose a function allowing to manipulate HCR_EL2 on the current CPU. This configuration will be persistent across power management cycles and such as it is propagated all the way to the init params per-cpu struct. Bug: 245034629 Change-Id: I21d596bd1d01f4edc48a188cc3c2eb78dc9a4444 Signed-off-by: Quentin Perret --- arch/arm64/include/asm/kvm_pkvm_module.h | 1 + arch/arm64/kvm/hyp/nvhe/modules.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h index d34ce49042bd..afe8001b9ded 100644 --- a/arch/arm64/include/asm/kvm_pkvm_module.h +++ b/arch/arm64/include/asm/kvm_pkvm_module.h @@ -30,6 +30,7 @@ struct pkvm_module_ops { 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); + void (*update_hcr_el2)(unsigned long set_mask, unsigned long clear_mask); int (*register_host_perm_fault_handler)(int (*cb)(struct kvm_cpu_context *ctxt, u64 esr, u64 addr)); int (*host_stage2_mod_prot)(u64 pfn, enum kvm_pgtable_prot prot); int (*host_stage2_get_leaf)(phys_addr_t phys, kvm_pte_t *ptep, u32 *level); diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c index e3d73fab4e24..5aa6c22efe89 100644 --- a/arch/arm64/kvm/hyp/nvhe/modules.c +++ b/arch/arm64/kvm/hyp/nvhe/modules.c @@ -17,6 +17,16 @@ static void __kvm_flush_dcache_to_poc(void *addr, size_t size) kvm_flush_dcache_to_poc((unsigned long)addr, (unsigned long)size); } +static void __update_hcr_el2(unsigned long set_mask, unsigned long clear_mask) +{ + struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params); + + params->hcr_el2 |= set_mask; + params->hcr_el2 &= ~clear_mask; + __kvm_flush_dcache_to_poc(params, sizeof(*params)); + write_sysreg(params->hcr_el2, hcr_el2); +} + static atomic_t early_lm_pages; static void *__pkvm_linear_map_early(phys_addr_t phys, size_t size, enum kvm_pgtable_prot prot) { @@ -78,6 +88,7 @@ const struct pkvm_module_ops module_ops = { .linear_map_early = __pkvm_linear_map_early, .linear_unmap_early = __pkvm_linear_unmap_early, .flush_dcache_to_poc = __kvm_flush_dcache_to_poc, + .update_hcr_el2 = __update_hcr_el2, .register_host_perm_fault_handler = hyp_register_host_perm_fault_handler, .host_stage2_mod_prot = module_change_host_page_prot, .host_stage2_get_leaf = host_stage2_get_leaf,