qemu-devel
[Top][All Lists]
Advanced

[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;
> >   }
> >



reply via email to

[Prev in Thread] Current Thread [Next in Thread]