[PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction

Alistair Francis posted 3 patches 4 years, 5 months ago
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Bin Meng <bin.meng@windriver.com>
There is a newer version of this series
[PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Alistair Francis 4 years, 5 months ago
From: Alistair Francis <alistair.francis@wdc.com>

The stval and mtval registers can optionally contain the faulting
instruction on an illegal instruction exception. This patch adds support
for setting the stval and mtval registers based on the CPU feature.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h        |  5 ++++-
 target/riscv/cpu_helper.c | 10 ++++++++++
 target/riscv/translate.c  | 31 +++++++++++++++++--------------
 3 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index bf1c899c00..d11db1f031 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -77,7 +77,8 @@ enum {
     RISCV_FEATURE_MMU,
     RISCV_FEATURE_PMP,
     RISCV_FEATURE_EPMP,
-    RISCV_FEATURE_MISA
+    RISCV_FEATURE_MISA,
+    RISCV_FEATURE_MTVAL_INST,
 };
 
 #define PRIV_VERSION_1_10_0 0x00011000
@@ -130,6 +131,8 @@ struct CPURISCVState {
     target_ulong frm;
 
     target_ulong badaddr;
+    uint32_t bins;
+
     target_ulong guest_phys_fault_addr;
 
     target_ulong priv_ver;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 968cb8046f..65832967e1 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -967,6 +967,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             write_tval  = true;
             tval = env->badaddr;
             break;
+        case RISCV_EXCP_ILLEGAL_INST:
+            if (riscv_feature(env, RISCV_FEATURE_MTVAL_INST)) {
+                /*
+                 * The stval/mtval register can optionally also be used to
+                 * return the faulting instruction bits on an illegal
+                 * instruction exception.
+                 */
+                tval = env->bins;
+            }
+            break;
         default:
             break;
         }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 25670be435..99810db57d 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -173,8 +173,25 @@ static void lookup_and_goto_ptr(DisasContext *ctx)
     }
 }
 
+/*
+ * Wrappers for getting reg values.
+ *
+ * The $zero register does not have cpu_gpr[0] allocated -- we supply the
+ * constant zero as a source, and an uninitialized sink as destination.
+ *
+ * Further, we may provide an extension for word operations.
+ */
+static TCGv temp_new(DisasContext *ctx)
+{
+    assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
+    return ctx->temp[ctx->ntemp++] = tcg_temp_new();
+}
+
 static void gen_exception_illegal(DisasContext *ctx)
 {
+    tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
+                   offsetof(CPURISCVState, bins));
+
     generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
 }
 
@@ -195,20 +212,6 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
     }
 }
 
