git: 128085a3e7f3 - main - arm64: Use ISS to search for a special register

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 23 Jun 2025 12:07:37 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=128085a3e7f3afc2f89845e81730a1d2340b3f04

commit 128085a3e7f3afc2f89845e81730a1d2340b3f04
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2025-06-23 10:15:14 +0000
Commit:     Andrew Turner <andrew@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, &regs->field, masks->field))	\
+	if (!get_kernel_reg_iss_masked(reg ## _ISS, &regs->field,	\
+	    masks->field))						\
 		regs->field = 0;					\
 } while (0)
 	_FETCH_KERN_REG(ID_AA64AFR0_EL1, id_aa64afr0);