git: 32111003c308 - main - arm64/vmm: save and restore HCRX_EL2 register
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 04 Feb 2025 12:26:34 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=32111003c3087389cc5e50949ee3a26c4e7b26c4 commit 32111003c3087389cc5e50949ee3a26c4e7b26c4 Author: Harry Moulton <harry.moulton@arm.com> AuthorDate: 2025-01-23 12:40:05 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2025-02-04 11:24:41 +0000 arm64/vmm: save and restore HCRX_EL2 register With the addition of the Extended Hypervisor Configuration Register (HCRX_EL2), this change ensures that it is both set to 0 before entering a vm, and that it is properly saved/restored. Reviewed by: andrew Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D48584 Signed-off-by: Harry Moulton <harry.moulton@arm.com> --- sys/arm64/vmm/arm64.h | 1 + sys/arm64/vmm/vmm_hyp.c | 15 +++++++++++++++ sys/arm64/vmm/vmm_reset.c | 2 ++ 3 files changed, 18 insertions(+) diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h index 8cfe77dcde6f..6a0c4c78e568 100644 --- a/sys/arm64/vmm/arm64.h +++ b/sys/arm64/vmm/arm64.h @@ -94,6 +94,7 @@ struct hypctx { /* EL2 control registers */ uint64_t cptr_el2; /* Architectural Feature Trap Register */ uint64_t hcr_el2; /* Hypervisor Configuration Register */ + uint64_t hcrx_el2; /* Extended Hypervisor Configuration Register */ uint64_t mdcr_el2; /* Monitor Debug Configuration Register */ uint64_t vpidr_el2; /* Virtualization Processor ID Register */ uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register */ diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c index bd119c80139b..d61885c15871 100644 --- a/sys/arm64/vmm/vmm_hyp.c +++ b/sys/arm64/vmm/vmm_hyp.c @@ -259,6 +259,14 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest) hypctx->hcr_el2 = READ_SPECIALREG(hcr_el2); hypctx->vpidr_el2 = READ_SPECIALREG(vpidr_el2); hypctx->vmpidr_el2 = READ_SPECIALREG(vmpidr_el2); + +#ifndef VMM_VHE + /* hcrx_el2 depends on feat_hcx */ + uint64_t mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); + if (ID_AA64MMFR1_HCX_VAL(mmfr1) >> ID_AA64MMFR1_HCX_SHIFT) { + hypctx->hcrx_el2 = READ_SPECIALREG(MRS_REG_ALT_NAME(HCRX_EL2)); + } +#endif } static void @@ -268,6 +276,13 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest) /* Restore the special registers */ WRITE_SPECIALREG(hcr_el2, hypctx->hcr_el2); + + if (guest_or_nonvhe(guest)) { + uint64_t mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); + if (ID_AA64MMFR1_HCX_VAL(mmfr1) >> ID_AA64MMFR1_HCX_SHIFT) { + WRITE_SPECIALREG(MRS_REG_ALT_NAME(HCRX_EL2), hypctx->hcrx_el2); + } + } isb(); WRITE_SPECIALREG(sp_el0, hypctx->sp_el0); diff --git a/sys/arm64/vmm/vmm_reset.c b/sys/arm64/vmm/vmm_reset.c index 8ccb83e7a0ea..79d022cf33e8 100644 --- a/sys/arm64/vmm/vmm_reset.c +++ b/sys/arm64/vmm/vmm_reset.c @@ -140,6 +140,8 @@ reset_vm_el2_regs(void *vcpu) el2ctx->hcr_el2 |= HCR_E2H; } + /* Set the Extended Hypervisor Configuration Register */ + el2ctx->hcrx_el2 = 0; /* TODO: Trap all extensions we don't support */ el2ctx->mdcr_el2 = 0; /* PMCR_EL0.N is read from MDCR_EL2.HPMN */