-/*
- * Wrappers for getting reg values.
- *
- * The $zero register does not have cpu_gpr[0] allocated -- we supply the
- * constant zero as a source, and an uninitialized sink as destination.
- *
- * Further, we may provide an extension for word operations.
- */
-static TCGv temp_new(DisasContext *ctx)
-{
-    assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
-    return ctx->temp[ctx->ntemp++] = tcg_temp_new();
-}
-
 static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
 {
     TCGv t;
-- 
2.31.1


Re: [PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Bin Meng 4 years, 5 months ago
On Wed, Sep 8, 2021 at 12:54 PM Alistair Francis
<alistair.francis@opensource.wdc.com> wrote:
>
> From: Alistair Francis <alistair.francis@wdc.com>
>
> The stval and mtval registers can optionally contain the faulting
> instruction on an illegal instruction exception. This patch adds support
> for setting the stval and mtval registers based on the CPU feature.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.h        |  5 ++++-
>  target/riscv/cpu_helper.c | 10 ++++++++++
>  target/riscv/translate.c  | 31 +++++++++++++++++--------------
>  3 files changed, 31 insertions(+), 15 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Re: [PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Richard Henderson 4 years, 5 months ago
On 9/8/21 6:54 AM, Alistair Francis wrote:
> @@ -967,6 +967,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>               write_tval  = true;
>               tval = env->badaddr;
>               break;
> +        case RISCV_EXCP_ILLEGAL_INST:
> +            if (riscv_feature(env, RISCV_FEATURE_MTVAL_INST)) {
> +                /*
> +                 * The stval/mtval register can optionally also be used to
> +                 * return the faulting instruction bits on an illegal
> +                 * instruction exception.
> +                 */
> +                tval = env->bins;
> +            }
> +            break;

I'll note that write_tval should probably be renamed, and/or eliminated, because it looks 
like it's incorrectly unset here.  If you move the adjustment to cause above this switch, 
then you can move the RVH code that needed write_tval into this switch (just the 
HSTATUS_GVA update?).

But... more specific to this case.  Prior to this, was the exception handler allowed to 
assume anything about the contents of stval?  Should the value have been zero?  Would it 
be wrong to write to stval unconditionally?  How does the guest OS know that it can rely 
on stval being set?

I simply wonder whether it's worthwhile to add the feature and feature test.


r~

Re: [PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Alistair Francis 4 years, 4 months ago
On Wed, Sep 8, 2021 at 4:48 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 9/8/21 6:54 AM, Alistair Francis wrote:
> > @@ -967,6 +967,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >               write_tval  = true;
> >               tval = env->badaddr;
> >               break;
> > +        case RISCV_EXCP_ILLEGAL_INST:
> > +            if (riscv_feature(env, RISCV_FEATURE_MTVAL_INST)) {
> > +                /*
> > +                 * The stval/mtval register can optionally also be used to
> > +                 * return the faulting instruction bits on an illegal
> > +                 * instruction exception.
> > +                 */
> > +                tval = env->bins;
> > +            }
> > +            break;
>
> I'll note that write_tval should probably be renamed, and/or eliminated, because it looks
> like it's incorrectly unset here.  If you move the adjustment to cause above this switch,
> then you can move the RVH code that needed write_tval into this switch (just the
> HSTATUS_GVA update?).
>
> But... more specific to this case.  Prior to this, was the exception handler allowed to
> assume anything about the contents of stval?  Should the value have been zero?  Would it
> be wrong to write to stval unconditionally?  How does the guest OS know that it can rely
> on stval being set?

As we didn't support writing the illegal instruction stval should be
zero before this patch.

>
> I simply wonder whether it's worthwhile to add the feature and feature test.

Do you just mean have it enabled all the time?

Alistair

>
>
> r~

Re: [PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Richard Henderson 4 years, 4 months ago
On 9/24/21 2:48 AM, Alistair Francis wrote:
>> But... more specific to this case.  Prior to this, was the exception handler allowed to
>> assume anything about the contents of stval?  Should the value have been zero?  Would it
>> be wrong to write to stval unconditionally?  How does the guest OS know that it can rely
>> on stval being set?
> 
> As we didn't support writing the illegal instruction stval should be
> zero before this patch.

Ok, that didn't quite answer the question...

If *wasn't* zero before this patch: we didn't write anything at all, and so keep whatever 
previous value the previous exception wrote.

Is that a bug that needs fixing?  Because you're still not writing anything to stval if 
!MTVAL_INST...

>> I simply wonder whether it's worthwhile to add the feature and feature test.
> 
> Do you just mean have it enabled all the time?

Yes, if without this feature the value of stval was undefined.


r~

Re: [PATCH v2 2/3] target/riscv: Implement the stval/mtval illegal instruction
Posted by Alistair Francis 4 years, 4 months ago
On Fri, Sep 24, 2021 at 10:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 9/24/21 2:48 AM, Alistair Francis wrote:
> >> But... more specific to this case.  Prior to this, was the exception handler allowed to
> >> assume anything about the contents of stval?  Should the value have been zero?  Would it
> >> be wrong to write to stval unconditionally?  How does the guest OS know that it can rely
> >> on stval being set?
> >
> > As we didn't support writing the illegal instruction stval should be
> > zero before this patch.
>
> Ok, that didn't quite answer the question...
>
> If *wasn't* zero before this patch: we didn't write anything at all, and so keep whatever
> previous value the previous exception wrote.
>
> Is that a bug that needs fixing?  Because you're still not writing anything to stval if
> !MTVAL_INST...

Yeah, that sounds like a bug then.

>
> >> I simply wonder whether it's worthwhile to add the feature and feature test.
> >
> > Do you just mean have it enabled all the time?
>
> Yes, if without this feature the value of stval was undefined.

Ok, I'll have another look at this. Thanks for pointing this out.

Alistair

>
>
> r~