[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v1 RFC Zisslpcfi 5/9] target/riscv: state save and restore of
From: |
Deepak Gupta |
Subject: |
Re: [PATCH v1 RFC Zisslpcfi 5/9] target/riscv: state save and restore of zisslppcfi state |
Date: |
Wed, 15 Feb 2023 15:13:34 -0800 |
On Tue, Feb 14, 2023 at 10:11 PM LIU Zhiwei
<zhiwei_liu@linux.alibaba.com> wrote:
>
>
> On 2023/2/9 14:24, Deepak Gupta wrote:
> > zisslpcfi's forward cfi if enabled on a hart, enables tracking of
> > indirect branches. CPU/hart internally keeps a state `elp` short
> > for expecting landing pad instruction. This state goes into
> > LP_EXPECTED on an indirect branch. But an interrupt/exception can occur
> > before target instruction is executed. In such a case this state must be
> > preserved so that it can be restored later. zisslpcfi saves elp state in
> > `sstatus` CSR.
>
> And mstatus CSR.
Noted.
>
> Otherwise,
>
> Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> > This patch saves elp state in sstatus CSR on trap delivery
> > while restores from sstatus CSR on trap return.
> >
> > Additionally state in sstatus CSR must have save and restore zisslpcfi
> > state on exiting from hypervisor and entering into hypervisor.
> >
> > Signed-off-by: Deepak Gupta <debug@rivosinc.com>
> > Signed-off-by: Kip Walker <kip@rivosinc.com>
> > ---
> > target/riscv/cpu_bits.h | 5 +++++
> > target/riscv/cpu_helper.c | 26 ++++++++++++++++++++++++++
> > target/riscv/op_helper.c | 12 ++++++++++++
> > 3 files changed, 43 insertions(+)
> >
> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> > index 1663ba5775..37100ec8f6 100644
> > --- a/target/riscv/cpu_bits.h
> > +++ b/target/riscv/cpu_bits.h
> > @@ -594,6 +594,11 @@ typedef enum {
> >
> > #define CFISTATUS_S_MASK (SSTATUS_UFCFIEN | SSTATUS_UBCFIEN | \
> > SSTATUS_SPELP)
> > +/* enum for branch tracking state in cpu/hart */
> > +typedef enum {
> > + NO_LP_EXPECTED = 0,
> > + LP_EXPECTED = 1,
> > +} cfi_elp;
> >
> > /* hstatus CSR bits */
> > #define HSTATUS_VSBE 0x00000020
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index a397023840..fc188683c9 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -534,6 +534,16 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
> > if (riscv_has_ext(env, RVF)) {
> > mstatus_mask |= MSTATUS_FS;
> > }
> > +
> > + /*
> > + * If cfi extension available, menvcfg.CFI = 1 and henvcfg.CFI = 1,
> > + * then apply CFI mask on mstatus
> > + */
> > + if (env_archcpu(env)->cfg.ext_cfi &&
> > + get_field(env->menvcfg, MENVCFG_CFI) &&
> > + get_field(env->henvcfg, HENVCFG_CFI)) {
> > + mstatus_mask |= CFISTATUS_S_MASK;
> > + }
> > bool current_virt = riscv_cpu_virt_enabled(env);
> >
> > g_assert(riscv_has_ext(env, RVH));
> > @@ -1723,6 +1733,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > if (env->priv <= PRV_S &&
> > cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> > /* handle the trap in S-mode */
> > + /* save elp status */
> > + if (cpu_get_fcfien(env)) {
> > + env->mstatus = set_field(env->mstatus, MSTATUS_SPELP,
> > env->elp);
> > + }
> > if (riscv_has_ext(env, RVH)) {
> > uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
> >
> > @@ -1772,6 +1786,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > riscv_cpu_set_mode(env, PRV_S);
> > } else {
> > /* handle the trap in M-mode */
> > + /* save elp status */
> > + if (cpu_get_fcfien(env)) {
> > + env->mstatus = set_field(env->mstatus, MSTATUS_MPELP,
> > env->elp);
> > + }
> > if (riscv_has_ext(env, RVH)) {
> > if (riscv_cpu_virt_enabled(env)) {
> > riscv_cpu_swap_hypervisor_regs(env);
> > @@ -1803,6 +1821,14 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > riscv_cpu_set_mode(env, PRV_M);
> > }
> >
> > + /*
> > + * Interrupt/exception/trap delivery is asynchronous event and as per
> > + * Zisslpcfi spec CPU should clear up the ELP state. If cfi extension
> > is
> > + * available, clear ELP state.
> > + */
> > + if (cpu->cfg.ext_cfi) {
> > + env->elp = NO_LP_EXPECTED;
> > + }
> > /* NOTE: it is not necessary to yield load reservations here. It is
> > only
> > * necessary for an SC from "another hart" to cause a load reservation
> > * to be yielded. Refer to the memory consistency model section of the
> > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> > index 878bcb03b8..d15893aa82 100644
> > --- a/target/riscv/op_helper.c
> > +++ b/target/riscv/op_helper.c
> > @@ -176,6 +176,12 @@ target_ulong helper_sret(CPURISCVState *env)
> > riscv_cpu_set_virt_enabled(env, prev_virt);
> > }
> >
> > + /* If forward cfi enabled for target, restore elp status */
> > + if (cpu_get_fcfien(env)) {
> > + env->elp = get_field(env->mstatus, MSTATUS_SPELP);
> > + env->mstatus = set_field(env->mstatus, MSTATUS_SPELP, 0);
> > + }
> > +
> > riscv_cpu_set_mode(env, prev_priv);
> >
> > return retpc;
> > @@ -220,6 +226,12 @@ target_ulong helper_mret(CPURISCVState *env)
> > riscv_cpu_set_virt_enabled(env, prev_virt);
> > }
> >
> > + /* If forward cfi enabled for target, restore elp status */
> > + if (cpu_get_fcfien(env)) {
> > + env->elp = get_field(env->mstatus, MSTATUS_MPELP);
> > + env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, 0);
> > + }
> > +
> > return retpc;
> > }
> >