zicfilp introduces a new state elp ("expected landing pad") in cpu.
During normal execution, elp is idle (NO_LP_EXPECTED) i.e not expecting
landing pad. On an indirect call, elp moves LP_EXPECTED. When elp is
LP_EXPECTED, only a subsquent landing pad instruction can set state back
to NO_LP_EXPECTED. On reset, elp is set to NO_LP_EXPECTED.
zicfilp is enabled via bit2 in *envcfg CSRs. Enabling control for M-mode
is in mseccfg CSR at bit position 10.
On trap, elp state is saved away in *status.
Adds elp to the migration state as well.
Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Co-developed-by: Jim Shu <jim.shu@sifive.com>
Co-developed-by: Andy Chiu <andy.chiu@sifive.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
target/riscv/cpu.c | 3 +++
target/riscv/cpu.h | 2 ++
target/riscv/cpu_bits.h | 6 ++++++
target/riscv/csr.c | 31 +++++++++++++++++++++++++++++++
target/riscv/machine.c | 19 +++++++++++++++++++
target/riscv/pmp.c | 5 +++++
target/riscv/pmp.h | 3 ++-
7 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5dfb3f39ab..8e1f05e5b1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -994,6 +994,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
/* mmte is supposed to have pm.current hardwired to 1 */
env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
+ /* on reset elp is clear */
+ env->elp = false;
+
/*
* Bits 10, 6, 2 and 12 of mideleg are read only 1 when the Hypervisor
* extension is enabled.
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..f966c36a31 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -222,6 +222,8 @@ struct CPUArchState {
target_ulong jvt;
+ /* elp state for zicfilp extension */
+ bool elp;
#ifdef CONFIG_USER_ONLY
uint32_t elf_flags;
#endif
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index c257c5ed7d..b05ebe6f29 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -545,6 +545,8 @@
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */
#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */
+#define MSTATUS_SPELP 0x00800000 /* zicfilp */
+#define MSTATUS_MPELP 0x020000000000 /* zicfilp */
#define MSTATUS_GVA 0x4000000000ULL
#define MSTATUS_MPV 0x8000000000ULL
@@ -575,6 +577,7 @@ typedef enum {
#define SSTATUS_XS 0x00018000
#define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */
#define SSTATUS_MXR 0x00080000
+#define SSTATUS_SPELP MSTATUS_SPELP /* zicfilp */
#define SSTATUS64_UXL 0x0000000300000000ULL
@@ -747,6 +750,7 @@ typedef enum RISCVException {
/* Execution environment configuration bits */
#define MENVCFG_FIOM BIT(0)
+#define MENVCFG_LPE BIT(2) /* zicfilp */
#define MENVCFG_CBIE (3UL << 4)
#define MENVCFG_CBCFE BIT(6)
#define MENVCFG_CBZE BIT(7)
@@ -760,11 +764,13 @@ typedef enum RISCVException {
#define MENVCFGH_STCE BIT(31)
#define SENVCFG_FIOM MENVCFG_FIOM
+#define SENVCFG_LPE MENVCFG_LPE
#define SENVCFG_CBIE MENVCFG_CBIE
#define SENVCFG_CBCFE MENVCFG_CBCFE
#define SENVCFG_CBZE MENVCFG_CBZE
#define HENVCFG_FIOM MENVCFG_FIOM
+#define HENVCFG_LPE MENVCFG_LPE
#define HENVCFG_CBIE MENVCFG_CBIE
#define HENVCFG_CBCFE MENVCFG_CBCFE
#define HENVCFG_CBZE MENVCFG_CBZE
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 432c59dc66..5771a14848 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1400,6 +1400,11 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
}
}
+ /* If cfi lp extension is available, then apply cfi lp mask */
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= (MSTATUS_MPELP | MSTATUS_SPELP);
+ }
+
mstatus = (mstatus & ~mask) | (val & mask);
env->mstatus = mstatus;
@@ -2101,6 +2106,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
(cfg->ext_svadu ? MENVCFG_ADUE : 0);
+
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= MENVCFG_LPE;
+ }
}
env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
@@ -2153,6 +2162,10 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
return ret;
}
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= SENVCFG_LPE;
+ }
+
env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
return RISCV_EXCP_NONE;
}
@@ -2190,6 +2203,10 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE);
+
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= HENVCFG_LPE;
+ }
}
env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
@@ -2654,6 +2671,10 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
mask |= SSTATUS64_UXL;
}
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= SSTATUS_SPELP;
+ }
+
*val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus));
return RISCV_EXCP_NONE;
}
@@ -2665,6 +2686,11 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno,
if (env->xl != MXL_RV32 || env->debugger) {
mask |= SSTATUS64_UXL;
}
+
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= SSTATUS_SPELP;
+ }
+
/* TODO: Use SXL not MXL. */
*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
return RISCV_EXCP_NONE;
@@ -2680,6 +2706,11 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno,
mask |= SSTATUS64_UXL;
}
}
+
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ mask |= SSTATUS_SPELP;
+ }
+
target_ulong newval = (env->mstatus & ~mask) | (val & mask);
return write_mstatus(env, CSR_MSTATUS, newval);
}
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 76f2150f78..873957c4ab 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -351,6 +351,24 @@ static const VMStateDescription vmstate_jvt = {
}
};
+static bool elp_needed(void *opaque)
+{
+ RISCVCPU *cpu = opaque;
+
+ return cpu->cfg.ext_zicfilp;
+}
+
+static const VMStateDescription vmstate_elp = {
+ .name = "cpu/elp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = elp_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_BOOL(env.elp, RISCVCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 10,
@@ -423,6 +441,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_debug,
&vmstate_smstateen,
&vmstate_jvt,
+ &vmstate_elp,
NULL
}
};
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..1111d08d08 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -598,6 +598,11 @@ void mseccfg_csr_write(CPURISCVState *env, target_ulong val)
val &= ~(MSECCFG_MMWP | MSECCFG_MML | MSECCFG_RLB);
}
+ /* M-mode forward cfi to be enabled if cfi extension is implemented */
+ if (env_archcpu(env)->cfg.ext_zicfilp) {
+ val |= (val & MSECCFG_MLPE);
+ }
+
env->mseccfg = val;
}
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
index f5c10ce85c..e0530a17a3 100644
--- a/target/riscv/pmp.h
+++ b/target/riscv/pmp.h
@@ -44,7 +44,8 @@ typedef enum {
MSECCFG_MMWP = 1 << 1,
MSECCFG_RLB = 1 << 2,
MSECCFG_USEED = 1 << 8,
- MSECCFG_SSEED = 1 << 9
+ MSECCFG_SSEED = 1 << 9,
+ MSECCFG_MLPE = 1 << 10,
} mseccfg_field_t;
typedef struct {
--
2.44.0
On Tue, Aug 27, 2024 at 1:30 AM Deepak Gupta <debug@rivosinc.com> wrote: > > zicfilp introduces a new state elp ("expected landing pad") in cpu. > During normal execution, elp is idle (NO_LP_EXPECTED) i.e not expecting > landing pad. On an indirect call, elp moves LP_EXPECTED. When elp is > LP_EXPECTED, only a subsquent landing pad instruction can set state back > to NO_LP_EXPECTED. On reset, elp is set to NO_LP_EXPECTED. > > zicfilp is enabled via bit2 in *envcfg CSRs. Enabling control for M-mode > is in mseccfg CSR at bit position 10. > > On trap, elp state is saved away in *status. > Adds elp to the migration state as well. > > Signed-off-by: Deepak Gupta <debug@rivosinc.com> > Co-developed-by: Jim Shu <jim.shu@sifive.com> > Co-developed-by: Andy Chiu <andy.chiu@sifive.com> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/cpu.c | 3 +++ > target/riscv/cpu.h | 2 ++ > target/riscv/cpu_bits.h | 6 ++++++ > target/riscv/csr.c | 31 +++++++++++++++++++++++++++++++ > target/riscv/machine.c | 19 +++++++++++++++++++ > target/riscv/pmp.c | 5 +++++ > target/riscv/pmp.h | 3 ++- > 7 files changed, 68 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 5dfb3f39ab..8e1f05e5b1 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -994,6 +994,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) > /* mmte is supposed to have pm.current hardwired to 1 */ > env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT); > > + /* on reset elp is clear */ > + env->elp = false; > + > /* > * Bits 10, 6, 2 and 12 of mideleg are read only 1 when the Hypervisor > * extension is enabled. > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > index 87742047ce..f966c36a31 100644 > --- a/target/riscv/cpu.h > +++ b/target/riscv/cpu.h > @@ -222,6 +222,8 @@ struct CPUArchState { > > target_ulong jvt; > > + /* elp state for zicfilp extension */ > + bool elp; > #ifdef CONFIG_USER_ONLY > uint32_t elf_flags; > #endif > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h > index c257c5ed7d..b05ebe6f29 100644 > --- a/target/riscv/cpu_bits.h > +++ b/target/riscv/cpu_bits.h > @@ -545,6 +545,8 @@ > #define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */ > #define MSTATUS_TW 0x00200000 /* since: priv-1.10 */ > #define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */ > +#define MSTATUS_SPELP 0x00800000 /* zicfilp */ > +#define MSTATUS_MPELP 0x020000000000 /* zicfilp */ > #define MSTATUS_GVA 0x4000000000ULL > #define MSTATUS_MPV 0x8000000000ULL > > @@ -575,6 +577,7 @@ typedef enum { > #define SSTATUS_XS 0x00018000 > #define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */ > #define SSTATUS_MXR 0x00080000 > +#define SSTATUS_SPELP MSTATUS_SPELP /* zicfilp */ > > #define SSTATUS64_UXL 0x0000000300000000ULL > > @@ -747,6 +750,7 @@ typedef enum RISCVException { > > /* Execution environment configuration bits */ > #define MENVCFG_FIOM BIT(0) > +#define MENVCFG_LPE BIT(2) /* zicfilp */ > #define MENVCFG_CBIE (3UL << 4) > #define MENVCFG_CBCFE BIT(6) > #define MENVCFG_CBZE BIT(7) > @@ -760,11 +764,13 @@ typedef enum RISCVException { > #define MENVCFGH_STCE BIT(31) > > #define SENVCFG_FIOM MENVCFG_FIOM > +#define SENVCFG_LPE MENVCFG_LPE > #define SENVCFG_CBIE MENVCFG_CBIE > #define SENVCFG_CBCFE MENVCFG_CBCFE > #define SENVCFG_CBZE MENVCFG_CBZE > > #define HENVCFG_FIOM MENVCFG_FIOM > +#define HENVCFG_LPE MENVCFG_LPE > #define HENVCFG_CBIE MENVCFG_CBIE > #define HENVCFG_CBCFE MENVCFG_CBCFE > #define HENVCFG_CBZE MENVCFG_CBZE > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 432c59dc66..5771a14848 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -1400,6 +1400,11 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, > } > } > > + /* If cfi lp extension is available, then apply cfi lp mask */ > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= (MSTATUS_MPELP | MSTATUS_SPELP); > + } > + > mstatus = (mstatus & ~mask) | (val & mask); > > env->mstatus = mstatus; > @@ -2101,6 +2106,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno, > mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) | > (cfg->ext_sstc ? MENVCFG_STCE : 0) | > (cfg->ext_svadu ? MENVCFG_ADUE : 0); > + > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= MENVCFG_LPE; > + } > } > env->menvcfg = (env->menvcfg & ~mask) | (val & mask); > > @@ -2153,6 +2162,10 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno, > return ret; > } > > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= SENVCFG_LPE; > + } > + > env->senvcfg = (env->senvcfg & ~mask) | (val & mask); > return RISCV_EXCP_NONE; > } > @@ -2190,6 +2203,10 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno, > > if (riscv_cpu_mxl(env) == MXL_RV64) { > mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE); > + > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= HENVCFG_LPE; > + } > } > > env->henvcfg = (env->henvcfg & ~mask) | (val & mask); > @@ -2654,6 +2671,10 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, > mask |= SSTATUS64_UXL; > } > > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= SSTATUS_SPELP; > + } > + > *val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus)); > return RISCV_EXCP_NONE; > } > @@ -2665,6 +2686,11 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, > if (env->xl != MXL_RV32 || env->debugger) { > mask |= SSTATUS64_UXL; > } > + > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= SSTATUS_SPELP; > + } > + > /* TODO: Use SXL not MXL. */ > *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask); > return RISCV_EXCP_NONE; > @@ -2680,6 +2706,11 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno, > mask |= SSTATUS64_UXL; > } > } > + > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + mask |= SSTATUS_SPELP; > + } > + > target_ulong newval = (env->mstatus & ~mask) | (val & mask); > return write_mstatus(env, CSR_MSTATUS, newval); > } > diff --git a/target/riscv/machine.c b/target/riscv/machine.c > index 76f2150f78..873957c4ab 100644 > --- a/target/riscv/machine.c > +++ b/target/riscv/machine.c > @@ -351,6 +351,24 @@ static const VMStateDescription vmstate_jvt = { > } > }; > > +static bool elp_needed(void *opaque) > +{ > + RISCVCPU *cpu = opaque; > + > + return cpu->cfg.ext_zicfilp; > +} > + > +static const VMStateDescription vmstate_elp = { > + .name = "cpu/elp", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = elp_needed, > + .fields = (const VMStateField[]) { > + VMSTATE_BOOL(env.elp, RISCVCPU), > + VMSTATE_END_OF_LIST() > + } > +}; > + > const VMStateDescription vmstate_riscv_cpu = { > .name = "cpu", > .version_id = 10, > @@ -423,6 +441,7 @@ const VMStateDescription vmstate_riscv_cpu = { > &vmstate_debug, > &vmstate_smstateen, > &vmstate_jvt, > + &vmstate_elp, > NULL > } > }; > diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c > index 9eea397e72..1111d08d08 100644 > --- a/target/riscv/pmp.c > +++ b/target/riscv/pmp.c > @@ -598,6 +598,11 @@ void mseccfg_csr_write(CPURISCVState *env, target_ulong val) > val &= ~(MSECCFG_MMWP | MSECCFG_MML | MSECCFG_RLB); > } > > + /* M-mode forward cfi to be enabled if cfi extension is implemented */ > + if (env_archcpu(env)->cfg.ext_zicfilp) { > + val |= (val & MSECCFG_MLPE); > + } > + > env->mseccfg = val; > } > > diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h > index f5c10ce85c..e0530a17a3 100644 > --- a/target/riscv/pmp.h > +++ b/target/riscv/pmp.h > @@ -44,7 +44,8 @@ typedef enum { > MSECCFG_MMWP = 1 << 1, > MSECCFG_RLB = 1 << 2, > MSECCFG_USEED = 1 << 8, > - MSECCFG_SSEED = 1 << 9 > + MSECCFG_SSEED = 1 << 9, > + MSECCFG_MLPE = 1 << 10, > } mseccfg_field_t; > > typedef struct { > -- > 2.44.0 > >
© 2016 - 2024 Red Hat, Inc.