include: sbi: Use array for struct sbi_trap_regs and GET/SET macros

Rather than hand-rolling scaled pointer arithmetic with casts and
shifts, let the compiler do so by indexing an array of GPRs, taking
advantage of the language's type system to scale based on whatever type
the register happens to be. This makes it easier to support CHERI where
the registers are capabilities, not plain integers, and so this pointer
arithmetic would need to change (and currently REGBYTES is both the size
of a register and the size of an integer word upstream).

Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250709232932.37622-1-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Jessica Clarke
2025-07-10 00:29:28 +01:00
committed by Anup Patel
parent 0b7c2e0d60
commit ffd3ed976d
2 changed files with 92 additions and 81 deletions

View File

@@ -1291,6 +1291,8 @@
#define SHIFT_FUNCT3 12 #define SHIFT_FUNCT3 12
#define MASK_RS1 0xf8000 #define MASK_RS1 0xf8000
#define MASK_RS2 0x1f00000
#define MASK_RD 0xf80
#define MASK_CSR 0xfff00000 #define MASK_CSR 0xfff00000
#define SHIFT_CSR 20 #define SHIFT_CSR 20
@@ -1356,28 +1358,17 @@
#define SHIFT_RIGHT(x, y) \ #define SHIFT_RIGHT(x, y) \
((y) < 0 ? ((x) << -(y)) : ((x) >> (y))) ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
#define REG_MASK \
((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
#define REG_OFFSET(insn, pos) \
(SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
#define REG_PTR(insn, pos, regs) \
(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
#define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3) #define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
#define GET_RM(insn) GET_FUNC3(insn) #define GET_RM(insn) GET_FUNC3(insn)
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> 15) #define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> SH_RS1)
#define GET_RS2_NUM(insn) ((insn & MASK_RS2) >> SH_RS2)
#define GET_RS1S_NUM(insn) RVC_RS1S(insn)
#define GET_RS2S_NUM(insn) RVC_RS2S(insn)
#define GET_RS2C_NUM(insn) RVC_RS2(insn)
#define GET_RD_NUM(insn) ((insn & MASK_RD) >> SH_RD)
#define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR) #define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR)
#define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL) #define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL)
#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
#define GET_SP(regs) (*REG_PTR(2, 0, regs))
#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
#define IMM_I(insn) ((s32)(insn) >> 20) #define IMM_I(insn) ((s32)(insn) >> 20)
#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \ #define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
(s32)(((insn) >> 7) & 0x1f)) (s32)(((insn) >> 7) & 0x1f))

View File

@@ -127,70 +127,75 @@
/** Representation of register state at time of trap/interrupt */ /** Representation of register state at time of trap/interrupt */
struct sbi_trap_regs { struct sbi_trap_regs {
/** zero register state */ union {
unsigned long zero; unsigned long gprs[32];
/** ra register state */ struct {
unsigned long ra; /** zero register state */
/** sp register state */ unsigned long zero;
unsigned long sp; /** ra register state */
/** gp register state */ unsigned long ra;
unsigned long gp; /** sp register state */
/** tp register state */ unsigned long sp;
unsigned long tp; /** gp register state */
/** t0 register state */ unsigned long gp;
unsigned long t0; /** tp register state */
/** t1 register state */ unsigned long tp;
unsigned long t1; /** t0 register state */
/** t2 register state */ unsigned long t0;
unsigned long t2; /** t1 register state */
/** s0 register state */ unsigned long t1;
unsigned long s0; /** t2 register state */
/** s1 register state */ unsigned long t2;
unsigned long s1; /** s0 register state */
/** a0 register state */ unsigned long s0;
unsigned long a0; /** s1 register state */
/** a1 register state */ unsigned long s1;
unsigned long a1; /** a0 register state */
/** a2 register state */ unsigned long a0;
unsigned long a2; /** a1 register state */
/** a3 register state */ unsigned long a1;
unsigned long a3; /** a2 register state */
/** a4 register state */ unsigned long a2;
unsigned long a4; /** a3 register state */
/** a5 register state */ unsigned long a3;
unsigned long a5; /** a4 register state */
/** a6 register state */ unsigned long a4;
unsigned long a6; /** a5 register state */
/** a7 register state */ unsigned long a5;
unsigned long a7; /** a6 register state */
/** s2 register state */ unsigned long a6;
unsigned long s2; /** a7 register state */
/** s3 register state */ unsigned long a7;
unsigned long s3; /** s2 register state */
/** s4 register state */ unsigned long s2;
unsigned long s4; /** s3 register state */
/** s5 register state */ unsigned long s3;
unsigned long s5; /** s4 register state */
/** s6 register state */ unsigned long s4;
unsigned long s6; /** s5 register state */
/** s7 register state */ unsigned long s5;
unsigned long s7; /** s6 register state */
/** s8 register state */ unsigned long s6;
unsigned long s8; /** s7 register state */
/** s9 register state */ unsigned long s7;
unsigned long s9; /** s8 register state */
/** s10 register state */ unsigned long s8;
unsigned long s10; /** s9 register state */
/** s11 register state */ unsigned long s9;
unsigned long s11; /** s10 register state */
/** t3 register state */ unsigned long s10;
unsigned long t3; /** s11 register state */
/** t4 register state */ unsigned long s11;
unsigned long t4; /** t3 register state */
/** t5 register state */ unsigned long t3;
unsigned long t5; /** t4 register state */
/** t6 register state */ unsigned long t4;
unsigned long t6; /** t5 register state */
unsigned long t5;
/** t6 register state */
unsigned long t6;
};
};
/** mepc register state */ /** mepc register state */
unsigned long mepc; unsigned long mepc;
/** mstatus register state */ /** mstatus register state */
@@ -199,6 +204,21 @@ struct sbi_trap_regs {
unsigned long mstatusH; unsigned long mstatusH;
}; };
_Static_assert(
sizeof(((struct sbi_trap_regs *)0)->gprs) ==
offsetof(struct sbi_trap_regs, t6) +
sizeof(((struct sbi_trap_regs *)0)->t6),
"struct sbi_trap_regs's layout differs between gprs and named members");
#define REG_VAL(idx, regs) ((regs)->gprs[(idx)])
#define GET_RS1(insn, regs) REG_VAL(GET_RS1_NUM(insn), regs)
#define GET_RS2(insn, regs) REG_VAL(GET_RS2_NUM(insn), regs)
#define GET_RS1S(insn, regs) REG_VAL(GET_RS1S_NUM(insn), regs)
#define GET_RS2S(insn, regs) REG_VAL(GET_RS2S_NUM(insn), regs)
#define GET_RS2C(insn, regs) REG_VAL(GET_RS2C_NUM(insn), regs)
#define SET_RD(insn, regs, val) (REG_VAL(GET_RD_NUM(insn), regs) = (val))
/** Representation of trap details */ /** Representation of trap details */
struct sbi_trap_info { struct sbi_trap_info {
/** cause Trap exception cause */ /** cause Trap exception cause */