diff mbox series

target/riscv: Support SW update of PTE A/D bits and Ssptwad extension

Message ID 20220718035249.17440-1-jim.shu@sifive.com
State New
Headers show
Series target/riscv: Support SW update of PTE A/D bits and Ssptwad extension | expand

Commit Message

Jim Shu July 18, 2022, 3:52 a.m. UTC
RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
(Access/Dirty bit): HW update or SW update. RISC-V profile defines the
extension name 'Ssptwad' for HW update to PTE A/D bits.
https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc

Current QEMU RISC-V implements HW update scheme, so this commit
introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
uses HW update scheme (ext_ssptwad=true) by default to keep the backward
compatibility.

SW update scheme implemention is based on priv spec v1.12:
"When a virtual page is accessed and the A bit is clear, or is written
and the D bit is clear, a page-fault exception (corresponding to the
original access type) is raised."

Signed-off-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
---
 target/riscv/cpu.c        | 2 ++
 target/riscv/cpu.h        | 1 +
 target/riscv/cpu_helper.c | 9 +++++++++
 3 files changed, 12 insertions(+)

Comments

Anup Patel July 18, 2022, 4:02 a.m. UTC | #1
+Atish

On Mon, Jul 18, 2022 at 9:23 AM Jim Shu <jim.shu@sifive.com> wrote:
>
> RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
> (Access/Dirty bit): HW update or SW update. RISC-V profile defines the
> extension name 'Ssptwad' for HW update to PTE A/D bits.
> https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc

The Ssptwad (even though used by profiles) is not a well defined RISC-V
ISA extension. Rather, Ssptwad is just a name used in profiles to represent
an optional feature.

In fact, since it is not a well-defined ISA extension, QEMU cannot include
Ssptwad in the ISA string as well.

I think for such optionalities which are not well-defined ISA extensions,
QEMU should treat it differently.

Regards,
Anup

