The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=128085a3e7f3afc2f89845e81730a1d2340b3f04
commit 128085a3e7f3afc2f89845e81730a1d2340b3f04 Author: Andrew Turner <and...@freebsd.org> AuthorDate: 2025-06-23 10:15:14 +0000 Commit: Andrew Turner <and...@freebsd.org> CommitDate: 2025-06-23 10:18:19 +0000 arm64: Use ISS to search for a special register Previously we would use part of the msr/mrs instruction to find what register was being asked for. This was the only use for these values. We now have ESR_EL1 ISS field values for the same register so can use this new value to find what register is asked for. This lets us remove the old reg field from struct mrs_user_reg. Add macros to keep the old KPI. Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D50905 --- sys/arm64/arm64/identcpu.c | 18 ++++++++---------- sys/arm64/include/cpu.h | 16 ++++++++++++---- sys/arm64/vmm/vmm.c | 3 ++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index c1960812928f..72ef94531f54 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -2195,7 +2195,6 @@ static const struct mrs_field mvfr1_fields[] = { #endif /* COMPAT_FREEBSD32 */ struct mrs_user_reg { - u_int reg; u_int iss; bool is64bit; size_t offset; @@ -2204,7 +2203,6 @@ struct mrs_user_reg { #define USER_REG(name, field_name, _is64bit) \ { \ - .reg = name, \ .iss = name##_ISS, \ .offset = __offsetof(struct cpu_desc, field_name), \ .fields = field_name##_fields, \ @@ -2497,12 +2495,12 @@ mrs_field_cmp(uint64_t a, uint64_t b, u_int shift, int width, bool sign) } bool -get_kernel_reg(u_int reg, uint64_t *val) +get_kernel_reg_iss(u_int iss, uint64_t *val) { int i; for (i = 0; i < nitems(user_regs); i++) { - if (user_regs[i].reg == reg) { + if (user_regs[i].iss == iss) { *val = CPU_DESC_FIELD(kern_cpu_desc, i); return (true); } @@ -2516,13 +2514,13 @@ get_kernel_reg(u_int reg, uint64_t *val) * do not exceed those in the mask. */ bool -get_kernel_reg_masked(u_int reg, uint64_t *valp, uint64_t mask) +get_kernel_reg_iss_masked(u_int iss, uint64_t *valp, uint64_t mask) { const struct mrs_field *fields; uint64_t val; for (int i = 0; i < nitems(user_regs); i++) { - if (user_regs[i].reg == reg) { + if (user_regs[i].iss == iss) { val = CPU_DESC_FIELD(kern_cpu_desc, i); fields = user_regs[i].fields; for (int j = 0; fields[j].type != 0; j++) { @@ -2539,12 +2537,12 @@ get_kernel_reg_masked(u_int reg, uint64_t *valp, uint64_t mask) } bool -get_user_reg(u_int reg, uint64_t *val, bool fbsd) +get_user_reg_iss(u_int iss, uint64_t *val, bool fbsd) { int i; for (i = 0; i < nitems(user_regs); i++) { - if (user_regs[i].reg == reg) { + if (user_regs[i].iss == iss) { if (fbsd) *val = CPU_DESC_FIELD(user_cpu_desc, i); else @@ -2694,7 +2692,7 @@ update_special_regs(u_int cpu) * HWCAPs are set the check for these is enough. */ void -update_special_reg(u_int reg, uint64_t clear, uint64_t set) +update_special_reg_iss(u_int iss, uint64_t clear, uint64_t set) { MPASS(hwcaps_set == false); /* There is no locking here, so we only support changing this on CPU0 */ @@ -2702,7 +2700,7 @@ update_special_reg(u_int reg, uint64_t clear, uint64_t set) MPASS(PCPU_GET(cpuid) == 0); for (int i = 0; i < nitems(user_regs); i++) { - if (user_regs[i].reg != reg) + if (user_regs[i].iss != iss) continue; clear_set_special_reg_idx(i, clear, set); diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h index 2dd1a905b2b7..4ef01e9a47ed 100644 --- a/sys/arm64/include/cpu.h +++ b/sys/arm64/include/cpu.h @@ -232,10 +232,18 @@ void ptrauth_mp_start(uint64_t); /* Functions to read the sanitised view of the special registers */ void update_special_regs(u_int); -void update_special_reg(u_int reg, uint64_t, uint64_t); -bool get_kernel_reg(u_int, uint64_t *); -bool get_kernel_reg_masked(u_int, uint64_t *, uint64_t); -bool get_user_reg(u_int, uint64_t *, bool); +void update_special_reg_iss(u_int, uint64_t, uint64_t); +#define update_special_reg(reg, clear, set) \ + update_special_reg_iss(reg ## _ISS, clear, set) +bool get_kernel_reg_iss(u_int, uint64_t *); +#define get_kernel_reg(reg, valp) \ + get_kernel_reg_iss(reg ## _ISS, valp) +bool get_kernel_reg_iss_masked(u_int, uint64_t *, uint64_t); +#define get_kernel_reg_masked(reg, valp, mask) \ + get_kernel_reg_iss_masked(reg ## _ISS, valp, mask) +bool get_user_reg_iss(u_int, uint64_t *, bool); +#define get_user_reg(reg, valp, fbsd) \ + get_user_reg_iss(reg ## _ISS, valp, fbsd) void cpu_desc_init(void); diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c index f28643db99d2..3082d2941221 100644 --- a/sys/arm64/vmm/vmm.c +++ b/sys/arm64/vmm/vmm.c @@ -245,7 +245,8 @@ vmm_regs_init(struct vmm_regs *regs, const struct vmm_regs *masks) { #define _FETCH_KERN_REG(reg, field) do { \ regs->field = vmm_arch_regs_masks.field; \ - if (!get_kernel_reg_masked(reg, ®s->field, masks->field)) \ + if (!get_kernel_reg_iss_masked(reg ## _ISS, ®s->field, \ + masks->field)) \ regs->field = 0; \ } while (0) _FETCH_KERN_REG(ID_AA64AFR0_EL1, id_aa64afr0);