git: 5bcd16cced3b - main - arm64: Use the new sys handler for ID regs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 12 May 2025 12:50:27 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=5bcd16cced3b57d16e5c0973641c31acba4e1f64 commit 5bcd16cced3b57d16e5c0973641c31acba4e1f64 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2025-05-12 11:07:09 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2025-05-12 11:07:09 +0000 arm64: Use the new sys handler for ID regs Switch to the new sys instruction handling for the ID registers. Reviewed by: harry.moulton_arm.com Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D50211 --- sys/arm64/arm64/identcpu.c | 75 ++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index c4eaaaafc279..508ea0d472d3 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -2384,48 +2384,49 @@ user_ctr_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame, return (1); } -static int -user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame, - uint32_t esr) +static bool +user_idreg_handler(uint64_t esr, struct trapframe *frame) { uint64_t value; - int CRm, Op2, i, reg; + int reg; - if ((insn & MRS_MASK) != MRS_VALUE) - return (0); + if (ESR_ELx_EXCEPTION(esr) != EXCP_MSR) + return (false); + + /* Only support reading from ID registers */ + if ((esr & ISS_MSR_DIR) == 0) + return (false); /* - * We only emulate Op0 == 3, Op1 == 0, CRn == 0, CRm == {0, 4-7}. - * These are in the EL1 CPU identification space. - * CRm == 0 holds MIDR_EL1, MPIDR_EL1, and REVID_EL1. - * CRm == {4-7} holds the ID_AA64 registers. + * This only handles the ID register space and a few registers that + * are safe to pass through to userspace. * - * For full details see the ARMv8 ARM (ARM DDI 0487C.a) - * Table D9-2 System instruction encodings for non-Debug System - * register accesses. + * These registers are all in the space op0 == 3, op1 == 0, + * CRn == 0. We support the following CRm: + * - CRm == 0: midr_el1, mpidr_el1, and revidr_el1. + * - CRm in {4-7}: sanitized ID registers. + * + * Registers in the ID register space (CRm in {4-7}) are all + * read-only and have either defined fields, or are read as + * zero (RAZ). For these we return 0 for any unknown register. */ - if (mrs_Op0(insn) != 3 || mrs_Op1(insn) != 0 || mrs_CRn(insn) != 0) - return (0); - - CRm = mrs_CRm(insn); - if (CRm > 7 || (CRm < 4 && CRm != 0)) - return (0); + if (ISS_MSR_OP0(esr) != 3 || ISS_MSR_OP1(esr) != 0 || + ISS_MSR_CRn(esr) != 0) + return (false); - Op2 = mrs_Op2(insn); value = 0; - - for (i = 0; i < nitems(user_regs); i++) { - if (user_regs[i].CRm == CRm && user_regs[i].Op2 == Op2) { - if (SV_CURPROC_ABI() == SV_ABI_FREEBSD) - value = CPU_DESC_FIELD(user_cpu_desc, i); - else - value = CPU_DESC_FIELD(l_user_cpu_desc, i); - break; + if (ISS_MSR_CRm(esr) >= 4 && ISS_MSR_CRm(esr) <= 7) { + for (int i = 0; i < nitems(user_regs); i++) { + if (user_regs[i].iss == (esr & ISS_MSR_REG_MASK)) { + if (SV_CURPROC_ABI() == SV_ABI_FREEBSD) + value = CPU_DESC_FIELD(user_cpu_desc, i); + else + value = CPU_DESC_FIELD(l_user_cpu_desc, i); + break; + } } - } - - if (CRm == 0) { - switch (Op2) { + } else if (ISS_MSR_CRm(esr) == 0) { + switch (ISS_MSR_OP2(esr)) { case 0: value = READ_SPECIALREG(midr_el1); break; @@ -2436,8 +2437,10 @@ user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame, value = READ_SPECIALREG(revidr_el1); break; default: - return (0); + return (false); } + } else { + return (false); } /* @@ -2446,7 +2449,7 @@ user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame, */ frame->tf_elr += INSN_SIZE; - reg = MRS_REGISTER(insn); + reg = ISS_MSR_Rt(esr); /* If reg is 31 then write to xzr, i.e. do nothing */ if (reg == 31) return (1); @@ -2456,7 +2459,7 @@ user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame, else if (reg == 30) frame->tf_lr = value; - return (1); + return (true); } /* @@ -2795,7 +2798,7 @@ identify_cpu_sysinit(void *dummy __unused) #endif install_undef_handler(user_ctr_handler); - install_undef_handler(user_mrs_handler); + install_sys_handler(user_idreg_handler); } SYSINIT(identify_cpu, SI_SUB_CPU, SI_ORDER_MIDDLE, identify_cpu_sysinit, NULL);