diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 110e14397a9a..78a19ce7a811 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -221,6 +221,7 @@ struct kvm_nvhe_init_params { unsigned long stack_pa; phys_addr_t pgd_pa; unsigned long hcr_el2; + unsigned long hfgwtr_el2; unsigned long vttbr; unsigned long vtcr; }; diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h index afe8001b9ded..28c32711c1f3 100644 --- a/arch/arm64/include/asm/kvm_pkvm_module.h +++ b/arch/arm64/include/asm/kvm_pkvm_module.h @@ -31,6 +31,7 @@ struct pkvm_module_ops { 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); + void (*update_hfgwtr_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/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 1197e7679882..57191e3d2a3e 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -128,6 +128,7 @@ int main(void) DEFINE(NVHE_INIT_STACK_HYP_VA, offsetof(struct kvm_nvhe_init_params, stack_hyp_va)); DEFINE(NVHE_INIT_PGD_PA, offsetof(struct kvm_nvhe_init_params, pgd_pa)); DEFINE(NVHE_INIT_HCR_EL2, offsetof(struct kvm_nvhe_init_params, hcr_el2)); + DEFINE(NVHE_INIT_HFGWTR_EL2, offsetof(struct kvm_nvhe_init_params, hfgwtr_el2)); DEFINE(NVHE_INIT_VTTBR, offsetof(struct kvm_nvhe_init_params, vttbr)); DEFINE(NVHE_INIT_VTCR, offsetof(struct kvm_nvhe_init_params, vtcr)); #endif diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S index a6d67c2bb5ae..e7b375ec6460 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-init.S +++ b/arch/arm64/kvm/hyp/nvhe/hyp-init.S @@ -95,6 +95,9 @@ SYM_CODE_START_LOCAL(___kvm_hyp_init) ldr x1, [x0, #NVHE_INIT_HCR_EL2] msr hcr_el2, x1 + ldr x1, [x0, #NVHE_INIT_HFGWTR_EL2] + msr_s SYS_HFGWTR_EL2, x1 + ldr x1, [x0, #NVHE_INIT_VTTBR] msr vttbr_el2, x1 diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c index 5aa6c22efe89..138e0d68e95a 100644 --- a/arch/arm64/kvm/hyp/nvhe/modules.c +++ b/arch/arm64/kvm/hyp/nvhe/modules.c @@ -27,6 +27,16 @@ static void __update_hcr_el2(unsigned long set_mask, unsigned long clear_mask) write_sysreg(params->hcr_el2, hcr_el2); } +static void __update_hfgwtr_el2(unsigned long set_mask, unsigned long clear_mask) +{ + struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params); + + params->hfgwtr_el2 |= set_mask; + params->hfgwtr_el2 &= ~clear_mask; + __kvm_flush_dcache_to_poc(params, sizeof(*params)); + write_sysreg_s(params->hfgwtr_el2, SYS_HFGWTR_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) { @@ -89,6 +99,7 @@ const struct pkvm_module_ops module_ops = { .linear_unmap_early = __pkvm_linear_unmap_early, .flush_dcache_to_poc = __kvm_flush_dcache_to_poc, .update_hcr_el2 = __update_hcr_el2, + .update_hfgwtr_el2 = __update_hfgwtr_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,