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 */