Date: Mon, 06 Jul 2026 15:24:39 +0000 From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Kajetan Puchalski <kajetan.puchalski@arm.com> Subject: git: dd08cb0c8d6e - main - arm64/vmm: Use the VNCR_EL2 memory page to store guest registers Message-ID: <6a4bc8b7.1e2c2.1d541648@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=dd08cb0c8d6e1737d2dddf978a0291f09911a715 commit dd08cb0c8d6e1737d2dddf978a0291f09911a715 Author: Kajetan Puchalski <kajetan.puchalski@arm.com> AuthorDate: 2026-07-06 14:16:34 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2026-07-06 15:18:29 +0000 arm64/vmm: Use the VNCR_EL2 memory page to store guest registers Wherever possible, move the storage space for guest register values from the hypctx struct into a preallocated memory page matching the layout of the page pointed to by VNCR_EL2. This will streamline implementing support for nested virtualization, but the implementation itself is not reliant on the presence of nested virtualization architecture features. Signed-off-by: Kajetan Puchalski <kajetan.puchalski@arm.com> Reviewed by: andrew Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D56551 --- sys/arm64/include/hypervisor.h | 2 + sys/arm64/vmm/arm64.h | 168 +++++++++++++++++++++++++++++++++++------ sys/arm64/vmm/vmm_arm64.c | 78 ++++++++++++------- sys/arm64/vmm/vmm_hyp.c | 111 +++++++++++++++++---------- sys/arm64/vmm/vmm_nvhe.c | 3 + sys/arm64/vmm/vmm_reset.c | 22 +----- 6 files changed, 277 insertions(+), 107 deletions(-) diff --git a/sys/arm64/include/hypervisor.h b/sys/arm64/include/hypervisor.h index bc5b6f4344ee..0b6492785a0a 100644 --- a/sys/arm64/include/hypervisor.h +++ b/sys/arm64/include/hypervisor.h @@ -2185,6 +2185,8 @@ /* Assumed to be 0 by locore.S */ #define VTTBR_HOST 0x0000000000000000 +/* Size of the memory page pointed to by VNCR_EL2 */ +#define VNCR_PAGE_SIZE 4096 /* * Memory offsets of registers redirected to memory by HCR_EL2.NV2 * relative to the base address stored in VNCR_EL2. diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h index 6062d1c07ae4..4db26709f21e 100644 --- a/sys/arm64/vmm/arm64.h +++ b/sys/arm64/vmm/arm64.h @@ -39,6 +39,109 @@ struct vgic_v3; struct vgic_v3_cpu; +/* + Encode the index of a given register within VNCR into the enum value. + We move the indices up by VNCR_START to not interfere with values for + non-VNCR registers. +*/ +#define VNCR_REG(reg) reg = (VNCR_START + VNCR_##reg / 8) +/* Retrieve the VNCR offset from the enum value */ +#define REG_VNCR_OFFSET(val) ((val - VNCR_START) * 8) + +enum hypctx_sysreg { + /* VNCR Registers */ + VNCR_START, + + VNCR_REG(VTTBR_EL2), + VNCR_REG(VSTTBR_EL2), + VNCR_REG(VTCR_EL2), + VNCR_REG(VSTCR_EL2), + VNCR_REG(VMPIDR_EL2), /* Virtualization Multiprocessor ID Register */ + VNCR_REG(CNTVOFF_EL2), + VNCR_REG(HCR_EL2), /* Hypervisor Configuration Register */ + VNCR_REG(HSTR_EL2), + VNCR_REG(VPIDR_EL2), /* Virtualization Processor ID Register */ + VNCR_REG(TPIDR_EL2), + VNCR_REG(HCRX_EL2), /* Extended Hypervisor Configuration Register */ + VNCR_REG(VNCR_EL2), + VNCR_REG(CPACR_EL1), /* Architectural Feature Access Control Register */ + VNCR_REG(CONTEXTIDR_EL1), /* Current Process Identifier */ + VNCR_REG(SCTLR_EL1), /* System Control Register */ + VNCR_REG(ACTLR_EL1), /* Auxiliary Control Register */ + VNCR_REG(TCR_EL1), /* Translation Control Register */ + VNCR_REG(AFSR0_EL1), /* Auxiliary Fault Status Register 0 */ + VNCR_REG(AFSR1_EL1), /* Auxiliary Fault Status Register 1 */ + VNCR_REG(ESR_EL1), /* Exception Syndrome Register */ + VNCR_REG(MAIR_EL1), /* Memory Attribute Indirection Register */ + VNCR_REG(AMAIR_EL1), /* Auxiliary Memory Attribute Indirection Register */ + VNCR_REG(MDSCR_EL1), /* Monitor Debug System Control Register */ + VNCR_REG(SPSR_EL1), /* Saved Program Status Register */ + VNCR_REG(CNTV_CVAL_EL0), + VNCR_REG(CNTV_CTL_EL0), + VNCR_REG(CNTP_CVAL_EL0), + VNCR_REG(CNTP_CTL_EL0), + VNCR_REG(SCXTNUM_EL1), + VNCR_REG(TFSR_EL1), + VNCR_REG(HDFGRTR2_EL2), + VNCR_REG(CNTPOFF_EL2), + VNCR_REG(HDFGWTR2_EL2), + VNCR_REG(HFGRTR_EL2), + VNCR_REG(HFGWTR_EL2), + VNCR_REG(HFGITR_EL2), + VNCR_REG(HDFGRTR_EL2), + VNCR_REG(HDFGWTR_EL2), + VNCR_REG(ZCR_EL1), + VNCR_REG(HAFGRTR_EL2), + VNCR_REG(SMCR_EL1), + VNCR_REG(SMPRIMAP_EL2), + VNCR_REG(TTBR0_EL1), /* Translation Table Base Register 0 */ + VNCR_REG(TTBR1_EL1), /* Translation Table Base Register 1 */ + VNCR_REG(FAR_EL1), /* Fault Address Register */ + VNCR_REG(ELR_EL1), /* Exception Link Register */ + VNCR_REG(SP_EL1), + VNCR_REG(VBAR_EL1), /* Vector Base Address Register */ + VNCR_REG(TCR2_EL1), /* Translation Control Register 2 */ + VNCR_REG(SCTLR2_EL1), + VNCR_REG(MAIR2_EL1), + VNCR_REG(AMAIR2_EL1), + VNCR_REG(PIRE0_EL1), + VNCR_REG(PIRE0_EL2), + VNCR_REG(PIR_EL1), + VNCR_REG(POR_EL1), + VNCR_REG(S2PIR_EL2), + VNCR_REG(S2POR_EL1), + VNCR_REG(HFGRTR2_EL2), + VNCR_REG(HFGWTR2_EL2), + VNCR_REG(PFAR_EL1), + VNCR_REG(HFGITR2_EL2), + VNCR_REG(SCTLRMASK_EL1), + VNCR_REG(CPACRMASK_EL1), + VNCR_REG(SCTLR2MASK_EL1), + VNCR_REG(TCRMASK_EL1), + VNCR_REG(TCR2MASK_EL1), + VNCR_REG(ACTLRMASK_EL1), + VNCR_REG(ICH_HCR_EL2), + VNCR_REG(ICH_VMCR_EL2), + VNCR_REG(VDISR_EL2), + VNCR_REG(VSESR_EL2), + VNCR_REG(PMBLIMITR_EL1), + VNCR_REG(PMBPTR_EL1), + VNCR_REG(PMBSR_EL1), + VNCR_REG(PMSCR_EL1), + VNCR_REG(PMSEVFR_EL1), + VNCR_REG(PMSICR_EL1), + VNCR_REG(PMSIRR_EL1), + VNCR_REG(PMSLATFR_EL1), + VNCR_REG(PMSNEVFR_EL1), + VNCR_REG(PMSDSFR_EL1), + VNCR_REG(TRFCR_EL1), + VNCR_REG(TRCITECR_EL1), + VNCR_REG(GCSPR_EL1), + VNCR_REG(GCSCR_EL1), + VNCR_REG(BRBCR_EL1), + VNCR_REG(SPMACCESSR_EL1), +}; + /* * Per-vCPU hypervisor state. */ @@ -46,34 +149,15 @@ struct hypctx { struct trapframe tf; /* - * EL1 control registers. + * EL1 & EL0 registers. */ - uint64_t elr_el1; /* Exception Link Register */ uint64_t sp_el0; /* Stack pointer */ uint64_t tpidr_el0; /* EL0 Software ID Register */ uint64_t tpidrro_el0; /* Read-only Thread ID Register */ uint64_t tpidr_el1; /* EL1 Software ID Register */ - uint64_t vbar_el1; /* Vector Base Address Register */ - - uint64_t actlr_el1; /* Auxiliary Control Register */ - uint64_t afsr0_el1; /* Auxiliary Fault Status Register 0 */ - uint64_t afsr1_el1; /* Auxiliary Fault Status Register 1 */ - uint64_t amair_el1; /* Auxiliary Memory Attribute Indirection Register */ - uint64_t contextidr_el1; /* Current Process Identifier */ - uint64_t cpacr_el1; /* Architectural Feature Access Control Register */ uint64_t csselr_el1; /* Cache Size Selection Register */ - uint64_t esr_el1; /* Exception Syndrome Register */ - uint64_t far_el1; /* Fault Address Register */ - uint64_t mair_el1; /* Memory Attribute Indirection Register */ uint64_t mdccint_el1; /* Monitor DCC Interrupt Enable Register */ - uint64_t mdscr_el1; /* Monitor Debug System Control Register */ uint64_t par_el1; /* Physical Address Register */ - uint64_t sctlr_el1; /* System Control Register */ - uint64_t tcr_el1; /* Translation Control Register */ - uint64_t tcr2_el1; /* Translation Control Register 2 */ - uint64_t ttbr0_el1; /* Translation Table Base Register 0 */ - uint64_t ttbr1_el1; /* Translation Table Base Register 1 */ - uint64_t spsr_el1; /* Saved Program Status Register */ uint64_t pmcr_el0; /* Performance Monitors Control Register */ uint64_t pmccntr_el0; @@ -100,6 +184,8 @@ struct hypctx { uint64_t mdcr_el2; /* Monitor Debug Configuration Register */ uint64_t vpidr_el2; /* Virtualization Processor ID Register */ uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register */ + /* On systems without NV2 this still points to the register storage memory page */ + uint64_t vncr_el2; /* Virtual Nested Control Register */ /* FEAT_FGT registers */ /*uint64_t hafgrtr_el2; *//* For FEAT_AMUv1 (not supported) */ @@ -116,7 +202,6 @@ struct hypctx { uint64_t hfgrtr2_el2; uint64_t hfgwtr2_el2; - uint64_t el2_addr; /* The address of this in el2 space */ struct hyp *hyp; struct vcpu *vcpu; struct { @@ -136,8 +221,49 @@ struct hypctx { struct vgic_v3_cpu *vgic_cpu; bool has_exception; bool dbg_oslock; + + /* + * Memory page pointed at by VNCR_EL2. Contains storage for registers + * the accesses to which are redirected to memory by FEAT_NV2. + * NOTE: The storage is still used even if FEAT_NV2 is not present. + */ + void *vncr_regs; + /* Memory page used to store the host's values of VNCR registers. */ + void *host_vncr_regs; + + uint64_t el2_addr; /* The address of this in el2 space */ + uint64_t el2_vncr_addr; /* The address of vncr_regs in el2 space */ + uint64_t el2_host_vncr_addr; }; +/* For non-VHE vmm_hyp.c, this will already be defined in vmm_nvhe.c */ +#ifndef __hypctx_vncr_sysreg +#define __hypctx_vncr_sysreg(hypctx, reg) \ + ((uint64_t *)((char *)hypctx->vncr_regs + REG_VNCR_OFFSET(reg))) +#endif + +static inline uint64_t * +hypctx_sys_reg(struct hypctx *hypctx, int reg /* enum hypctx_sysreg */) +{ + if (reg > VNCR_START) + return (__hypctx_vncr_sysreg(hypctx, reg)); + /* TODO: uniform handling for non-VNCR registers */ + return (NULL); +} + +static inline void +hypctx_write_sys_reg(struct hypctx *hypctx, enum hypctx_sysreg reg, + uint64_t val) +{ + *hypctx_sys_reg(hypctx, reg) = val; +} + +static inline uint64_t +hypctx_read_sys_reg(struct hypctx *hypctx, enum hypctx_sysreg reg) +{ + return (*hypctx_sys_reg(hypctx, reg)); +} + struct hyp { struct vm *vm; struct vtimer vtimer; diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c index 8fe0bf62bf8b..3615d2da66cc 100644 --- a/sys/arm64/vmm/vmm_arm64.c +++ b/sys/arm64/vmm/vmm_arm64.c @@ -490,7 +490,8 @@ el2_hyp_size(struct vm *vm) static vm_size_t el2_hypctx_size(void) { - return (round_page(sizeof(struct hypctx))); + /* Allocation for hypctx, one vncr page & one host state page */ + return (round_page(sizeof(struct hypctx) + 2 * VNCR_PAGE_SIZE)); } static vm_offset_t @@ -559,7 +560,17 @@ vmmops_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid) vm_size_t size; size = el2_hypctx_size(); + /* + * Allocation memory layout: + 0x0000 - 0x0fff <- struct hypctx + 0x1000 - 0x1fff <- VNCR memory page + 0x2000 - 0x2fff <- host_ctx memory page + */ hypctx = malloc_aligned(size, PAGE_SIZE, M_HYP, M_WAITOK | M_ZERO); + _Static_assert(sizeof(struct hypctx) < VNCR_PAGE_SIZE, + "struct hypctx exceeds VNCR_PAGE_SIZE"); + hypctx->vncr_regs = (void *)((char *)hypctx + VNCR_PAGE_SIZE); + hypctx->host_vncr_regs = (void *)((char *)hypctx + 2 * VNCR_PAGE_SIZE); KASSERT(vcpuid >= 0 && vcpuid < vm_get_maxcpus(hyp->vm), ("%s: Invalid vcpuid %d", __func__, vcpuid)); @@ -574,9 +585,12 @@ vmmops_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid) vtimer_cpuinit(hypctx); vgic_cpuinit(hypctx); - if (!in_vhe()) + if (!in_vhe()) { hypctx->el2_addr = el2_map_enter((vm_offset_t)hypctx, size, VM_PROT_READ | VM_PROT_WRITE); + hypctx->el2_vncr_addr = hypctx->el2_addr + VNCR_PAGE_SIZE; + hypctx->el2_host_vncr_addr = hypctx->el2_addr + 2 * VNCR_PAGE_SIZE; + } return (hypctx); } @@ -639,12 +653,14 @@ arm64_gen_inst_emul_data(struct hypctx *hypctx, uint32_t esr_iss, vie->reg = reg_num; paging = &vme_ret->u.inst_emul.paging; - paging->ttbr0_addr = hypctx->ttbr0_el1 & ~(TTBR_ASID_MASK | TTBR_CnP); - paging->ttbr1_addr = hypctx->ttbr1_el1 & ~(TTBR_ASID_MASK | TTBR_CnP); - paging->tcr_el1 = hypctx->tcr_el1; - paging->tcr2_el1 = hypctx->tcr2_el1; + paging->ttbr0_addr = hypctx_read_sys_reg(hypctx, TTBR0_EL1) & + ~(TTBR_ASID_MASK | TTBR_CnP); + paging->ttbr1_addr = hypctx_read_sys_reg(hypctx, TTBR1_EL1) & + ~(TTBR_ASID_MASK | TTBR_CnP); + paging->tcr_el1 = hypctx_read_sys_reg(hypctx, TCR_EL1); + paging->tcr2_el1 = hypctx_read_sys_reg(hypctx, TCR2_EL1); paging->flags = hypctx->tf.tf_spsr & (PSR_M_MASK | PSR_M_32); - if ((hypctx->sctlr_el1 & SCTLR_M) != 0) + if ((hypctx_read_sys_reg(hypctx, SCTLR_EL1) & SCTLR_M) != 0) paging->flags |= VM_GP_MMU_ENABLED; } @@ -1078,7 +1094,7 @@ fault: int vmmops_run(void *vcpui, register_t pc, pmap_t pmap, struct vm_eventinfo *evinfo) { - uint64_t excp_type; + uint64_t excp_type, vbar_el1; int handled; register_t daif; struct hyp *hyp; @@ -1097,36 +1113,41 @@ vmmops_run(void *vcpui, register_t pc, pmap_t pmap, struct vm_eventinfo *evinfo) for (;;) { if (hypctx->has_exception) { hypctx->has_exception = false; - hypctx->elr_el1 = hypctx->tf.tf_elr; + hypctx_write_sys_reg(hypctx, ELR_EL1, hypctx->tf.tf_elr); mode = hypctx->tf.tf_spsr & (PSR_M_MASK | PSR_M_32); + vbar_el1 = hypctx_read_sys_reg(hypctx, VBAR_EL1); if (mode == PSR_M_EL1t) { - hypctx->tf.tf_elr = hypctx->vbar_el1 + 0x0; + hypctx->tf.tf_elr = vbar_el1 + 0x0; } else if (mode == PSR_M_EL1h) { - hypctx->tf.tf_elr = hypctx->vbar_el1 + 0x200; + hypctx->tf.tf_elr = vbar_el1 + 0x200; } else if ((mode & PSR_M_32) == PSR_M_64) { /* 64-bit EL0 */ - hypctx->tf.tf_elr = hypctx->vbar_el1 + 0x400; + hypctx->tf.tf_elr = vbar_el1 + 0x400; } else { /* 32-bit EL0 */ - hypctx->tf.tf_elr = hypctx->vbar_el1 + 0x600; + hypctx->tf.tf_elr = vbar_el1 + 0x600; } /* Set the new spsr */ - hypctx->spsr_el1 = hypctx->tf.tf_spsr; + hypctx_write_sys_reg(hypctx, SPSR_EL1, hypctx->tf.tf_spsr); /* Set the new cpsr */ - hypctx->tf.tf_spsr = hypctx->spsr_el1 & PSR_FLAGS; + hypctx->tf.tf_spsr = hypctx_read_sys_reg(hypctx, + SPSR_EL1) & PSR_FLAGS; + hypctx->tf.tf_spsr |= PSR_DAIF | PSR_M_EL1h; /* * Update fields that may change on exeption entry * based on how sctlr_el1 is configured. */ - if ((hypctx->sctlr_el1 & SCTLR_SPAN) == 0) + if ((hypctx_read_sys_reg(hypctx, SCTLR_EL1) & + SCTLR_SPAN) == 0) hypctx->tf.tf_spsr |= PSR_PAN; - if ((hypctx->sctlr_el1 & SCTLR_DSSBS) == 0) + if ((hypctx_read_sys_reg(hypctx, SCTLR_EL1) & + SCTLR_DSSBS) == 0) hypctx->tf.tf_spsr &= ~PSR_SSBS; else hypctx->tf.tf_spsr |= PSR_SSBS; @@ -1259,15 +1280,15 @@ hypctx_regptr(struct hypctx *hypctx, int reg) case VM_REG_GUEST_PC: return (&hypctx->tf.tf_elr); case VM_REG_GUEST_SCTLR_EL1: - return (&hypctx->sctlr_el1); + return hypctx_sys_reg(hypctx, SCTLR_EL1); case VM_REG_GUEST_TTBR0_EL1: - return (&hypctx->ttbr0_el1); + return hypctx_sys_reg(hypctx, TTBR0_EL1); case VM_REG_GUEST_TTBR1_EL1: - return (&hypctx->ttbr1_el1); + return hypctx_sys_reg(hypctx, TTBR1_EL1); case VM_REG_GUEST_TCR_EL1: - return (&hypctx->tcr_el1); + return hypctx_sys_reg(hypctx, TCR_EL1); case VM_REG_GUEST_TCR2_EL1: - return (&hypctx->tcr2_el1); + return hypctx_sys_reg(hypctx, TCR2_EL1); case VM_REG_GUEST_MPIDR_EL1: return (&hypctx->vmpidr_el2); default: @@ -1327,8 +1348,8 @@ vmmops_exception(void *vcpui, uint64_t esr, uint64_t far) panic("%s: %s%d is running", __func__, vm_name(hypctx->hyp->vm), vcpu_vcpuid(hypctx->vcpu)); - hypctx->far_el1 = far; - hypctx->esr_el1 = esr; + hypctx_write_sys_reg(hypctx, FAR_EL1, far); + hypctx_write_sys_reg(hypctx, ESR_EL1, esr); hypctx->has_exception = true; return (0); @@ -1382,17 +1403,18 @@ vmmops_setcap(void *vcpui, int num, int val) if (val != 0) { hypctx->debug_spsr |= (hypctx->tf.tf_spsr & PSR_SS); - hypctx->debug_mdscr |= (hypctx->mdscr_el1 & MDSCR_SS); + hypctx->debug_mdscr |= + (hypctx_read_sys_reg(hypctx, MDSCR_EL1) & MDSCR_SS); hypctx->tf.tf_spsr |= PSR_SS; - hypctx->mdscr_el1 |= MDSCR_SS; + *hypctx_sys_reg(hypctx, MDSCR_EL1) |= MDSCR_SS; hypctx->mdcr_el2 |= MDCR_EL2_TDE; } else { hypctx->tf.tf_spsr &= ~PSR_SS; hypctx->tf.tf_spsr |= hypctx->debug_spsr; hypctx->debug_spsr &= ~PSR_SS; - hypctx->mdscr_el1 &= ~MDSCR_SS; - hypctx->mdscr_el1 |= hypctx->debug_mdscr; + *hypctx_sys_reg(hypctx, MDSCR_EL1) &= ~MDSCR_SS; + *hypctx_sys_reg(hypctx, MDSCR_EL1) |= hypctx->debug_mdscr; hypctx->debug_mdscr &= ~MDSCR_SS; if ((hypctx->setcaps & (1ul << VM_CAP_BRK_EXIT)) == 0) hypctx->mdcr_el2 &= ~MDCR_EL2_TDE; diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c index 27fdf18e4700..bde283a077c8 100644 --- a/sys/arm64/vmm/vmm_hyp.c +++ b/sys/arm64/vmm/vmm_hyp.c @@ -246,30 +246,44 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest, hypctx->tpidrro_el0 = READ_SPECIALREG(tpidrro_el0); hypctx->tpidr_el1 = READ_SPECIALREG(tpidr_el1); - hypctx->actlr_el1 = READ_SPECIALREG(actlr_el1); + hypctx_write_sys_reg(hypctx, ACTLR_EL1, READ_SPECIALREG(actlr_el1)); hypctx->csselr_el1 = READ_SPECIALREG(csselr_el1); hypctx->mdccint_el1 = READ_SPECIALREG(mdccint_el1); - hypctx->mdscr_el1 = READ_SPECIALREG(mdscr_el1); + hypctx_write_sys_reg(hypctx, MDSCR_EL1, READ_SPECIALREG(mdscr_el1)); if (guest_or_nonvhe(guest)) { - hypctx->elr_el1 = READ_SPECIALREG(EL1_REG(ELR)); - hypctx->vbar_el1 = READ_SPECIALREG(EL1_REG(VBAR)); - - hypctx->afsr0_el1 = READ_SPECIALREG(EL1_REG(AFSR0)); - hypctx->afsr1_el1 = READ_SPECIALREG(EL1_REG(AFSR1)); - hypctx->amair_el1 = READ_SPECIALREG(EL1_REG(AMAIR)); - hypctx->contextidr_el1 = READ_SPECIALREG(EL1_REG(CONTEXTIDR)); - hypctx->cpacr_el1 = READ_SPECIALREG(EL1_REG(CPACR)); - hypctx->esr_el1 = READ_SPECIALREG(EL1_REG(ESR)); - hypctx->far_el1 = READ_SPECIALREG(EL1_REG(FAR)); - hypctx->mair_el1 = READ_SPECIALREG(EL1_REG(MAIR)); - hypctx->sctlr_el1 = READ_SPECIALREG(EL1_REG(SCTLR)); - hypctx->spsr_el1 = READ_SPECIALREG(EL1_REG(SPSR)); - hypctx->tcr_el1 = READ_SPECIALREG(EL1_REG(TCR)); + hypctx_write_sys_reg(hypctx, ELR_EL1, + READ_SPECIALREG(EL1_REG(ELR))); + hypctx_write_sys_reg(hypctx, VBAR_EL1, + READ_SPECIALREG(EL1_REG(VBAR))); + hypctx_write_sys_reg(hypctx, AFSR0_EL1, + READ_SPECIALREG(EL1_REG(AFSR0))); + hypctx_write_sys_reg(hypctx, AFSR1_EL1, + READ_SPECIALREG(EL1_REG(AFSR1))); + hypctx_write_sys_reg(hypctx, AMAIR_EL1, + READ_SPECIALREG(EL1_REG(AMAIR))); + hypctx_write_sys_reg(hypctx, CONTEXTIDR_EL1, + READ_SPECIALREG(EL1_REG(CONTEXTIDR))); + hypctx_write_sys_reg(hypctx, CPACR_EL1, + READ_SPECIALREG(EL1_REG(CPACR))); + hypctx_write_sys_reg(hypctx, ESR_EL1, + READ_SPECIALREG(EL1_REG(ESR))); + hypctx_write_sys_reg(hypctx, FAR_EL1, + READ_SPECIALREG(EL1_REG(FAR))); + hypctx_write_sys_reg(hypctx, MAIR_EL1, + READ_SPECIALREG(EL1_REG(MAIR))); + hypctx_write_sys_reg(hypctx, SCTLR_EL1, + READ_SPECIALREG(EL1_REG(SCTLR))); + hypctx_write_sys_reg(hypctx, SPSR_EL1, + READ_SPECIALREG(EL1_REG(SPSR))); + hypctx_write_sys_reg(hypctx, TCR_EL1, + READ_SPECIALREG(EL1_REG(TCR))); /* TODO: Support when this is not res0 */ - hypctx->tcr2_el1 = 0; - hypctx->ttbr0_el1 = READ_SPECIALREG(EL1_REG(TTBR0)); - hypctx->ttbr1_el1 = READ_SPECIALREG(EL1_REG(TTBR1)); + hypctx_write_sys_reg(hypctx, TCR2_EL1, 0); + hypctx_write_sys_reg(hypctx, TTBR0_EL1, + READ_SPECIALREG(EL1_REG(TTBR0))); + hypctx_write_sys_reg(hypctx, TTBR1_EL1, + READ_SPECIALREG(EL1_REG(TTBR1))); } hypctx->cptr_el2 = READ_SPECIALREG(cptr_el2); @@ -320,30 +334,43 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest, WRITE_SPECIALREG(tpidrro_el0, hypctx->tpidrro_el0); WRITE_SPECIALREG(tpidr_el1, hypctx->tpidr_el1); - WRITE_SPECIALREG(actlr_el1, hypctx->actlr_el1); + WRITE_SPECIALREG(actlr_el1, hypctx_read_sys_reg(hypctx, ACTLR_EL1)); WRITE_SPECIALREG(csselr_el1, hypctx->csselr_el1); WRITE_SPECIALREG(mdccint_el1, hypctx->mdccint_el1); - WRITE_SPECIALREG(mdscr_el1, hypctx->mdscr_el1); + WRITE_SPECIALREG(mdscr_el1, hypctx_read_sys_reg(hypctx, MDSCR_EL1)); if (guest_or_nonvhe(guest)) { - WRITE_SPECIALREG(EL1_REG(ELR), hypctx->elr_el1); - WRITE_SPECIALREG(EL1_REG(VBAR), hypctx->vbar_el1); - - WRITE_SPECIALREG(EL1_REG(AFSR0), hypctx->afsr0_el1); - WRITE_SPECIALREG(EL1_REG(AFSR1), hypctx->afsr1_el1); - WRITE_SPECIALREG(EL1_REG(AMAIR), hypctx->amair_el1); - WRITE_SPECIALREG(EL1_REG(CONTEXTIDR), hypctx->contextidr_el1); - WRITE_SPECIALREG(EL1_REG(CPACR), hypctx->cpacr_el1); - WRITE_SPECIALREG(EL1_REG(ESR), hypctx->esr_el1); - WRITE_SPECIALREG(EL1_REG(FAR), hypctx->far_el1); - WRITE_SPECIALREG(EL1_REG(MAIR), hypctx->mair_el1); // - - WRITE_SPECIALREG(EL1_REG(SCTLR), hypctx->sctlr_el1); - WRITE_SPECIALREG(EL1_REG(SPSR), hypctx->spsr_el1); - WRITE_SPECIALREG(EL1_REG(TCR), hypctx->tcr_el1); + WRITE_SPECIALREG(EL1_REG(ELR), + hypctx_read_sys_reg(hypctx, ELR_EL1)); + WRITE_SPECIALREG(EL1_REG(VBAR), + hypctx_read_sys_reg(hypctx, VBAR_EL1)); + WRITE_SPECIALREG(EL1_REG(AFSR0), + hypctx_read_sys_reg(hypctx, AFSR0_EL1)); + WRITE_SPECIALREG(EL1_REG(AFSR1), + hypctx_read_sys_reg(hypctx, AFSR1_EL1)); + WRITE_SPECIALREG(EL1_REG(AMAIR), + hypctx_read_sys_reg(hypctx, AMAIR_EL1)); + WRITE_SPECIALREG(EL1_REG(CONTEXTIDR), + hypctx_read_sys_reg(hypctx, CONTEXTIDR_EL1)); + WRITE_SPECIALREG(EL1_REG(CPACR), + hypctx_read_sys_reg(hypctx, CPACR_EL1)); + WRITE_SPECIALREG(EL1_REG(ESR), + hypctx_read_sys_reg(hypctx, ESR_EL1)); + WRITE_SPECIALREG(EL1_REG(FAR), + hypctx_read_sys_reg(hypctx, FAR_EL1)); + WRITE_SPECIALREG(EL1_REG(MAIR), + hypctx_read_sys_reg(hypctx, MAIR_EL1)); + WRITE_SPECIALREG(EL1_REG(SCTLR), + hypctx_read_sys_reg(hypctx, SCTLR_EL1)); + WRITE_SPECIALREG(EL1_REG(SPSR), + hypctx_read_sys_reg(hypctx, SPSR_EL1)); + WRITE_SPECIALREG(EL1_REG(TCR), + hypctx_read_sys_reg(hypctx, TCR_EL1)); /* TODO: tcr2_el1 */ - WRITE_SPECIALREG(EL1_REG(TTBR0), hypctx->ttbr0_el1); - WRITE_SPECIALREG(EL1_REG(TTBR1), hypctx->ttbr1_el1); + WRITE_SPECIALREG(EL1_REG(TTBR0), + hypctx_read_sys_reg(hypctx, TTBR0_EL1)); + WRITE_SPECIALREG(EL1_REG(TTBR1), + hypctx_read_sys_reg(hypctx, TTBR1_EL1)); } if (guest) { @@ -542,7 +569,7 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest, #define LOAD_APR(x) \ case x: \ WRITE_SPECIALREG(ich_ap0r ## x ##_el2, \ - hypctx->vgic_v3_regs.ich_ap0r_el2[x]); \ + hypctx->vgic_v3_regs.ich_ap0r_el2[x]); \ WRITE_SPECIALREG(ich_ap1r ## x ##_el2, \ hypctx->vgic_v3_regs.ich_ap1r_el2[x]) LOAD_APR(3); @@ -568,6 +595,12 @@ vmm_hyp_call_guest(struct hyp *hyp, struct hypctx *hypctx) uint64_t s1e1r, hpfar_el2; bool ecv_poff, hpfar_valid; + /* Allows uniform implementation of guest and host register reloads */ + host_hypctx.vncr_regs = hypctx->host_vncr_regs; +#ifndef VMM_VHE + host_hypctx.el2_vncr_addr = hypctx->el2_host_vncr_addr; +#endif + ecv_poff = (hyp->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0; vmm_hyp_reg_store(&host_hypctx, NULL, false, ecv_poff); #ifndef VMM_VHE diff --git a/sys/arm64/vmm/vmm_nvhe.c b/sys/arm64/vmm/vmm_nvhe.c index 025b1308ce68..3d42fc1d5900 100644 --- a/sys/arm64/vmm/vmm_nvhe.c +++ b/sys/arm64/vmm/vmm_nvhe.c @@ -36,6 +36,9 @@ #define EL1_REG(reg) MRS_REG_ALT_NAME(reg ## _EL1) #define EL0_REG(reg) MRS_REG_ALT_NAME(reg ## _EL0) +#define __hypctx_vncr_sysreg(hypctx, reg) \ + ((uint64_t*)(hypctx->el2_vncr_addr + REG_VNCR_OFFSET(reg))) + #include "vmm_hyp.c" uint64_t vmm_hyp_enter(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, diff --git a/sys/arm64/vmm/vmm_reset.c b/sys/arm64/vmm/vmm_reset.c index fd3414ecd066..4966de5c8fa5 100644 --- a/sys/arm64/vmm/vmm_reset.c +++ b/sys/arm64/vmm/vmm_reset.c @@ -55,19 +55,8 @@ reset_vm_el01_regs(void *vcpu) set_arch_unknown(el2ctx->tf); - set_arch_unknown(el2ctx->actlr_el1); - set_arch_unknown(el2ctx->afsr0_el1); - set_arch_unknown(el2ctx->afsr1_el1); - set_arch_unknown(el2ctx->amair_el1); - set_arch_unknown(el2ctx->contextidr_el1); - set_arch_unknown(el2ctx->cpacr_el1); set_arch_unknown(el2ctx->csselr_el1); - set_arch_unknown(el2ctx->elr_el1); - set_arch_unknown(el2ctx->esr_el1); - set_arch_unknown(el2ctx->far_el1); - set_arch_unknown(el2ctx->mair_el1); set_arch_unknown(el2ctx->mdccint_el1); - set_arch_unknown(el2ctx->mdscr_el1); set_arch_unknown(el2ctx->par_el1); /* @@ -77,19 +66,14 @@ reset_vm_el01_regs(void *vcpu) * SCTLR_CP15BEN: memory barrier instruction enable from EL0; RAO/WI * ~SCTLR_I: instruction cache off */ - el2ctx->sctlr_el1 = SCTLR_RES1; - el2ctx->sctlr_el1 &= ~SCTLR_M & ~SCTLR_C & ~SCTLR_I; - el2ctx->sctlr_el1 |= SCTLR_CP15BEN; + *hypctx_sys_reg(el2ctx, SCTLR_EL1) = SCTLR_RES1; + *hypctx_sys_reg(el2ctx, SCTLR_EL1) &= ~SCTLR_M & ~SCTLR_C & ~SCTLR_I; + *hypctx_sys_reg(el2ctx, SCTLR_EL1) |= SCTLR_CP15BEN; set_arch_unknown(el2ctx->sp_el0); - set_arch_unknown(el2ctx->tcr_el1); set_arch_unknown(el2ctx->tpidr_el0); set_arch_unknown(el2ctx->tpidr_el1); set_arch_unknown(el2ctx->tpidrro_el0); - set_arch_unknown(el2ctx->ttbr0_el1); - set_arch_unknown(el2ctx->ttbr1_el1); - set_arch_unknown(el2ctx->vbar_el1); - set_arch_unknown(el2ctx->spsr_el1); set_arch_unknown(el2ctx->dbgbcr_el1); set_arch_unknown(el2ctx->dbgbvr_el1);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a4bc8b7.1e2c2.1d541648>