>
> Current QEMU RISC-V implements HW update scheme, so this commit
> introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
> as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
> uses HW update scheme (ext_ssptwad=true) by default to keep the backward
> compatibility.
>
> SW update scheme implemention is based on priv spec v1.12:
> "When a virtual page is accessed and the A bit is clear, or is written
> and the D bit is clear, a page-fault exception (corresponding to the
> original access type) is raised."
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
> ---
>  target/riscv/cpu.c        | 2 ++
>  target/riscv/cpu.h        | 1 +
>  target/riscv/cpu_helper.c | 9 +++++++++
>  3 files changed, 12 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1bb3973806..1d38c1c1d2 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -857,6 +857,7 @@ static void riscv_cpu_init(Object *obj)
>
>      cpu->cfg.ext_ifencei = true;
>      cpu->cfg.ext_icsr = true;
> +    cpu->cfg.ext_ssptwad = true;
>      cpu->cfg.mmu = true;
>      cpu->cfg.pmp = true;
>
> @@ -900,6 +901,7 @@ static Property riscv_cpu_extensions[] = {
>      DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>      DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>      DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> +    DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
>
>      DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
>      DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5c7acc055a..2eee59af98 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -433,6 +433,7 @@ struct RISCVCPUConfig {
>      bool ext_zve32f;
>      bool ext_zve64f;
>      bool ext_zmmul;
> +    bool ext_ssptwad;
>      bool rvv_ta_all_1s;
>
>      uint32_t mvendorid;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 59b3680b1b..a8607c0d7b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -981,6 +981,15 @@ restart:
>
>              /* Page table updates need to be atomic with MTTCG enabled */
>              if (updated_pte != pte) {
> +                if (!cpu->cfg.ext_ssptwad) {
> +                    /*
> +                     * If A/D bits are managed by SW, HW just raises the
> +                     * page fault exception corresponding to the original
> +                     * access type when A/D bits need to be updated.
> +                     */
> +                    return TRANSLATE_FAIL;
> +                }
> +
>                  /*
>                   * - if accessed or dirty bits need updating, and the PTE is
>                   *   in RAM, then we do so atomically with a compare and swap.
> --
> 2.17.1
>
>
Jim Shu July 19, 2022, 11:32 p.m. UTC | #2
Hi Anup,

Do you think it is OK if we only use ssptwad as a CPU option name
but not a RISC-V extension? just like MMU and PMP options of RISC-V.
(And we could change it to RISC-V extension in the future
if Ssptwad becomes the formal RISC-V extension)

Both HW/SW update schemes are already defined in RISC-V priv spec,
so I think it's reasonable to implement them in QEMU. The only issue here is
to choose a proper CPU option name to turn on/off HW update of A/D bits.

Regards,
Jim Shu

On Mon, Jul 18, 2022 at 12:02 PM Anup Patel <anup@brainfault.org> wrote:

> +Atish
>
> On Mon, Jul 18, 2022 at 9:23 AM Jim Shu <jim.shu@sifive.com> wrote:
> >
> > RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
> > (Access/Dirty bit): HW update or SW update. RISC-V profile defines the
> > extension name 'Ssptwad' for HW update to PTE A/D bits.
> > https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc
>
> The Ssptwad (even though used by profiles) is not a well defined RISC-V
> ISA extension. Rather, Ssptwad is just a name used in profiles to represent
> an optional feature.
>
> In fact, since it is not a well-defined ISA extension, QEMU cannot include
> Ssptwad in the ISA string as well.
>
> I think for such optionalities which are not well-defined ISA extensions,
> QEMU should treat it differently.
>
> Regards,
> Anup
>
> >
> > Current QEMU RISC-V implements HW update scheme, so this commit
> > introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
> > as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
> > uses HW update scheme (ext_ssptwad=true) by default to keep the backward
> > compatibility.
> >
> > SW update scheme implemention is based on priv spec v1.12:
> > "When a virtual page is accessed and the A bit is clear, or is written
> > and the D bit is clear, a page-fault exception (corresponding to the
> > original access type) is raised."
> >
> > Signed-off-by: Jim Shu <jim.shu@sifive.com>
> > Reviewed-by: Frank Chang <frank.chang@sifive.com>
> > ---
> >  target/riscv/cpu.c        | 2 ++
> >  target/riscv/cpu.h        | 1 +
> >  target/riscv/cpu_helper.c | 9 +++++++++
> >  3 files changed, 12 insertions(+)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 1bb3973806..1d38c1c1d2 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -857,6 +857,7 @@ static void riscv_cpu_init(Object *obj)
> >
> >      cpu->cfg.ext_ifencei = true;
> >      cpu->cfg.ext_icsr = true;
> > +    cpu->cfg.ext_ssptwad = true;
> >      cpu->cfg.mmu = true;
> >      cpu->cfg.pmp = true;
> >
> > @@ -900,6 +901,7 @@ static Property riscv_cpu_extensions[] = {
> >      DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
> >      DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
> >      DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> > +    DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
> >
> >      DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
> >      DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 5c7acc055a..2eee59af98 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -433,6 +433,7 @@ struct RISCVCPUConfig {
> >      bool ext_zve32f;
> >      bool ext_zve64f;
> >      bool ext_zmmul;
> > +    bool ext_ssptwad;
> >      bool rvv_ta_all_1s;
> >
> >      uint32_t mvendorid;
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index 59b3680b1b..a8607c0d7b 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -981,6 +981,15 @@ restart:
> >
> >              /* Page table updates need to be atomic with MTTCG enabled
> */
> >              if (updated_pte != pte) {
> > +                if (!cpu->cfg.ext_ssptwad) {
> > +                    /*
> > +                     * If A/D bits are managed by SW, HW just raises the
> > +                     * page fault exception corresponding to the
> original
> > +                     * access type when A/D bits need to be updated.
> > +                     */
> > +                    return TRANSLATE_FAIL;
> > +                }
> > +
> >                  /*
> >                   * - if accessed or dirty bits need updating, and the
> PTE is
> >                   *   in RAM, then we do so atomically with a compare
> and swap.
> > --
> > 2.17.1
> >
> >
>
Anup Patel July 20, 2022, 3:52 a.m. UTC | #3
On Wed, Jul 20, 2022 at 5:02 AM Jim Shu <jim.shu@sifive.com> wrote:
>
> Hi Anup,
>
> Do you think it is OK if we only use ssptwad as a CPU option name
> but not a RISC-V extension? just like MMU and PMP options of RISC-V.
> (And we could change it to RISC-V extension in the future
> if Ssptwad becomes the formal RISC-V extension)
>
> Both HW/SW update schemes are already defined in RISC-V priv spec,
> so I think it's reasonable to implement them in QEMU. The only issue here is
> to choose a proper CPU option name to turn on/off HW update of A/D bits.

I am not saying that we should avoid implementing it in QEMU.

My suggestion is to differentiate HW optionalities from ISA extensions
in QEMU. For example, instead of referring to this as Ssptwad, we should
call it "hw_ptwad" or "opt_ptwad" and don't use the "ext_" prefix.

@Alistair Francis might have better suggestions on this ?

Regards,
Anup

>
> Regards,
> Jim Shu
>
> On Mon, Jul 18, 2022 at 12:02 PM Anup Patel <anup@brainfault.org> wrote:
>>
>> +Atish
>>
>> On Mon, Jul 18, 2022 at 9:23 AM Jim Shu <jim.shu@sifive.com> wrote:
>> >
>> > RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
>> > (Access/Dirty bit): HW update or SW update. RISC-V profile defines the
>> > extension name 'Ssptwad' for HW update to PTE A/D bits.
>> > https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc
>>
>> The Ssptwad (even though used by profiles) is not a well defined RISC-V
>> ISA extension. Rather, Ssptwad is just a name used in profiles to represent
>> an optional feature.
>>
>> In fact, since it is not a well-defined ISA extension, QEMU cannot include
>> Ssptwad in the ISA string as well.
>>
>> I think for such optionalities which are not well-defined ISA extensions,
>> QEMU should treat it differently.
>>
>> Regards,
>> Anup
>>
>> >
>> > Current QEMU RISC-V implements HW update scheme, so this commit
>> > introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
>> > as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
>> > uses HW update scheme (ext_ssptwad=true) by default to keep the backward
>> > compatibility.
>> >
>> > SW update scheme implemention is based on priv spec v1.12:
>> > "When a virtual page is accessed and the A bit is clear, or is written
>> > and the D bit is clear, a page-fault exception (corresponding to the
>> > original access type) is raised."
>> >
>> > Signed-off-by: Jim Shu <jim.shu@sifive.com>
>> > Reviewed-by: Frank Chang <frank.chang@sifive.com>
>> > ---
>> >  target/riscv/cpu.c        | 2 ++
>> >  target/riscv/cpu.h        | 1 +
>> >  target/riscv/cpu_helper.c | 9 +++++++++
>> >  3 files changed, 12 insertions(+)
>> >
>> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > index 1bb3973806..1d38c1c1d2 100644
>> > --- a/target/riscv/cpu.c
>> > +++ b/target/riscv/cpu.c
>> > @@ -857,6 +857,7 @@ static void riscv_cpu_init(Object *obj)
>> >
>> >      cpu->cfg.ext_ifencei = true;
>> >      cpu->cfg.ext_icsr = true;
>> > +    cpu->cfg.ext_ssptwad = true;
>> >      cpu->cfg.mmu = true;
>> >      cpu->cfg.pmp = true;
>> >
>> > @@ -900,6 +901,7 @@ static Property riscv_cpu_extensions[] = {
>> >      DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>> >      DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>> >      DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
>> > +    DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
>> >
>> >      DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
>> >      DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
>> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > index 5c7acc055a..2eee59af98 100644
>> > --- a/target/riscv/cpu.h
>> > +++ b/target/riscv/cpu.h
>> > @@ -433,6 +433,7 @@ struct RISCVCPUConfig {
>> >      bool ext_zve32f;
>> >      bool ext_zve64f;
>> >      bool ext_zmmul;
>> > +    bool ext_ssptwad;
>> >      bool rvv_ta_all_1s;
>> >
>> >      uint32_t mvendorid;
>> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> > index 59b3680b1b..a8607c0d7b 100644
>> > --- a/target/riscv/cpu_helper.c
>> > +++ b/target/riscv/cpu_helper.c
>> > @@ -981,6 +981,15 @@ restart:
>> >
>> >              /* Page table updates need to be atomic with MTTCG enabled */
>> >              if (updated_pte != pte) {
>> > +                if (!cpu->cfg.ext_ssptwad) {
>> > +                    /*
>> > +                     * If A/D bits are managed by SW, HW just raises the
>> > +                     * page fault exception corresponding to the original
>> > +                     * access type when A/D bits need to be updated.
>> > +                     */
>> > +                    return TRANSLATE_FAIL;
>> > +                }
>> > +
>> >                  /*
>> >                   * - if accessed or dirty bits need updating, and the PTE is
>> >                   *   in RAM, then we do so atomically with a compare and swap.
>> > --
>> > 2.17.1
>> >
>> >
Alistair Francis July 20, 2022, 5:29 a.m. UTC | #4
On Wed, Jul 20, 2022 at 1:52 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Jul 20, 2022 at 5:02 AM Jim Shu <jim.shu@sifive.com> wrote:
> >
> > Hi Anup,
> >
> > Do you think it is OK if we only use ssptwad as a CPU option name
> > but not a RISC-V extension? just like MMU and PMP options of RISC-V.
> > (And we could change it to RISC-V extension in the future
> > if Ssptwad becomes the formal RISC-V extension)
> >
> > Both HW/SW update schemes are already defined in RISC-V priv spec,
> > so I think it's reasonable to implement them in QEMU. The only issue here is
> > to choose a proper CPU option name to turn on/off HW update of A/D bits.
>
> I am not saying that we should avoid implementing it in QEMU.
>
> My suggestion is to differentiate HW optionalities from ISA extensions
> in QEMU. For example, instead of referring to this as Ssptwad, we should
> call it "hw_ptwad" or "opt_ptwad" and don't use the "ext_" prefix.
>
> @Alistair Francis might have better suggestions on this ?

I'm just trying to wrap my head around this.

So the priv spec has this line:

"Two schemes to manage the A and D bits are permitted"

The first scheme just raises a page-fault exception, the second scheme
updates the A/D bits as you would expect.

The profiles spec then states that you must do the second scheme, as
that is what all software expects.

This patch is adding optional support for the first scheme.

Why do we want to support that? We can do either and we are
implementing the much more usual scheme. I don't see a reason to
bother implementing the other one. Is anyone ever going to use it?

Alistair
Jim Shu July 25, 2022, 3:22 p.m. UTC | #5
Hi Alistair,

Why do we want to support that? We can do either and we are
> implementing the much more usual scheme. I don't see a reason to
> bother implementing the other one. Is anyone ever going to use it?
>

Thanks for your response.
I got it.

Regards,
Jim Shu
diff mbox series

Patch

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1bb3973806..1d38c1c1d2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -857,6 +857,7 @@  static void riscv_cpu_init(Object *obj)
 
     cpu->cfg.ext_ifencei = true;
     cpu->cfg.ext_icsr = true;
+    cpu->cfg.ext_ssptwad = true;
     cpu->cfg.mmu = true;
     cpu->cfg.pmp = true;
 
@@ -900,6 +901,7 @@  static Property riscv_cpu_extensions[] = {
     DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
     DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
     DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
+    DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
 
     DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
     DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5c7acc055a..2eee59af98 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -433,6 +433,7 @@  struct RISCVCPUConfig {
     bool ext_zve32f;
     bool ext_zve64f;
     bool ext_zmmul;
+    bool ext_ssptwad;
     bool rvv_ta_all_1s;
 
     uint32_t mvendorid;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 59b3680b1b..a8607c0d7b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -981,6 +981,15 @@  restart:
 
             /* Page table updates need to be atomic with MTTCG enabled */
             if (updated_pte != pte) {
+                if (!cpu->cfg.ext_ssptwad) {
+                    /*
+                     * If A/D bits are managed by SW, HW just raises the
+                     * page fault exception corresponding to the original
+                     * access type when A/D bits need to be updated.
+                     */
+                    return TRANSLATE_FAIL;
+                }
+
                 /*
                  * - if accessed or dirty bits need updating, and the PTE is
                  *   in RAM, then we do so atomically with a compare and swap.