Re: [PATCH] targer/riscv: Implement Zabha extension

2024-05-28 Thread Alexandre Ghiti
Hi Zhiwei,

On Tue, May 28, 2024 at 8:57 AM LIU Zhiwei  wrote:
>
> Hi Alexandre,
>
> I have sent the patch set about Zabha before last week.

Sorry I did not check!

>
> https://lore.kernel.org/all/fed99165-58da-458c-b68f-a9717fc15...@linux.alibaba.com/T/
>
> Welcome to review it and give comments.

Sure, I'll do that, your patchset seems more complete than ours.

Thanks,

Alex

>
> Thanks,
> Zhiwei
>
> On 2024/5/28 13:45, Alexandre Ghiti wrote:
> > From: Gianluca Guida 
> >
> > Add Zabha implementation.
> >
> > Signed-off-by: Gianluca Guida 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >   target/riscv/cpu.c  |   2 +
> >   target/riscv/cpu_cfg.h  |   1 +
> >   target/riscv/insn32.decode  |  22 +++
> >   target/riscv/insn_trans/trans_rvzabha.c.inc | 149 
> >   target/riscv/tcg/tcg-cpu.c  |   5 +
> >   target/riscv/translate.c|   1 +
> >   6 files changed, 180 insertions(+)
> >   create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 70d1a527a1..b01f82002b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -116,6 +116,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
> >   ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
> >   ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
> >   ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
> > +ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_12_0, ext_zabha),
> >   ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
> >   ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
> >   ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
> > @@ -1464,6 +1465,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = 
> > {
> >   MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
> >   MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
> >   MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
> > +MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
> >   MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
> >   MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
> >   MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
> > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> > index d36c416ef0..7f614da4e2 100644
> > --- a/target/riscv/cpu_cfg.h
> > +++ b/target/riscv/cpu_cfg.h
> > @@ -81,6 +81,7 @@ struct RISCVCPUConfig {
> >   bool ext_svvptc;
> >   bool ext_zdinx;
> >   bool ext_zaamo;
> > +bool ext_zabha;
> >   bool ext_zacas;
> >   bool ext_zalrsc;
> >   bool ext_zawrs;
> > diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> > index f22df04cfd..6d7726120f 100644
> > --- a/target/riscv/insn32.decode
> > +++ b/target/riscv/insn32.decode
> > @@ -1010,3 +1010,25 @@ amocas_w00101 . . . . 010 . 010 
> > @atom_st
> >   amocas_d00101 . . . . 011 . 010 @atom_st
> >   # *** RV64 Zacas Standard Extension ***
> >   amocas_q00101 . . . . 100 . 010 @atom_st
> > +
> > +# *** Zabha Standard Extension ***
> > +amoswap_b  1 . . . . 000 . 010 @atom_st
> > +amoadd_b   0 . . . . 000 . 010 @atom_st
> > +amoxor_b   00100 . . . . 000 . 010 @atom_st
> > +amoand_b   01100 . . . . 000 . 010 @atom_st
> > +amoor_b01000 . . . . 000 . 010 @atom_st
> > +amomin_b   1 . . . . 000 . 010 @atom_st
> > +amomax_b   10100 . . . . 000 . 010 @atom_st
> > +amominu_b  11000 . . . . 000 . 010 @atom_st
> > +amomaxu_b  11100 . . . . 000 . 010 @atom_st
> > +amocas_b   00101 . . . . 000 . 010 @atom_st
> > +amoswap_h  1 . . . . 001 . 010 @atom_st
> > +amoadd_h   0 . . . . 001 . 010 @atom_st
> > +amoxor_h   00100 . . . . 001 . 010 @atom_st
> > +amoand_h   01100 . . . . 001 . 010 @atom_st
> > +amoor_h01000 . . . . 001 . 010 @atom_st
> > +amomin_h   1 . . . . 001 . 010 @atom_st
> > +amomax_h   10100 . . . . 001 . 010 @atom_st
> > +amominu_h  11000 . . . . 001 . 010 @atom_st
> > +amomaxu_h  11100 . . . . 001 

[PATCH] targer/riscv: Implement Zabha extension

2024-05-27 Thread Alexandre Ghiti
From: Gianluca Guida 

Add Zabha implementation.

Signed-off-by: Gianluca Guida 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c  |   2 +
 target/riscv/cpu_cfg.h  |   1 +
 target/riscv/insn32.decode  |  22 +++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 149 
 target/riscv/tcg/tcg-cpu.c  |   5 +
 target/riscv/translate.c|   1 +
 6 files changed, 180 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 70d1a527a1..b01f82002b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -116,6 +116,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_12_0, ext_zabha),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
 ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
@@ -1464,6 +1465,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index d36c416ef0..7f614da4e2 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -81,6 +81,7 @@ struct RISCVCPUConfig {
 bool ext_svvptc;
 bool ext_zdinx;
 bool ext_zaamo;
+bool ext_zabha;
 bool ext_zacas;
 bool ext_zalrsc;
 bool ext_zawrs;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f22df04cfd..6d7726120f 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1010,3 +1010,25 @@ amocas_w00101 . . . . 010 . 010 
@atom_st
 amocas_d00101 . . . . 011 . 010 @atom_st
 # *** RV64 Zacas Standard Extension ***
 amocas_q00101 . . . . 100 . 010 @atom_st
+
+# *** Zabha Standard Extension ***
+amoswap_b  1 . . . . 000 . 010 @atom_st
+amoadd_b   0 . . . . 000 . 010 @atom_st
+amoxor_b   00100 . . . . 000 . 010 @atom_st
+amoand_b   01100 . . . . 000 . 010 @atom_st
+amoor_b01000 . . . . 000 . 010 @atom_st
+amomin_b   1 . . . . 000 . 010 @atom_st
+amomax_b   10100 . . . . 000 . 010 @atom_st
+amominu_b  11000 . . . . 000 . 010 @atom_st
+amomaxu_b  11100 . . . . 000 . 010 @atom_st
+amocas_b   00101 . . . . 000 . 010 @atom_st
+amoswap_h  1 . . . . 001 . 010 @atom_st
+amoadd_h   0 . . . . 001 . 010 @atom_st
+amoxor_h   00100 . . . . 001 . 010 @atom_st
+amoand_h   01100 . . . . 001 . 010 @atom_st
+amoor_h01000 . . . . 001 . 010 @atom_st
+amomin_h   1 . . . . 001 . 010 @atom_st
+amomax_h   10100 . . . . 001 . 010 @atom_st
+amominu_h  11000 . . . . 001 . 010 @atom_st
+amomaxu_h  11100 . . . . 001 . 010 @atom_st
+amocas_h   00101 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
new file mode 100644
index 00..74f43bb95a
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -0,0 +1,149 @@
+/*
+ * RISC-V translation routines for the Zabha Standard Extension.
+ *
+ * Copyright (c) 2023 Rivos Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZABHA(ctx) do { \
+if (!ctx->cfg_ptr->ext_zabha) { \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_ZA

Re: [PATCH RFC] target: riscv: Add Svvptc extension support

2024-02-20 Thread Alexandre Ghiti
Hi Andrew,

Sorry for the very late reply, I was (and still am) off!

On Tue, Feb 13, 2024 at 4:33 PM Andrew Jones  wrote:
>
> On Tue, Feb 13, 2024 at 03:53:08PM +0100, Alexandre Ghiti wrote:
> > The Svvptc extension describes a uarch that does not cache invalid TLB
> > entries: that's the case for qemu so there is nothing particular to
> > implement other than the introduction of this extension, which is done
> > here.
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >
> > That's an RFC since the extension has not been ratified yet.
>
> Hi Alex,
>
> No need for the RFC tag. You can add not-yet-ratified extension support
> to QEMU as long as the CPU property is off by default (as you've done)
> and you add it to the riscv_cpu_experimental_exts[] array with an "x-"
> prefix on its property name.
>

I'll do that next week then,

Thanks,

Alex

> Thanks,
> drew
>
> >
> >  target/riscv/cpu.c | 2 ++
> >  target/riscv/cpu_cfg.h | 1 +
> >  2 files changed, 3 insertions(+)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 1b8d001d23..4beb5d0350 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
> >  ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
> >  ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
> >  ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
> > +ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_12_0, ext_svvptc),
> >  ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
> >  ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
> >  ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
> > @@ -1467,6 +1468,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = 
> > {
> >  MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
> >  MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
> >  MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
> > +MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, false),
> >
> >  MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
> >  MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true),
> > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> > index 833bf58217..c973693b6e 100644
> > --- a/target/riscv/cpu_cfg.h
> > +++ b/target/riscv/cpu_cfg.h
> > @@ -77,6 +77,7 @@ struct RISCVCPUConfig {
> >  bool ext_svinval;
> >  bool ext_svnapot;
> >  bool ext_svpbmt;
> > +bool ext_svvptc;
> >  bool ext_zdinx;
> >  bool ext_zaamo;
> >  bool ext_zacas;
> > --
> > 2.39.2
> >
> >



[PATCH RFC] target: riscv: Add Svvptc extension support

2024-02-13 Thread Alexandre Ghiti
The Svvptc extension describes a uarch that does not cache invalid TLB
entries: that's the case for qemu so there is nothing particular to
implement other than the introduction of this extension, which is done
here.

Signed-off-by: Alexandre Ghiti 
---

That's an RFC since the extension has not been ratified yet.

 target/riscv/cpu.c | 2 ++
 target/riscv/cpu_cfg.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1b8d001d23..4beb5d0350 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
 ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
 ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_12_0, ext_svvptc),
 ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
 ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
 ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
@@ -1467,6 +1468,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
 MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
 MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
+MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, false),
 
 MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
 MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 833bf58217..c973693b6e 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -77,6 +77,7 @@ struct RISCVCPUConfig {
 bool ext_svinval;
 bool ext_svnapot;
 bool ext_svpbmt;
+bool ext_svvptc;
 bool ext_zdinx;
 bool ext_zaamo;
 bool ext_zacas;
-- 
2.39.2




Re: [PATCH v2] hw: riscv: Allow large kernels to boot by moving the initrd further away in RAM

2024-02-06 Thread Alexandre Ghiti
On Tue, Feb 6, 2024 at 9:39 PM Daniel Henrique Barboza
 wrote:
>
>
>
> On 2/6/24 12:40, Alexandre Ghiti wrote:
> > Currently, the initrd is placed at 128MB, which overlaps with the kernel
> > when it is large (for example syzbot kernels are). From the kernel side,
> > there is no reason we could not push the initrd further away in memory
> > to accommodate large kernels, so move the initrd at 512MB when possible.
> >
> > The ideal solution would have been to place the initrd based on the
> > kernel size but we actually can't since the bss size is not known when
> > the image is loaded by load_image_targphys_as() and the initrd would
> > then overlap with this section.
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
>
> Reviewed-by: Daniel Henrique Barboza 

Thanks for your help!

Alex

>
> >
> > Changes in v2:
> > - Fix typos in commit log (Daniel) and title
> > - Added to the commit log why using the kernel size does not work
> >(Daniel)
> >
> >   hw/riscv/boot.c | 12 ++--
> >   1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> > index 0ffca05189..9a367af2fa 100644
> > --- a/hw/riscv/boot.c
> > +++ b/hw/riscv/boot.c
> > @@ -188,13 +188,13 @@ static void riscv_load_initrd(MachineState *machine, 
> > uint64_t kernel_entry)
> >* kernel is uncompressed it will not clobber the initrd. However
> >* on boards without much RAM we must ensure that we still leave
> >* enough room for a decent sized initrd, and on boards with large
> > - * amounts of RAM we must avoid the initrd being so far up in RAM
> > - * that it is outside lowmem and inaccessible to the kernel.
> > - * So for boards with less  than 256MB of RAM we put the initrd
> > - * halfway into RAM, and for boards with 256MB of RAM or more we put
> > - * the initrd at 128MB.
> > + * amounts of RAM, we put the initrd at 512MB to allow large kernels
> > + * to boot.
> > + * So for boards with less than 1GB of RAM we put the initrd
> > + * halfway into RAM, and for boards with 1GB of RAM or more we put
> > + * the initrd at 512MB.
> >*/
> > -start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
> > +start = kernel_entry + MIN(mem_size / 2, 512 * MiB);
> >
> >   size = load_ramdisk(filename, start, mem_size - start);
> >   if (size == -1) {



[PATCH v2] hw: riscv: Allow large kernels to boot by moving the initrd further away in RAM

2024-02-06 Thread Alexandre Ghiti
Currently, the initrd is placed at 128MB, which overlaps with the kernel
when it is large (for example syzbot kernels are). From the kernel side,
there is no reason we could not push the initrd further away in memory
to accommodate large kernels, so move the initrd at 512MB when possible.

The ideal solution would have been to place the initrd based on the
kernel size but we actually can't since the bss size is not known when
the image is loaded by load_image_targphys_as() and the initrd would
then overlap with this section.

Signed-off-by: Alexandre Ghiti 
---

Changes in v2:
- Fix typos in commit log (Daniel) and title
- Added to the commit log why using the kernel size does not work
  (Daniel)

 hw/riscv/boot.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 0ffca05189..9a367af2fa 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -188,13 +188,13 @@ static void riscv_load_initrd(MachineState *machine, 
uint64_t kernel_entry)
  * kernel is uncompressed it will not clobber the initrd. However
  * on boards without much RAM we must ensure that we still leave
  * enough room for a decent sized initrd, and on boards with large
- * amounts of RAM we must avoid the initrd being so far up in RAM
- * that it is outside lowmem and inaccessible to the kernel.
- * So for boards with less  than 256MB of RAM we put the initrd
- * halfway into RAM, and for boards with 256MB of RAM or more we put
- * the initrd at 128MB.
+ * amounts of RAM, we put the initrd at 512MB to allow large kernels
+ * to boot.
+ * So for boards with less than 1GB of RAM we put the initrd
+ * halfway into RAM, and for boards with 1GB of RAM or more we put
+ * the initrd at 512MB.
  */
-start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
+start = kernel_entry + MIN(mem_size / 2, 512 * MiB);
 
 size = load_ramdisk(filename, start, mem_size - start);
 if (size == -1) {
-- 
2.39.2




Re: [PATCH] hw: riscv: Allow large kernels to boot by moving the initrd further way in RAM

2024-02-06 Thread Alexandre Ghiti
Hi Daniel,

On Mon, Feb 5, 2024 at 2:36 PM Alexandre Ghiti  wrote:
>
> Hi Daniel,
>
> On Mon, Feb 5, 2024 at 1:17 PM Daniel Henrique Barboza
>  wrote:
> >
> >
> >
> > On 2/5/24 04:00, Alexandre Ghiti wrote:
> > > Currently, the initrd is placed at 128MB, which overlaps with the kernel
> > > when it is large (for example syzbot kernels are). From the kernel side,
> > > there is no reason we could not push the initrd further away in memory
> > > to accomodate large kernels, so move the initrd at 512MB when possible.
> >
> > typo: accommodate
> >
> > >
> > > Signed-off-by: Alexandre Ghiti 
> > > ---
> >
> > Patch looks good - just tested with an Ubuntu guest and nothing bad 
> > happened.
> >
> > But I wonder ... what if there's an even bigger kernel we have to deal with?
> > Move initrd even further away to fit it in?
> >
> > Instead of making assumptions about where initrd starts, we could grab the 
> > kernel
> > size loaded in the board and use it as a reference. This would be done by 
> > storing
> > the return of load_elf_ram_sym/load_uimage_as/load_image_targphys_as from
> > riscv_load_kernel() an passing as argument to riscv_load_initrd().

So this does not work because the size returned by
load_image_targphys_as() does not take into account the size of the
BSS sections (and I guess other NOBITS sections) and then we end up
loading the initrd there. I'm a bit surprised though because arm64
does just that 
https://elixir.bootlin.com/qemu/latest/source/hw/arm/boot.c#L1034.
I also tried using the highaddr parameter, but that gives the same
result. We could parse the Image header (a PE header) to get the
"Virtual Size" of the .data section, but I did not find any PE header
parser in qemu, so that would be overkill?

Any idea?

Thanks,

Alex

> >
> > initrd start would then be:
> >
> >  start = kernel_entry + MIN(mem_size / 2, kernel_size);
> >
> > However, I believe we would like to keep the existing 128Mb minimum initrd 
> > start,
> > even if the kernel is smaller than 128Mb, to avoid breaking existing 
> > configs that
> > might be making this assumption. initrd start would then become:
> >
> >
> >  start = kernel_entry + MIN(mem_size / 2, MAX(kernel_size, 128 * MiB));
>
> Great, I agree with you, thanks for the pointers. I'll just align the
> size on a 2MB boundary to make sure the kernel mapping (which in the
> case of Linux uses PMD) does not overlap with the initrd.
>
> I'll get back soon with a v2.
>
> Thanks again,
>
> Alex
>
> >
> >
> >
> > Thanks,
> >
> >
> >
> > Daniel
> >
> >
> > >   hw/riscv/boot.c | 12 ++--
> > >   1 file changed, 6 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> > > index 0ffca05189..9a367af2fa 100644
> > > --- a/hw/riscv/boot.c
> > > +++ b/hw/riscv/boot.c
> > > @@ -188,13 +188,13 @@ static void riscv_load_initrd(MachineState 
> > > *machine, uint64_t kernel_entry)
> > >* kernel is uncompressed it will not clobber the initrd. However
> > >* on boards without much RAM we must ensure that we still leave
> > >* enough room for a decent sized initrd, and on boards with large
> > > - * amounts of RAM we must avoid the initrd being so far up in RAM
> > > - * that it is outside lowmem and inaccessible to the kernel.
> > > - * So for boards with less  than 256MB of RAM we put the initrd
> > > - * halfway into RAM, and for boards with 256MB of RAM or more we put
> > > - * the initrd at 128MB.
> > > + * amounts of RAM, we put the initrd at 512MB to allow large kernels
> > > + * to boot.
> > > + * So for boards with less than 1GB of RAM we put the initrd
> > > + * halfway into RAM, and for boards with 1GB of RAM or more we put
> > > + * the initrd at 512MB.
> > >*/
> > > -start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
> > > +start = kernel_entry + MIN(mem_size / 2, 512 * MiB);
> > >
> > >   size = load_ramdisk(filename, start, mem_size - start);
> > >   if (size == -1) {



Re: [PATCH] hw: riscv: Allow large kernels to boot by moving the initrd further way in RAM

2024-02-05 Thread Alexandre Ghiti
Hi Daniel,

On Mon, Feb 5, 2024 at 1:17 PM Daniel Henrique Barboza
 wrote:
>
>
>
> On 2/5/24 04:00, Alexandre Ghiti wrote:
> > Currently, the initrd is placed at 128MB, which overlaps with the kernel
> > when it is large (for example syzbot kernels are). From the kernel side,
> > there is no reason we could not push the initrd further away in memory
> > to accomodate large kernels, so move the initrd at 512MB when possible.
>
> typo: accommodate
>
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
>
> Patch looks good - just tested with an Ubuntu guest and nothing bad happened.
>
> But I wonder ... what if there's an even bigger kernel we have to deal with?
> Move initrd even further away to fit it in?
>
> Instead of making assumptions about where initrd starts, we could grab the 
> kernel
> size loaded in the board and use it as a reference. This would be done by 
> storing
> the return of load_elf_ram_sym/load_uimage_as/load_image_targphys_as from
> riscv_load_kernel() an passing as argument to riscv_load_initrd().
>
> initrd start would then be:
>
>  start = kernel_entry + MIN(mem_size / 2, kernel_size);
>
> However, I believe we would like to keep the existing 128Mb minimum initrd 
> start,
> even if the kernel is smaller than 128Mb, to avoid breaking existing configs 
> that
> might be making this assumption. initrd start would then become:
>
>
>  start = kernel_entry + MIN(mem_size / 2, MAX(kernel_size, 128 * MiB));

Great, I agree with you, thanks for the pointers. I'll just align the
size on a 2MB boundary to make sure the kernel mapping (which in the
case of Linux uses PMD) does not overlap with the initrd.

I'll get back soon with a v2.

Thanks again,

Alex

>
>
>
> Thanks,
>
>
>
> Daniel
>
>
> >   hw/riscv/boot.c | 12 ++--
> >   1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> > index 0ffca05189..9a367af2fa 100644
> > --- a/hw/riscv/boot.c
> > +++ b/hw/riscv/boot.c
> > @@ -188,13 +188,13 @@ static void riscv_load_initrd(MachineState *machine, 
> > uint64_t kernel_entry)
> >* kernel is uncompressed it will not clobber the initrd. However
> >* on boards without much RAM we must ensure that we still leave
> >* enough room for a decent sized initrd, and on boards with large
> > - * amounts of RAM we must avoid the initrd being so far up in RAM
> > - * that it is outside lowmem and inaccessible to the kernel.
> > - * So for boards with less  than 256MB of RAM we put the initrd
> > - * halfway into RAM, and for boards with 256MB of RAM or more we put
> > - * the initrd at 128MB.
> > + * amounts of RAM, we put the initrd at 512MB to allow large kernels
> > + * to boot.
> > + * So for boards with less than 1GB of RAM we put the initrd
> > + * halfway into RAM, and for boards with 1GB of RAM or more we put
> > + * the initrd at 512MB.
> >*/
> > -start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
> > +start = kernel_entry + MIN(mem_size / 2, 512 * MiB);
> >
> >   size = load_ramdisk(filename, start, mem_size - start);
> >   if (size == -1) {



[PATCH] hw: riscv: Allow large kernels to boot by moving the initrd further way in RAM

2024-02-04 Thread Alexandre Ghiti
Currently, the initrd is placed at 128MB, which overlaps with the kernel
when it is large (for example syzbot kernels are). From the kernel side,
there is no reason we could not push the initrd further away in memory
to accomodate large kernels, so move the initrd at 512MB when possible.

Signed-off-by: Alexandre Ghiti 
---
 hw/riscv/boot.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 0ffca05189..9a367af2fa 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -188,13 +188,13 @@ static void riscv_load_initrd(MachineState *machine, 
uint64_t kernel_entry)
  * kernel is uncompressed it will not clobber the initrd. However
  * on boards without much RAM we must ensure that we still leave
  * enough room for a decent sized initrd, and on boards with large
- * amounts of RAM we must avoid the initrd being so far up in RAM
- * that it is outside lowmem and inaccessible to the kernel.
- * So for boards with less  than 256MB of RAM we put the initrd
- * halfway into RAM, and for boards with 256MB of RAM or more we put
- * the initrd at 128MB.
+ * amounts of RAM, we put the initrd at 512MB to allow large kernels
+ * to boot.
+ * So for boards with less than 1GB of RAM we put the initrd
+ * halfway into RAM, and for boards with 1GB of RAM or more we put
+ * the initrd at 512MB.
  */
-start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
+start = kernel_entry + MIN(mem_size / 2, 512 * MiB);
 
 size = load_ramdisk(filename, start, mem_size - start);
 if (size == -1) {
-- 
2.39.2




Re: [PATCH v2] riscv: Make sure an exception is raised if a pte is malformed

2023-04-20 Thread Alexandre Ghiti
On Thu, Apr 20, 2023 at 1:31 AM Alistair Francis  wrote:
>
> On Wed, Apr 19, 2023 at 8:48 PM Alexandre Ghiti  
> wrote:
> >
> > As per the privileged specification, in 64-bit, if any of the pte reserved
> > bits 60-54 is set an exception should be triggered, and the same applies to
> > napot/pbmt bits if those extensions are not enabled
> > (see 4.4.1, "Addressing and Memory Protection").
> >
> > Reported-by: Andrea Parri 
> > Signed-off-by: Alexandre Ghiti 
>
> Thanks for the patch
>
> Do you mind sending a v3 rebased on
> https://github.com/alistair23/qemu/tree/riscv-to-apply.next ?

Sure, I have just sent the v3.

Thanks for your quick review!

Alex

>
> Alistair
>
> > ---
> >  target/riscv/cpu_bits.h   |  1 +
> >  target/riscv/cpu_helper.c | 15 +++
> >  2 files changed, 12 insertions(+), 4 deletions(-)
> >
> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> > index fca7ef0cef..8d9ba2ce11 100644
> > --- a/target/riscv/cpu_bits.h
> > +++ b/target/riscv/cpu_bits.h
> > @@ -640,6 +640,7 @@ typedef enum {
> >  #define PTE_SOFT0x300 /* Reserved for Software */
> >  #define PTE_PBMT0x6000ULL /* Page-based memory 
> > types */
> >  #define PTE_N   0x8000ULL /* NAPOT translation */
> > +#define PTE_RESERVED0x1FC0ULL /* Reserved bits */
> >  #define PTE_ATTR(PTE_N | PTE_PBMT) /* All attributes bits */
> >
> >  /* Page table PPN shift amount */
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index f88c503cf4..8dc832d1bb 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -946,13 +946,20 @@ restart:
> >
> >  if (riscv_cpu_sxl(env) == MXL_RV32) {
> >  ppn = pte >> PTE_PPN_SHIFT;
> > -} else if (pbmte || cpu->cfg.ext_svnapot) {
> > -ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
> >  } else {
> > -ppn = pte >> PTE_PPN_SHIFT;
> > -if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
> > +if (pte & PTE_RESERVED) {
> > +return TRANSLATE_FAIL;
> > +}
> > +
> > +if (!pbmte && (pte & PTE_PBMT)) {
> >  return TRANSLATE_FAIL;
> >  }
> > +
> > +if (!cpu->cfg.ext_svnapot && (pte & PTE_N)) {
> > +return TRANSLATE_FAIL;
> > +}
> > +
> > +ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
> >  }
> >
> >  if (!(pte & PTE_V)) {
> > --
> > 2.37.2
> >
> >



[PATCH v3] riscv: Make sure an exception is raised if a pte is malformed

2023-04-20 Thread Alexandre Ghiti
As per the specification, in 64-bit, if any of the pte reserved bits
60-54 is set an exception should be triggered (see 4.4.1, "Addressing and
Memory Protection"). In addition, we must check the napot/pbmt bits are
not set if those extensions are not active.

Reported-by: Andrea Parri 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
---
Changes in v3:
- Rebase on top of https://github.com/alistair23/qemu/tree/riscv-to-apply.next

Changes in v2:
- Handle napot and pbmt exception

 target/riscv/cpu_bits.h   |  1 +
 target/riscv/cpu_helper.c | 15 +++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fb63b8e125..59f0ffd9e1 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -644,6 +644,7 @@ typedef enum {
 #define PTE_SOFT0x300 /* Reserved for Software */
 #define PTE_PBMT0x6000ULL /* Page-based memory types */
 #define PTE_N   0x8000ULL /* NAPOT translation */
+#define PTE_RESERVED0x1FC0ULL /* Reserved bits */
 #define PTE_ATTR(PTE_N | PTE_PBMT) /* All attributes bits */
 
 /* Page table PPN shift amount */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b68dcfe7b6..57d04385f1 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -927,13 +927,20 @@ restart:
 
 if (riscv_cpu_sxl(env) == MXL_RV32) {
 ppn = pte >> PTE_PPN_SHIFT;
-} else if (pbmte || riscv_cpu_cfg(env)->ext_svnapot) {
-ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
 } else {
-ppn = pte >> PTE_PPN_SHIFT;
-if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
+if (pte & PTE_RESERVED) {
+return TRANSLATE_FAIL;
+}
+
+if (!pbmte && (pte & PTE_PBMT)) {
 return TRANSLATE_FAIL;
 }
+
+if (!riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
+return TRANSLATE_FAIL;
+}
+
+ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
 }
 
 if (!(pte & PTE_V)) {
-- 
2.37.2




[PATCH v2] riscv: Make sure an exception is raised if a pte is malformed

2023-04-19 Thread Alexandre Ghiti
As per the privileged specification, in 64-bit, if any of the pte reserved
bits 60-54 is set an exception should be triggered, and the same applies to
napot/pbmt bits if those extensions are not enabled
(see 4.4.1, "Addressing and Memory Protection").

Reported-by: Andrea Parri 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu_bits.h   |  1 +
 target/riscv/cpu_helper.c | 15 +++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fca7ef0cef..8d9ba2ce11 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -640,6 +640,7 @@ typedef enum {
 #define PTE_SOFT0x300 /* Reserved for Software */
 #define PTE_PBMT0x6000ULL /* Page-based memory types */
 #define PTE_N   0x8000ULL /* NAPOT translation */
+#define PTE_RESERVED0x1FC0ULL /* Reserved bits */
 #define PTE_ATTR(PTE_N | PTE_PBMT) /* All attributes bits */
 
 /* Page table PPN shift amount */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f88c503cf4..8dc832d1bb 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -946,13 +946,20 @@ restart:
 
 if (riscv_cpu_sxl(env) == MXL_RV32) {
 ppn = pte >> PTE_PPN_SHIFT;
-} else if (pbmte || cpu->cfg.ext_svnapot) {
-ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
 } else {
-ppn = pte >> PTE_PPN_SHIFT;
-if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
+if (pte & PTE_RESERVED) {
+return TRANSLATE_FAIL;
+}
+
+if (!pbmte && (pte & PTE_PBMT)) {
 return TRANSLATE_FAIL;
 }
+
+if (!cpu->cfg.ext_svnapot && (pte & PTE_N)) {
+return TRANSLATE_FAIL;
+}
+
+ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
 }
 
 if (!(pte & PTE_V)) {
-- 
2.37.2




Re: [PATCH] riscv: Raise an exception if pte reserved bits are not cleared

2023-04-18 Thread Alexandre Ghiti
Hi Alistair,

Sorry for the late reply, I was on PTO.

On Tue, Apr 18, 2023 at 4:22 AM Alistair Francis  wrote:
>
> On Mon, Apr 17, 2023 at 8:47 PM Andrea Parri  wrote:
> >
> > Hi Alistair,
> >
> > > > @@ -936,6 +936,11 @@ restart:
> > > >  return TRANSLATE_FAIL;
> > > >  }
> > > >
> > > > +/* PTE reserved bits must be cleared otherwise an exception is 
> > > > raised */
> > > > +if (riscv_cpu_mxl(env) == MXL_RV64 && (pte & PTE_RESERVED)) {
> > > > +return TRANSLATE_FAIL;
> > > > +}
> > >
> > > Isn't this caught by our existing check?
> > >
> > > if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
> > > return TRANSLATE_FAIL;
> > > }
> >
> > Thanks for checking this out.  AFAICS, the existing check/code doesn't
> > work if either svnapot or svpbmt are active.
>
> svpbmt uses some of the reserved fields right?

No, pbmt uses bits 61-62 and napot uses bit 63, this patchset deals
with bits 54-60.

>
> I'm not sure why svnapot excludes the check. The correct fix should be
> to change this check as required (instead of adding a new check).

napot and pbmt exclude the check because PTE_PPN_MASK only deals with
PPN bits, and then ~PTE_PPN_MASK is too large as it tests the
PBMT/NAPOT bits AND the reserved bits.
But you made me notice that the pbmt/napot check isn't right either,
as the napot bit could be set if !napot and then an exception would
not be triggered (the same for pbmt).

Let me check this completely and come back with a proper fix for that too.

Thanks!

Alex

>
> Alistair
>
> >
> > Please let me know if you need other information.
> >
> >   Andrea



[PATCH] riscv: Raise an exception if pte reserved bits are not cleared

2023-04-12 Thread Alexandre Ghiti
As per the specification, in 64-bit, if any of the pte reserved bits 60-54
is set, an exception should be triggered (see 4.4.1, "Addressing and Memory
Protection"), so implement this behaviour in the address translation process.

Reported-by: Andrea Parri 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu_bits.h   | 1 +
 target/riscv/cpu_helper.c | 5 +
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fca7ef0cef..8d9ba2ce11 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -640,6 +640,7 @@ typedef enum {
 #define PTE_SOFT0x300 /* Reserved for Software */
 #define PTE_PBMT0x6000ULL /* Page-based memory types */
 #define PTE_N   0x8000ULL /* NAPOT translation */
+#define PTE_RESERVED0x1FC0ULL /* Reserved bits */
 #define PTE_ATTR(PTE_N | PTE_PBMT) /* All attributes bits */
 
 /* Page table PPN shift amount */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f88c503cf4..39c323a865 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -936,6 +936,11 @@ restart:
 return TRANSLATE_FAIL;
 }
 
+/* PTE reserved bits must be cleared otherwise an exception is raised 
*/
+if (riscv_cpu_mxl(env) == MXL_RV64 && (pte & PTE_RESERVED)) {
+return TRANSLATE_FAIL;
+}
+
 bool pbmte = env->menvcfg & MENVCFG_PBMTE;
 bool hade = env->menvcfg & MENVCFG_HADE;
 
-- 
2.37.2




Re: [PATCH v11 0/5] riscv: Allow user to set the satp mode

2023-03-06 Thread Alexandre Ghiti
Hi Palmer,

On Mon, Mar 6, 2023 at 12:34 AM Palmer Dabbelt  wrote:
>
> On Fri, 03 Mar 2023 05:12:47 PST (-0800), alexgh...@rivosinc.com wrote:
> > This introduces new properties to allow the user to set the satp mode,
> > see patch 3 for full syntax. In addition, it prevents cpus to boot in a
> > satp mode they do not support (see patch 4).
> >
> > base-commit: commit c61d1a066cb6 ("Merge tag 'for-upstream' of
> > https://gitlab.com/bonzini/qemu into staging")
>
> I have that, but I still got some merge conflicts.  I've put that here
> <https://github.com/palmer-dabbelt/qemu/tree/set-satp> for now, pending
> Daniel's response below.

Weird, I have just tried again and it applied cleanly on the
base-commit I mentioned, I tried to cherry-pick a few patches, even
commit d4ea71170432 ("target/riscv: introduce riscv_cpu_cfg()") does
not break the merge.

Anyway, FWIW I checked the patches on the set-satp branch again, and
your merge seems ok.

>
> >
> > v11:
> > - rebase on top of master
> > - Added RB/AB from Frank and Alistair
> > - Use VM_1_10_XX directly instead of satp_mode_from_str, from Frank
> > - Set satp mode max for thead c906 to sv39
>
> Daniel: It looks like the feedback on v10 included dropping the first
> patch
> <https://lore.kernel.org/qemu-devel/66d80b94-5941-31f3-995f-e9666a91f...@ventanamicro.com/T/#macdb6c5232bd8c082966107d7b44aaaec9b29ad6>.
> Sorry if I'm just misunderstanding, but it looks to me like that patch
> is still useful and the v11 doesn't even build without it.

No, the first commit is a preparatory commit for the series, it is required.


>
> >
> > v10:
> > - Fix user mode build by surrounding satp handling with #ifndef
> >   CONFIG_USER_ONLY, Frank
> > - Fix AB/RB from Frank and Alistair
> >
> > v9:
> > - Move valid_vm[i] up, Andrew
> > - Fixed expansion of the bitmap map, Bin
> > - Rename set_satp_mode_default into set_satp_mode_default_map, Bin
> > - Remove outer parenthesis and alignment, Bin
> > - Fix qemu32 build failure, Bin
> > - Fixed a few typos, Bin
> > - Add RB from Andrew and Bin
> >
> > v8:
> > - Remove useless !map check, Andrew
> > - Add RB from Andrew
> >
> > v7:
> > - Expand map to contain all valid modes, Andrew
> > - Fix commit log for patch 3, Andrew
> > - Remove is_32_bit argument from set_satp_mode_default, Andrew
> > - Move and fixed comment, Andrew
> > - Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
> >   too early, Alex
> > - Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
> > - Use satp_mode directly instead of a string in
> >   set_satp_mode_max_supported, Andrew
> > - Swap the patch introducing supported bitmap and the patch that sets
> >   sv57 in the dt, Andrew
> > - Add various RB from Andrew and Alistair, thanks
> >
> > v6:
> > - Remove the valid_vm check in validate_vm and add it to the finalize 
> > function
> >   so that map already contains the constraint, Alex
> > - Add forgotten mbare to satp_mode_from_str, Alex
> > - Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
> > - Only add satp mode properties corresponding to the cpu, and then remove 
> > the
> >   check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
> >   Andrew/Alistair/Alex
> > - Move mmu-type setting to its own patch, Andrew
> > - patch 5 is new and is a fix, Alex
> >
> > v5:
> > - Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
> >   suggested by Andrew
> > - Split the v4 patch into 2 patches as suggested by Andrew
> > - Lot of other minor corrections, from Andrew
> > - Set the satp mode N by disabling the satp mode N + 1
> > - Add a helper to set satp mode from a string, as suggested by Frank
> >
> > v4:
> > - Use custom boolean properties instead of OnOffAuto properties, based
> >   on ARMVQMap, as suggested by Andrew
> >
> > v3:
> > - Free sv_name as pointed by Bin
> > - Replace satp-mode with boolean properties as suggested by Andrew
> > - Removed RB from Atish as the patch considerably changed
> >
> > v2:
> > - Use error_setg + return as suggested by Alistair
> > - Add RB from Atish
> > - Fixed checkpatch issues missed in v1
> > - Replaced Ludovic email address with the rivos one
> >
> > Alexandre Ghiti (5):
> >   riscv: Pass Object to register_cpu_props instead of DeviceState
> >   riscv: Change type of valid_vm_1_10_[32|64] to bool
> >   riscv: Allow user to set the satp mode
> >   riscv: Introduce satp mode hw capabilities
> >   riscv: Correctly set the device-tree entry 'mmu-type'
> >
> >  hw/riscv/virt.c|  19 +--
> >  target/riscv/cpu.c | 288 ++---
> >  target/riscv/cpu.h |  25 
> >  target/riscv/csr.c |  29 +++--
> >  4 files changed, 323 insertions(+), 38 deletions(-)



[PATCH v11 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-03-03 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: Frank Chang 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 86c4adc0c9..59922d6965 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,8 +228,9 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *ms = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 bool is_32_bit = riscv_is_32bit(>soc[0]);
+uint8_t satp_mode_max;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -237,14 +238,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(ms->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(ms->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v11 4/5] riscv: Introduce satp mode hw capabilities

2023-03-03 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the guest
  OS.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 93 ++
 target/riscv/cpu.h |  8 +++-
 2 files changed, 75 insertions(+), 26 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6de2ca0eaa..d4584299db 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -306,17 +306,24 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default_map(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+uint8_t satp_mode)
 {
 bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
 
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |= (1 << (rv32 ? VM_1_10_SV32 : VM_1_10_SV57));
-} else {
-cpu->cfg.satp_mode.map |= (1 << VM_1_10_MBARE);
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
+
+/* Set the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
+}
 #endif
 
 static void riscv_any_cpu_init(Object *obj)
@@ -327,6 +334,13 @@ static void riscv_any_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
+
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj),
+riscv_cpu_mxl(_CPU(obj)->env) == MXL_RV32 ?
+VM_1_10_SV32 : VM_1_10_SV57);
+#endif
+
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
 }
@@ -340,6 +354,9 @@ static void rv64_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
+#endif
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -348,6 +365,9 @@ static void rv64_sifive_u_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
+#endif
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -359,6 +379,9 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
 }
 
 static void rv64_thead_c906_cpu_init(Object *obj)
@@ -388,6 +411,9 @@ static void rv64_thead_c906_cpu_init(Object *obj)
 cpu->cfg.ext_xtheadsync = true;
 
 cpu->cfg.mvendorid = THEAD_VENDOR_ID;
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(cpu, VM_1_10_SV39);
+#endif
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -404,6 +430,9 @@ static void rv128_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
+#endif
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -414,6 +443,9 @@ static void rv32_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
+#endif
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -422,6 +454,9 @@ static void rv32_sifive_u_cpu_init(Object *obj)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_support

[PATCH v11 3/5] riscv: Allow user to set the satp mode

2023-03-03 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
Acked-by: Alistair Francis 
Reviewed-by: Frank Chang 
---
 target/riscv/cpu.c | 214 +
 target/riscv/cpu.h |  21 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 240 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5dc11d6670..6de2ca0eaa 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -28,6 +28,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -242,6 +243,82 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+#ifndef CONFIG_USER_ONLY
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |= (1 << (rv32 ? VM_1_10_SV32 : VM_1_10_SV57));
+} else {
+cpu->cfg.satp_mode.map |= (1 << VM_1_10_MBARE);
+}
+}
+#endif
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -870,6 +947,87 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU 
*cpu, Error **errp)
 set_misa(env, env->misa_mxl, ext);
 }
 
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+uint8_t satp_mode_max;
+
+if (cpu->cfg.satp_mode.map == 0) {
+if (cpu->cfg.satp_mode.init == 0) {
+/* If unset by the user, we fallback to the default satp mode. */
+set_satp_mode_default_map(cpu);
+} else {
+/*
+ * Find the lowest level that was disabled and then enable the
+ * fir

[PATCH v11 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-03-03 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Suggested-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: Frank Chang 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 1b0a0c1693..163eb3b82b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1123,16 +1123,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1215,7 +1215,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2641,7 +2641,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




[PATCH v11 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-03-03 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9eb748a283..5dc11d6670 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -213,7 +213,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -251,7 +251,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -260,7 +260,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -269,7 +269,7 @@ static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 }
 
@@ -279,7 +279,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 RISCVCPU *cpu = RISCV_CPU(obj);
 
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
 }
@@ -324,7 +324,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -334,7 +334,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void rv32_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 }
 
@@ -353,7 +353,7 @@ static void rv32_sifive_e_cpu_init(Object *obj)
 RISCVCPU *cpu = RISCV_CPU(obj);
 
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
 }
@@ -364,7 +364,7 @@ static void rv32_ibex_cpu_init(Object *obj)
 RISCVCPU *cpu = RISCV_CPU(obj);
 
 set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_11_0);
 cpu->cfg.mmu = false;
 cpu->cfg.epmp = true;
@@ -376,7 +376,7 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
 RISCVCPU *cpu = RISCV_CPU(obj);
 
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
 }
@@ -391,7 +391,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1161,11 +1161,12 @@ static Property riscv_cpu_extensions[] = {
  * properties and leave. env.misa_ext = 0 means that we want
  * all the default properties to be registered.
  */
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
-RISCVCPU *cpu = RISCV_CPU(OBJECT(dev));
+RISCVCPU *cpu = RISCV_CPU(obj);
 uint32_t misa_ext = cpu->env.misa_ext;
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 /*
  * If misa_ext is not zero, set cfg properties now to
-- 
2.37.2




[PATCH v11 0/5] riscv: Allow user to set the satp mode

2023-03-03 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 4).

base-commit: commit c61d1a066cb6 ("Merge tag 'for-upstream' of
https://gitlab.com/bonzini/qemu into staging")

v11:
- rebase on top of master
- Added RB/AB from Frank and Alistair
- Use VM_1_10_XX directly instead of satp_mode_from_str, from Frank
- Set satp mode max for thead c906 to sv39

v10:
- Fix user mode build by surrounding satp handling with #ifndef
  CONFIG_USER_ONLY, Frank
- Fix AB/RB from Frank and Alistair

v9:
- Move valid_vm[i] up, Andrew
- Fixed expansion of the bitmap map, Bin
- Rename set_satp_mode_default into set_satp_mode_default_map, Bin
- Remove outer parenthesis and alignment, Bin
- Fix qemu32 build failure, Bin
- Fixed a few typos, Bin
- Add RB from Andrew and Bin

v8:
- Remove useless !map check, Andrew
- Add RB from Andrew

v7:
- Expand map to contain all valid modes, Andrew
- Fix commit log for patch 3, Andrew
- Remove is_32_bit argument from set_satp_mode_default, Andrew
- Move and fixed comment, Andrew
- Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
  too early, Alex
- Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
- Use satp_mode directly instead of a string in
  set_satp_mode_max_supported, Andrew
- Swap the patch introducing supported bitmap and the patch that sets
  sv57 in the dt, Andrew
- Add various RB from Andrew and Alistair, thanks

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Introduce satp mode hw capabilities
  riscv: Correctly set the device-tree entry 'mmu-type'

 hw/riscv/virt.c|  19 +--
 target/riscv/cpu.c | 288 ++---
 target/riscv/cpu.h |  25 
 target/riscv/csr.c |  29 +++--
 4 files changed, 323 insertions(+), 38 deletions(-)

-- 
2.37.2




Re: [PATCH v10 0/5] riscv: Allow user to set the satp mode

2023-03-03 Thread Alexandre Ghiti
Hi Daniel,

On Thu, Mar 2, 2023 at 10:03 PM Daniel Henrique Barboza
 wrote:
>
>
>
> On 3/2/23 14:42, Daniel Henrique Barboza wrote:
> > Hi Palmer,
> >
> > I think this series can be picked. All patches are fully acked. There is a 
> > nit
> > in patch 3 that I believe you can choose to fix in-tree if you want to.
>
> Update: patch 1 is not applicable anymore due to changes in current master. 
> All
> other patches have conflicts as well.
>
> I guess it's easier to Alexandre to rebase and re-send it when possible. 
> Frank's
> comment in patch 3 can also be handled during the process.

Sure I'll do that today,

Thanks,

Alex

>
>
> Thanks,
>
>
> Daniel
>
>
>
> >
> >
> > Thanks,
> >
> >
> > Daniel
> >
> >
> >
> >
> > On 2/3/23 02:58, Alexandre Ghiti wrote:
> >> This introduces new properties to allow the user to set the satp mode,
> >> see patch 3 for full syntax. In addition, it prevents cpus to boot in a
> >> satp mode they do not support (see patch 4).
> >>
> >> base-commit: commit 75cc28648574 ("configure: remove
> >> backwards-compatibility code"
> >>
> >> v10:
> >> - Fix user mode build by surrounding satp handling with #ifndef
> >>CONFIG_USER_ONLY, Frank
> >> - Fix AB/RB from Frank and Alistair
> >>
> >> v9:
> >> - Move valid_vm[i] up, Andrew
> >> - Fixed expansion of the bitmap map, Bin
> >> - Rename set_satp_mode_default into set_satp_mode_default_map, Bin
> >> - Remove outer parenthesis and alignment, Bin
> >> - Fix qemu32 build failure, Bin
> >> - Fixed a few typos, Bin
> >> - Add RB from Andrew and Bin
> >>
> >> v8:
> >> - Remove useless !map check, Andrew
> >> - Add RB from Andrew
> >>
> >> v7:
> >> - Expand map to contain all valid modes, Andrew
> >> - Fix commit log for patch 3, Andrew
> >> - Remove is_32_bit argument from set_satp_mode_default, Andrew
> >> - Move and fixed comment, Andrew
> >> - Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
> >>too early, Alex
> >> - Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
> >> - Use satp_mode directly instead of a string in
> >>set_satp_mode_max_supported, Andrew
> >> - Swap the patch introducing supported bitmap and the patch that sets
> >>sv57 in the dt, Andrew
> >> - Add various RB from Andrew and Alistair, thanks
> >>
> >> v6:
> >> - Remove the valid_vm check in validate_vm and add it to the finalize 
> >> function
> >>so that map already contains the constraint, Alex
> >> - Add forgotten mbare to satp_mode_from_str, Alex
> >> - Move satp mode properties handling to riscv_cpu_satp_mode_finalize, 
> >> Andrew
> >> - Only add satp mode properties corresponding to the cpu, and then remove 
> >> the
> >>check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
> >>Andrew/Alistair/Alex
> >> - Move mmu-type setting to its own patch, Andrew
> >> - patch 5 is new and is a fix, Alex
> >>
> >> v5:
> >> - Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
> >>suggested by Andrew
> >> - Split the v4 patch into 2 patches as suggested by Andrew
> >> - Lot of other minor corrections, from Andrew
> >> - Set the satp mode N by disabling the satp mode N + 1
> >> - Add a helper to set satp mode from a string, as suggested by Frank
> >>
> >> v4:
> >> - Use custom boolean properties instead of OnOffAuto properties, based
> >>on ARMVQMap, as suggested by Andrew
> >>
> >> v3:
> >> - Free sv_name as pointed by Bin
> >> - Replace satp-mode with boolean properties as suggested by Andrew
> >> - Removed RB from Atish as the patch considerably changed
> >>
> >> v2:
> >> - Use error_setg + return as suggested by Alistair
> >> - Add RB from Atish
> >> - Fixed checkpatch issues missed in v1
> >> - Replaced Ludovic email address with the rivos one
> >>
> >> Alexandre Ghiti (5):
> >>riscv: Pass Object to register_cpu_props instead of DeviceState
> >>riscv: Change type of valid_vm_1_10_[32|64] to bool
> >>riscv: Allow user to set the satp mode
> >>riscv: Introduce satp mode hw capabilities
> >>riscv: Correctly set the device-tree entry 'mmu-type'
> >>
> >>   hw/riscv/virt.c|  19 ++--
> >>   target/riscv/cpu.c | 271 +++--
> >>   target/riscv/cpu.h |  25 +
> >>   target/riscv/csr.c |  29 +++--
> >>   4 files changed, 313 insertions(+), 31 deletions(-)
> >>



[PATCH v10 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-02-02 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: Frank Chang 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v10 4/5] riscv: Introduce satp mode hw capabilities

2023-02-02 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the guest
  OS.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 91 +-
 target/riscv/cpu.h |  8 +++-
 2 files changed, 72 insertions(+), 27 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 56057cf87c..7e9924ede9 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -293,18 +293,24 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default_map(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+uint8_t satp_mode)
 {
 bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
 
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |=
-(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
-} else {
-cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
+
+/* Set the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
+}
 #endif
 
 static void riscv_any_cpu_init(Object *obj)
@@ -315,6 +321,13 @@ static void riscv_any_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
+
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj),
+riscv_cpu_mxl(_CPU(obj)->env) == MXL_RV32 ?
+VM_1_10_SV32 : VM_1_10_SV57);
+#endif
+
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
 }
@@ -328,6 +341,9 @@ static void rv64_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
+#endif
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -335,6 +351,9 @@ static void rv64_sifive_u_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
+#endif
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -345,6 +364,9 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -361,6 +383,9 @@ static void rv128_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
+#endif
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -371,6 +396,9 @@ static void rv32_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
+#endif
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -378,6 +406,9 @@ static void rv32_sifive_u_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
+#endif
 }
 
 static void rv32_sifive_e_cpu_init(Object *obj)
@@ -388,6 +419,9 @@ static void rv32_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);

[PATCH v10 3/5] riscv: Allow user to set the satp mode

2023-02-02 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
Acked-by: Alistair Francis 
---
 target/riscv/cpu.c | 215 +
 target/riscv/cpu.h |  21 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 241 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..56057cf87c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,83 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+#ifndef CONFIG_USER_ONLY
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |=
+(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
+} else {
+cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+}
+}
+#endif
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -619,6 +697,87 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 }
 }
 
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+uint8_t satp_mode_max;
+
+if (cpu->cfg.satp_mode.map == 0) {
+if (cpu->cfg.satp_mode.init == 0) {
+/* If unset by the user, we fallback to the default satp mode. */
+set_satp_mode_default_map(cpu);
+} else {
+/*
+ * Find the lowest level that was disabled and then ena

[PATCH v10 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-02-02 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Suggested-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: Frank Chang 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c233e5..6b157806a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




[PATCH v10 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-02-02 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v10 0/5] riscv: Allow user to set the satp mode

2023-02-02 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 4).

base-commit: commit 75cc28648574 ("configure: remove
backwards-compatibility code"

v10:
- Fix user mode build by surrounding satp handling with #ifndef
  CONFIG_USER_ONLY, Frank
- Fix AB/RB from Frank and Alistair

v9:
- Move valid_vm[i] up, Andrew
- Fixed expansion of the bitmap map, Bin
- Rename set_satp_mode_default into set_satp_mode_default_map, Bin
- Remove outer parenthesis and alignment, Bin
- Fix qemu32 build failure, Bin
- Fixed a few typos, Bin
- Add RB from Andrew and Bin

v8:
- Remove useless !map check, Andrew
- Add RB from Andrew

v7:
- Expand map to contain all valid modes, Andrew
- Fix commit log for patch 3, Andrew
- Remove is_32_bit argument from set_satp_mode_default, Andrew
- Move and fixed comment, Andrew
- Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
  too early, Alex
- Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
- Use satp_mode directly instead of a string in
  set_satp_mode_max_supported, Andrew
- Swap the patch introducing supported bitmap and the patch that sets
  sv57 in the dt, Andrew
- Add various RB from Andrew and Alistair, thanks

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Introduce satp mode hw capabilities
  riscv: Correctly set the device-tree entry 'mmu-type'

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 271 +++--
 target/riscv/cpu.h |  25 +
 target/riscv/csr.c |  29 +++--
 4 files changed, 313 insertions(+), 31 deletions(-)

-- 
2.37.2




Re: [PATCH v9 4/5] riscv: Introduce satp mode hw capabilities

2023-02-02 Thread Alexandre Ghiti
Hi Frank,

On Wed, Feb 1, 2023 at 4:49 PM Frank Chang  wrote:
>
> On Tue, Jan 31, 2023 at 10:36 PM Alexandre Ghiti  
> wrote:
>>
>> Currently, the max satp mode is set with the only constraint that it must be
>> implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].
>>
>> But we actually need to add another level of constraint: what the hw is
>> actually capable of, because currently, a linux booting on a sifive-u54
>> boots in sv57 mode which is incompatible with the cpu's sv39 max
>> capability.
>>
>> So add a new bitmap to RISCVSATPMap which contains this capability and
>> initialize it in every XXX_cpu_init.
>>
>> Finally:
>> - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
>> - the CPU hw capabilities constrains what the user may select
>> - the user's selection then constrains what's available to the guest
>>   OS.
>>
>> Signed-off-by: Alexandre Ghiti 
>> Reviewed-by: Andrew Jones 
>> ---
>>  target/riscv/cpu.c | 79 +++---
>>  target/riscv/cpu.h |  8 +++--
>>  2 files changed, 60 insertions(+), 27 deletions(-)
>>
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index 3a7a1746aa..6dd76355ec 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
>> is_32_bit)
>>  g_assert_not_reached();
>>  }
>>
>> -/* Sets the satp mode to the max supported */
>> -static void set_satp_mode_default_map(RISCVCPU *cpu)
>> +static void set_satp_mode_max_supported(RISCVCPU *cpu,
>> +uint8_t satp_mode)
>>  {
>>  bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
>> +const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
>
>
> This will break user-mode QEMU.
> valid_vm_1_10_32 and valid_vm_1_10_64 are defined in !CONFIG_USER_ONLY 
> section.
> This issue also exists in patch 3.
> You have to move valid_vm_1_10_32 and valid_vm_1_10_64 out from 
> !CONFIG_USER_ONLY.

Indeed, good catch, thanks! Rather than moving valid_vm_1_10_[32|64],
I'm going to try to surround all the satp handling inside #ifdef
CONFIG_USER_ONLY. But if it's too cumbersome, I'll do as you suggest.

Thanks again,

Alex

>
> Regards,
> Frank Chang
>
>>
>> -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
>> -cpu->cfg.satp_mode.map |=
>> -(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
>> -} else {
>> -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
>> +for (int i = 0; i <= satp_mode; ++i) {
>> +if (valid_vm[i]) {
>> +cpu->cfg.satp_mode.supported |= (1 << i);
>> +}
>>  }
>>  }
>>
>> +/* Set the satp mode to the max supported */
>> +static void set_satp_mode_default_map(RISCVCPU *cpu)
>> +{
>> +cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
>> +}
>> +
>>  static void riscv_any_cpu_init(Object *obj)
>>  {
>>  CPURISCVState *env = _CPU(obj)->env;
>> +RISCVCPU *cpu = RISCV_CPU(obj);
>> +
>>  #if defined(TARGET_RISCV32)
>>  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
>> +set_satp_mode_max_supported(cpu, VM_1_10_SV32);
>>  #elif defined(TARGET_RISCV64)
>>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
>> +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
>>  #endif
>>  set_priv_version(env, PRIV_VERSION_1_12_0);
>>  register_cpu_props(obj);
>> @@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
>>  static void rv64_base_cpu_init(Object *obj)
>>  {
>>  CPURISCVState *env = _CPU(obj)->env;
>> +RISCVCPU *cpu = RISCV_CPU(obj);
>> +
>>  /* We set this in the realise function */
>>  set_misa(env, MXL_RV64, 0);
>>  register_cpu_props(obj);
>>  /* Set latest version of privileged specification */
>>  set_priv_version(env, PRIV_VERSION_1_12_0);
>> +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
>>  }
>>
>>  static void rv64_sifive_u_cpu_init(Object *obj)
>>  {
>>  CPURISCVState *env = _CPU(obj)->env;
>> +RISCVCPU *cpu = RISCV_CPU(obj);
>> +
>>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
>>  set_priv_version(env, PRIV_VERSION_1_10_0);
>> +set_satp_mode_max_supported(cpu, VM_1_10_SV39);
>>  }
>>

Re: [PATCH v8 4/5] riscv: Introduce satp mode hw capabilities

2023-01-31 Thread Alexandre Ghiti
On Mon, Jan 30, 2023 at 5:29 AM Bin Meng  wrote:
>
> On Thu, Jan 26, 2023 at 12:24 AM Alexandre Ghiti  
> wrote:
> >
> > Currently, the max satp mode is set with the only constraint that it must be
> > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
>
> nits: s/qemu/QEMU/g

Ok

>
> >
> > But we actually need to add another level of constraint: what the hw is
> > actually capable of, because currently, a linux booting on a sifive-u54
> > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > capability.
> >
> > So add a new bitmap to RISCVSATPMap which contains this capability and
> > initialize it in every XXX_cpu_init.
> >
> > Finally:
> > - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
> > - the CPU hw capabilities constrains what the user may select
> > - the user's selection then constrains what's available to the guest
> >   OS.
> >
> > Signed-off-by: Alexandre Ghiti 
> > Reviewed-by: Andrew Jones 
> > ---
> >  target/riscv/cpu.c | 74 +++---
> >  target/riscv/cpu.h |  8 +++--
> >  2 files changed, 56 insertions(+), 26 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 54494a72be..e7e1fb96dc 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > is_32_bit)
> >  g_assert_not_reached();
> >  }
> >
> > -/* Sets the satp mode to the max supported */
> > -static void set_satp_mode_default(RISCVCPU *cpu)
> > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > +uint8_t satp_mode)
> >  {
> >  bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
> > +const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
> >
> > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > -cpu->cfg.satp_mode.map |=
> > -(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
> > -} else {
> > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > +for (int i = 0; i <= satp_mode; ++i) {
> > +if (valid_vm[i]) {
> > +cpu->cfg.satp_mode.supported |= (1 << i);
> > +}
> >  }
> >  }
> >
> > +/* Sets the satp mode to the max supported */
>
> nits: s/Sets/Set

Ok

>
> > +static void set_satp_mode_default(RISCVCPU *cpu)
> > +{
> > +cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
> > +}
> > +
> >  static void riscv_any_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  #if defined(TARGET_RISCV32)
> >  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, VM_1_10_SV32);
> >  #elif defined(TARGET_RISCV64)
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
> >  #endif
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> >  register_cpu_props(obj);
> > @@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
> >  static void rv64_base_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  /* We set this in the realise function */
> >  set_misa(env, MXL_RV64, 0);
> >  register_cpu_props(obj);
> >  /* Set latest version of privileged specification */
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> > +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
> >  }
> >
> >  static void rv64_sifive_u_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
> >  set_priv_version(env, PRIV_VERSION_1_10_0);
> > +set_satp_mode_max_supported(cpu, VM_1_10_SV39);
> >  }
> >
> >  static void rv64_sifive_e_cpu_init(Object *obj)
> > @@ -343,6 +359,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
> >  set_priv_version(env, PRIV_VERSION_1_10_0);
> >  cpu->cfg.mmu = false;
> > +set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
> >  }
>

[PATCH v9 3/5] riscv: Allow user to set the satp mode

2023-01-31 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 207 +
 target/riscv/cpu.h |  19 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 231 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..3a7a1746aa 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |=
+(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
+} else {
+cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+}
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -619,6 +695,83 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 }
 }
 
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+uint8_t satp_mode_max;
+
+if (cpu->cfg.satp_mode.map == 0) {
+if (cpu->cfg.satp_mode.init == 0) {
+/* If unset by the user, we fallback to the default satp mode. */
+set_satp_mode_default_map(cpu);
+} else {
+/*
+ * Find the lowest level that was disabled and then enable the
+ * first valid level below which can be found in
+ * valid_vm_1_10_32/6

Re: [PATCH v8 3/5] riscv: Allow user to set the satp mode

2023-01-31 Thread Alexandre Ghiti
On Wed, Jan 25, 2023 at 5:52 PM Andrew Jones  wrote:
>
> On Wed, Jan 25, 2023 at 05:20:08PM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> >
> > And contradictory configurations:
> > -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 206 +
> >  target/riscv/cpu.h |  19 +
> >  target/riscv/csr.c |  12 ++-
> >  3 files changed, 230 insertions(+), 7 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 7181b34f86..54494a72be 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -27,6 +27,7 @@
> >  #include "time_helper.h"
> >  #include "exec/exec-all.h"
> >  #include "qapi/error.h"
> > +#include "qapi/visitor.h"
> >  #include "qemu/error-report.h"
> >  #include "hw/qdev-properties.h"
> >  #include "migration/vmstate.h"
> > @@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
> > vext_ver)
> >  env->vext_ver = vext_ver;
> >  }
> >
> > +static uint8_t satp_mode_from_str(const char *satp_mode_str)
> > +{
> > +if (!strncmp(satp_mode_str, "mbare", 5)) {
> > +return VM_1_10_MBARE;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv32", 4)) {
> > +return VM_1_10_SV32;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv39", 4)) {
> > +return VM_1_10_SV39;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv48", 4)) {
> > +return VM_1_10_SV48;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv57", 4)) {
> > +return VM_1_10_SV57;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv64", 4)) {
> > +return VM_1_10_SV64;
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +uint8_t satp_mode_max_from_map(uint32_t map)
> > +{
> > +/* map here has at least one bit set, so no problem with clz */
> > +return 31 - __builtin_clz(map);
> > +}
> > +
> > +const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
> > +{
> > +if (is_32_bit) {
> > +switch (satp_mode) {
> > +case VM_1_10_SV32:
> > +return "sv32";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +} else {
> > +switch (satp_mode) {
> > +case VM_1_10_SV64:
> > +return "sv64";
> > +case VM_1_10_SV57:
> > +return "sv57";
> > +case VM_1_10_SV48:
> > +return "sv48";
> > +case VM_1_10_SV39:
> > +return "sv39";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +/* Sets the satp mode to the max supported */
> > +static void set_satp_mode_defau

[PATCH v9 4/5] riscv: Introduce satp mode hw capabilities

2023-01-31 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the guest
  OS.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 79 +++---
 target/riscv/cpu.h |  8 +++--
 2 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 3a7a1746aa..6dd76355ec 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default_map(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+uint8_t satp_mode)
 {
 bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
 
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |=
-(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
-} else {
-cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
 
+/* Set the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 #if defined(TARGET_RISCV32)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
@@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
 static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV39);
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -343,6 +359,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -354,28 +371,36 @@ static void rv128_base_cpu_init(Object *obj)
 exit(EXIT_FAILURE);
 }
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10

[PATCH v9 0/5] riscv: Allow user to set the satp mode

2023-01-31 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 4).

v9:
- Move valid_vm[i] up, Andrew
- Fixed expansion of the bitmap map, Bin
- Rename set_satp_mode_default into set_satp_mode_default_map, Bin
- Remove outer parenthesis and alignment, Bin
- Fix qemu32 build failure, Bin
- Fixed a few typos, Bin
- Add RB from Andrew and Bin

v8:
- Remove useless !map check, Andrew
- Add RB from Andrew

v7:
- Expand map to contain all valid modes, Andrew
- Fix commit log for patch 3, Andrew
- Remove is_32_bit argument from set_satp_mode_default, Andrew
- Move and fixed comment, Andrew
- Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
  too early, Alex
- Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
- Use satp_mode directly instead of a string in
  set_satp_mode_max_supported, Andrew
- Swap the patch introducing supported bitmap and the patch that sets
  sv57 in the dt, Andrew
- Add various RB from Andrew and Alistair, thanks

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Introduce satp mode hw capabilities
  riscv: Correctly set the device-tree entry 'mmu-type'

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 251 +++--
 target/riscv/cpu.h |  23 +
 target/riscv/csr.c |  29 +++---
 4 files changed, 291 insertions(+), 31 deletions(-)

-- 
2.37.2




[PATCH v9 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-31 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v9 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-01-31 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v9 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-01-31 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Suggested-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c233e5..6b157806a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




Re: [PATCH v8 3/5] riscv: Allow user to set the satp mode

2023-01-31 Thread Alexandre Ghiti
Hi Bin,

On Mon, Jan 30, 2023 at 5:22 AM Bin Meng  wrote:
>
> On Thu, Jan 26, 2023 at 12:23 AM Alexandre Ghiti  
> wrote:
> >
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> >
> > And contradictory configurations:
> > -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 206 +
> >  target/riscv/cpu.h |  19 +
> >  target/riscv/csr.c |  12 ++-
> >  3 files changed, 230 insertions(+), 7 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 7181b34f86..54494a72be 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -27,6 +27,7 @@
> >  #include "time_helper.h"
> >  #include "exec/exec-all.h"
> >  #include "qapi/error.h"
> > +#include "qapi/visitor.h"
> >  #include "qemu/error-report.h"
> >  #include "hw/qdev-properties.h"
> >  #include "migration/vmstate.h"
> > @@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
> > vext_ver)
> >  env->vext_ver = vext_ver;
> >  }
> >
> > +static uint8_t satp_mode_from_str(const char *satp_mode_str)
> > +{
> > +if (!strncmp(satp_mode_str, "mbare", 5)) {
> > +return VM_1_10_MBARE;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv32", 4)) {
> > +return VM_1_10_SV32;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv39", 4)) {
> > +return VM_1_10_SV39;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv48", 4)) {
> > +return VM_1_10_SV48;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv57", 4)) {
> > +return VM_1_10_SV57;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv64", 4)) {
> > +return VM_1_10_SV64;
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +uint8_t satp_mode_max_from_map(uint32_t map)
> > +{
> > +/* map here has at least one bit set, so no problem with clz */
> > +return 31 - __builtin_clz(map);
> > +}
> > +
> > +const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
> > +{
> > +if (is_32_bit) {
> > +switch (satp_mode) {
> > +case VM_1_10_SV32:
> > +return "sv32";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +} else {
> > +switch (satp_mode) {
> > +case VM_1_10_SV64:
> > +return "sv64";
> > +case VM_1_10_SV57:
> > +return "sv57";
> > +case VM_1_10_SV48:
> > +return "sv48";
> > +case VM_1_10_SV39:
> > +return "sv39";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +/* Sets the satp mode to the max supported */
> > +static void set

[PATCH v8 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-01-25 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v8 4/5] riscv: Introduce satp mode hw capabilities

2023-01-25 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in qemu, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the guest
  OS.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 74 +++---
 target/riscv/cpu.h |  8 +++--
 2 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 54494a72be..e7e1fb96dc 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+uint8_t satp_mode)
 {
 bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
 
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |=
-(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
-} else {
-cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
 
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu)
+{
+cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 #if defined(TARGET_RISCV32)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
@@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
 static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV39);
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -343,6 +359,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -354,11 +371,13 @@ static void rv128_base_cpu_init(Object *obj)
 exit(EXIT_FAILURE);
 }
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -369,13 +388,17 @@ static void rv32_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 }
 
 static void rv32_sifive_e_cpu_init(Object *obj)
@@ -386,6 +409,7 @@ static void rv

[PATCH v8 3/5] riscv: Allow user to set the satp mode

2023-01-25 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 206 +
 target/riscv/cpu.h |  19 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 230 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..54494a72be 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |=
+(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
+} else {
+cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+}
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -619,6 +695,82 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 }
 }
 
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+uint8_t satp_mode_max;
+
+if (cpu->cfg.satp_mode.map == 0) {
+if (cpu->cfg.satp_mode.init == 0) {
+/* If unset by the user, we fallback to the default satp mode. */
+set_satp_mode_default(cpu);
+} else {
+/*
+ * Find the lowest level that was disabled and then enable the
+ * first valid level below which can be found in
+ * valid_vm_1_10_32/64.
+ */
+

[PATCH v8 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-01-25 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Suggested-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c233e5..6b157806a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




[PATCH v8 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-25 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v8 0/5] riscv: Allow user to set the satp mode

2023-01-25 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 4).

v8:
- Remove useless !map check, Andrew
- Add RB from Andrew

v7:
- Expand map to contain all valid modes, Andrew
- Fix commit log for patch 3, Andrew
- Remove is_32_bit argument from set_satp_mode_default, Andrew
- Move and fixed comment, Andrew
- Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
  too early, Alex
- Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
- Use satp_mode directly instead of a string in
  set_satp_mode_max_supported, Andrew
- Swap the patch introducing supported bitmap and the patch that sets
  sv57 in the dt, Andrew
- Add various RB from Andrew and Alistair, thanks

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Introduce satp mode hw capabilities
  riscv: Correctly set the device-tree entry 'mmu-type'

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 247 +++--
 target/riscv/cpu.h |  23 +
 target/riscv/csr.c |  29 +++---
 4 files changed, 287 insertions(+), 31 deletions(-)

-- 
2.37.2




Re: [PATCH v7 3/5] riscv: Allow user to set the satp mode

2023-01-25 Thread Alexandre Ghiti
On Wed, Jan 25, 2023 at 1:01 PM Andrew Jones  wrote:
>
> On Wed, Jan 25, 2023 at 09:41:05AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> >
> > And contradictory configurations:
> > -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 207 +
> >  target/riscv/cpu.h |  19 +
> >  target/riscv/csr.c |  12 ++-
> >  3 files changed, 231 insertions(+), 7 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 7181b34f86..87153a0219 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -27,6 +27,7 @@
> >  #include "time_helper.h"
> >  #include "exec/exec-all.h"
> >  #include "qapi/error.h"
> > +#include "qapi/visitor.h"
> >  #include "qemu/error-report.h"
> >  #include "hw/qdev-properties.h"
> >  #include "migration/vmstate.h"
> > @@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
> > vext_ver)
> >  env->vext_ver = vext_ver;
> >  }
> >
> > +static uint8_t satp_mode_from_str(const char *satp_mode_str)
> > +{
> > +if (!strncmp(satp_mode_str, "mbare", 5)) {
> > +return VM_1_10_MBARE;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv32", 4)) {
> > +return VM_1_10_SV32;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv39", 4)) {
> > +return VM_1_10_SV39;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv48", 4)) {
> > +return VM_1_10_SV48;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv57", 4)) {
> > +return VM_1_10_SV57;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv64", 4)) {
> > +return VM_1_10_SV64;
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +uint8_t satp_mode_max_from_map(uint32_t map)
> > +{
> > +/* map here has at least one bit set, so no problem with clz */
> > +return 31 - __builtin_clz(map);
> > +}
> > +
> > +const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
> > +{
> > +if (is_32_bit) {
> > +switch (satp_mode) {
> > +case VM_1_10_SV32:
> > +return "sv32";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +} else {
> > +switch (satp_mode) {
> > +case VM_1_10_SV64:
> > +return "sv64";
> > +case VM_1_10_SV57:
> > +return "sv57";
> > +case VM_1_10_SV48:
> > +return "sv48";
> > +case VM_1_10_SV39:
> > +return "sv39";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +/* Sets the satp mode to the max supported */
> > +static void set_satp_mode_defau

[PATCH v7 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-01-25 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v7 4/5] riscv: Introduce satp mode hw capabilities

2023-01-25 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in qemu, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the guest
  OS.

Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 74 +++---
 target/riscv/cpu.h |  8 +++--
 2 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 87153a0219..bba9c39bb8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+uint8_t satp_mode)
 {
 bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
 
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |=
-(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
-} else {
-cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
 
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu)
+{
+cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 #if defined(TARGET_RISCV32)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
@@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
 static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV39);
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -343,6 +359,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -354,11 +371,13 @@ static void rv128_base_cpu_init(Object *obj)
 exit(EXIT_FAILURE);
 }
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -369,13 +388,17 @@ static void rv32_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
 }
 
 static void rv32_sifive_e_cpu_init(Object *obj)
@@ -386,6 +409,7 @@ static void rv32_sifive_e_cpu_init(Object 

[PATCH v7 3/5] riscv: Allow user to set the satp mode

2023-01-25 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 207 +
 target/riscv/cpu.h |  19 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 231 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..87153a0219 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,81 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |=
+(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
+} else {
+cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+}
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -619,6 +695,83 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 }
 }
 
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+uint8_t satp_mode_max;
+
+if (cpu->cfg.satp_mode.map == 0) {
+if (cpu->cfg.satp_mode.init == 0) {
+/* If unset by the user, we fallback to the default satp mode. */
+set_satp_mode_default(cpu);
+} else {
+/*
+ * Find the lowest level that was disabled and then enable the
+ * first valid level below which can be found in
+ * valid_vm_1_10_32/64.
+ */
+for (int i =

[PATCH v7 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-01-25 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Suggested-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
Reviewed-by: Andrew Jones 
Reviewed-by: Alistair Francis 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c233e5..6b157806a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




[PATCH v7 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-25 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v7 0/5] riscv: Allow user to set the satp mode

2023-01-25 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 5).

v7:
- Expand map to contain all valid modes, Andrew
- Fix commit log for patch 3, Andrew
- Remove is_32_bit argument from set_satp_mode_default, Andrew
- Move and fixed comment, Andrew
- Fix satp_mode_map_max in riscv_cpu_satp_mode_finalize which was set
  too early, Alex
- Remove is_32_bit argument from set_satp_mode_max_supported, Andrew
- Use satp_mode directly instead of a string in
  set_satp_mode_max_supported, Andrew
- Swap the patch introducing supported bitmap and the patch that sets
  sv57 in the dt, Andrew
- Add various RB from Andrew and Alistair, thanks

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Introduce satp mode hw capabilities
  riscv: Correctly set the device-tree entry 'mmu-type'

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 248 +++--
 target/riscv/cpu.h |  23 +
 target/riscv/csr.c |  29 +++---
 4 files changed, 288 insertions(+), 31 deletions(-)

-- 
2.37.2




Re: [PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-24 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 2:51 PM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:24AM +0100, Alexandre Ghiti wrote:
> > Currently, the max satp mode is set with the only constraint that it must be
> > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
> >
> > But we actually need to add another level of constraint: what the hw is
> > actually capable of, because currently, a linux booting on a sifive-u54
> > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > capability.
> >
> > So add a new bitmap to RISCVSATPMap which contains this capability and
> > initialize it in every XXX_cpu_init.
> >
> > Finally, we have the following chain of constraints:
> >
> > Qemu capability > HW capability > User choice > Software capability
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 78 +++---
> >  target/riscv/cpu.h |  8 +++--
> >  2 files changed, 59 insertions(+), 27 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index e409e6ab64..19a37fee2b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > is_32_bit)
> >  g_assert_not_reached();
> >  }
> >
> > -/* Sets the satp mode to the max supported */
> > -static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > +const char *satp_mode_str,
> > +bool is_32_bit)
>
> I'd drop 'is_32_bit' and get it from 'cpu', which would "clean up" all the
> callsites by getting rid of all the true/false stuff.

Indeed, better this way

> Also, why take the string instead of the VM_1_10_SV* define?

No particular reason, but I changed it to VM_1_10_SV*, thanks

>
> >  {
> > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > -cpu->cfg.satp_mode.map |=
> > -(1 << satp_mode_from_str(is_32_bit ? "sv32" : 
> > "sv57"));
> > -} else {
> > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > +uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
> > +const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
> > +
> > +for (int i = 0; i <= satp_mode; ++i) {
> > +if (valid_vm[i]) {
> > +cpu->cfg.satp_mode.supported |= (1 << i);
> > +}
> >  }
> >  }
> >
> > +/* Sets the satp mode to the max supported */
> > +static void set_satp_mode_default(RISCVCPU *cpu)
> > +{
> > +uint8_t satp_mode = 
> > satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
> > +
> > +cpu->cfg.satp_mode.map |= (1 << satp_mode);
>
> Let's do 'cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported' to make
> sure 'map' has all supported bits set for property probing.

Indeed now the map is fully set.

>
> > +}
> > +
> >  static void riscv_any_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  #if defined(TARGET_RISCV32)
> >  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, "sv32", true);
> >  #elif defined(TARGET_RISCV64)
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, "sv57", false);
> >  #endif
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> >  register_cpu_props(obj);
> > @@ -319,18 +334,24 @@ static void riscv_any_cpu_init(Object *obj)
> >  static void rv64_base_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  /* We set this in the realise function */
> >  set_misa(env, MXL_RV64, 0);
> >  register_cpu_props(obj);
> >  /* Set latest version of privileged specification */
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> > +set_satp_mode_max_supported(cpu, "sv57", false);
> >  }
> >
> >  static void rv64_sifive_u_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | R

Re: [PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-24 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 2:31 PM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 12:15:08PM +0100, Alexandre Ghiti wrote:
> > On Mon, Jan 23, 2023 at 11:51 AM Andrew Jones  
> > wrote:
> > >
> > > On Mon, Jan 23, 2023 at 10:03:24AM +0100, Alexandre Ghiti wrote:
> > > > Currently, the max satp mode is set with the only constraint that it 
> > > > must be
> > > > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
> > > >
> > > > But we actually need to add another level of constraint: what the hw is
> > > > actually capable of, because currently, a linux booting on a sifive-u54
> > > > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > > > capability.
> > > >
> > > > So add a new bitmap to RISCVSATPMap which contains this capability and
> > > > initialize it in every XXX_cpu_init.
> > > >
> > > > Finally, we have the following chain of constraints:
> > > >
> > > > Qemu capability > HW capability > User choice > Software capability
> > >
> > >   ^ What software is this?
> > >  I'd think the user's choice would always be last.
> > >
> > > >
> > > > Signed-off-by: Alexandre Ghiti 
> > > > ---
> > > >  target/riscv/cpu.c | 78 +++---
> > > >  target/riscv/cpu.h |  8 +++--
> > > >  2 files changed, 59 insertions(+), 27 deletions(-)
> > > >
> > > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > > > index e409e6ab64..19a37fee2b 100644
> > > > --- a/target/riscv/cpu.c
> > > > +++ b/target/riscv/cpu.c
> > > > @@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > > > is_32_bit)
> > > >  g_assert_not_reached();
> > > >  }
> > > >
> > > > -/* Sets the satp mode to the max supported */
> > > > -static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > > > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > > > +const char *satp_mode_str,
> > > > +bool is_32_bit)
> > > >  {
> > > > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > > > -cpu->cfg.satp_mode.map |=
> > > > -(1 << satp_mode_from_str(is_32_bit ? "sv32" : 
> > > > "sv57"));
> > > > -} else {
> > > > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > > > +uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
> > > > +const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : 
> > > > valid_vm_1_10_64;
> > > > +
> > > > +for (int i = 0; i <= satp_mode; ++i) {
> > > > +if (valid_vm[i]) {
> > > > +cpu->cfg.satp_mode.supported |= (1 << i);
> > >
> > > I don't think we need a new 'supported' bitmap, I think each board that
> > > needs to further constrain va-bits from what QEMU supports should just set
> > > valid_vm_1_10_32/64. I.e. drop const from the arrays and add an init
> > > function something like
> >
> > This was my first idea too, but those arrays are global and I have to
> > admit that I thought it was possible to emulate a cpu with different
> > cores. Anyway, isn't it a bit weird to store this into some global
> > array whereas it is intimately linked to the CPU? To me, it makes
> > sense to keep those variables as a way to know what qemu is able to
> > emulate and have a CPU specific map like in this patch for the hw
> > capabilities. Does it make sense to you?
>
> Ah, yes, to support heterogeneous configs it's best to keep this
> information per-cpu. I'll take another look at the patch.
>
> >
> > >
> > >  #define QEMU_SATP_MODE_MAX VM_1_10_SV64
> > >
> > >  void riscv_cpu_set_satp_mode_max(RISCVCPU *cpu, uint8_t satp_mode_max)
> > >  {
> > >  bool is_32_bit = cpu->env.misa_mxl == MXL_RV32;
> > >  bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
> > >
> > >  g_assert(satp_mode_max <= QEMU_SATP_MODE_MAX);
> > >  g_assert(!is_32_bit || satp_mode_max < 2);
> > >
> > >  memset(valid_vm, 0, sizeof(*valid_vm));
> > >
> > >  for (int i = 0; i <= satp_mode_max; i++) {
> > >  valid_vm[i] = true;
> > >  }
> > >  }
> > >
> > > The valid_vm[] checks already in finalize should then manage the
> > > validation needed to constrain boards. Only boards that care about
> > > this need to call this function, otherwise they'll get the default.
> > >
> > > Also, this patch should come before the patch that changes the default
> > > for all boards to sv57 in order to avoid breaking bisection.
> >
> > As I explained earlier, I didn't change the default to sv57! Just
> > fixed what was passed via the device tree, which should not be used
> > anyway :)
>
> OK, I keep misunderstanding how we're "fixing" something which is
> is wrong, but apparently doesn't exhibit any symptoms. So, assuming
> it doesn't matter, then I guess it can come anywhere in the series.

Actually *I* think it should not matter, but I can't be sure so I'll
do what you ask.

>
> Thanks,
> drew



Re: [PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-24 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 11:51 AM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:24AM +0100, Alexandre Ghiti wrote:
> > Currently, the max satp mode is set with the only constraint that it must be
> > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
> >
> > But we actually need to add another level of constraint: what the hw is
> > actually capable of, because currently, a linux booting on a sifive-u54
> > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > capability.
> >
> > So add a new bitmap to RISCVSATPMap which contains this capability and
> > initialize it in every XXX_cpu_init.
> >
> > Finally, we have the following chain of constraints:
> >
> > Qemu capability > HW capability > User choice > Software capability
>
>   ^ What software is this?
>  I'd think the user's choice would always be last.

Hmm maybe that's not clear, but I meant that the last constraint was
what the emulated software is capable of handling.

>
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 78 +++---
> >  target/riscv/cpu.h |  8 +++--
> >  2 files changed, 59 insertions(+), 27 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index e409e6ab64..19a37fee2b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > is_32_bit)
> >  g_assert_not_reached();
> >  }
> >
> > -/* Sets the satp mode to the max supported */
> > -static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > +const char *satp_mode_str,
> > +bool is_32_bit)
> >  {
> > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > -cpu->cfg.satp_mode.map |=
> > -(1 << satp_mode_from_str(is_32_bit ? "sv32" : 
> > "sv57"));
> > -} else {
> > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > +uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
> > +const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
> > +
> > +for (int i = 0; i <= satp_mode; ++i) {
> > +if (valid_vm[i]) {
> > +cpu->cfg.satp_mode.supported |= (1 << i);
>
> I don't think we need a new 'supported' bitmap, I think each board that
> needs to further constrain va-bits from what QEMU supports should just set
> valid_vm_1_10_32/64. I.e. drop const from the arrays and add an init
> function something like
>
>  #define QEMU_SATP_MODE_MAX VM_1_10_SV64
>
>  void riscv_cpu_set_satp_mode_max(RISCVCPU *cpu, uint8_t satp_mode_max)
>  {
>  bool is_32_bit = cpu->env.misa_mxl == MXL_RV32;
>  bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
>
>  g_assert(satp_mode_max <= QEMU_SATP_MODE_MAX);
>  g_assert(!is_32_bit || satp_mode_max < 2);
>
>  memset(valid_vm, 0, sizeof(*valid_vm));
>
>  for (int i = 0; i <= satp_mode_max; i++) {
>  valid_vm[i] = true;
>  }
>  }
>
> The valid_vm[] checks already in finalize should then manage the
> validation needed to constrain boards. Only boards that care about
> this need to call this function, otherwise they'll get the default.
>
> Also, this patch should come before the patch that changes the default
> for all boards to sv57 in order to avoid breaking bisection.
>
> Thanks,
> drew



Re: [PATCH v6 3/5] riscv: Allow user to set the satp mode

2023-01-24 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 11:29 AM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:22AM +0100, Alexandre Ghiti wrote:
> ...
> > +/* Sets the satp mode to the max supported */
> > +static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > +{
>
> nit: When passing in the cpu object pointer there's no need to also pass
> is_32_bit, we can just use it from the pointer, cpu->env.misa_mxl == MXL_RV32

Ok

Thanks,

Alex

>
> Thanks,
> drew



Re: [PATCH v6 3/5] riscv: Allow user to set the satp mode

2023-01-24 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 11:14 AM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:22AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> >
> > And contradictory configurations:
> > -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
> >
> > In addition, we now correctly set the device-tree entry 'mmu-type' using
> > those new properties.
>
> This sentence no longer applies to this patch.


Sorry about that and thanks for noticing.

Alex

>
> Thanks,
> drew



Re: [PATCH v6 3/5] riscv: Allow user to set the satp mode

2023-01-24 Thread Alexandre Ghiti
Hi Andrew,

On Mon, Jan 23, 2023 at 11:11 AM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:22AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
>
> The property doesn't exist for rv64 anymore, so I'm not sure we need
> this info in the commit message.

Sorry about that...

>
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> >
> > And contradictory configurations:
> > -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
> >
> > In addition, we now correctly set the device-tree entry 'mmu-type' using
> > those new properties.
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 204 +
> >  target/riscv/cpu.h |  19 +
> >  target/riscv/csr.c |  12 ++-
> >  3 files changed, 228 insertions(+), 7 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 7181b34f86..e409e6ab64 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -27,6 +27,7 @@
> >  #include "time_helper.h"
> >  #include "exec/exec-all.h"
> >  #include "qapi/error.h"
> > +#include "qapi/visitor.h"
> >  #include "qemu/error-report.h"
> >  #include "hw/qdev-properties.h"
> >  #include "migration/vmstate.h"
> > @@ -229,6 +230,79 @@ static void set_vext_version(CPURISCVState *env, int 
> > vext_ver)
> >  env->vext_ver = vext_ver;
> >  }
> >
> > +static uint8_t satp_mode_from_str(const char *satp_mode_str)
> > +{
> > +if (!strncmp(satp_mode_str, "mbare", 5)) {
> > +return VM_1_10_MBARE;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv32", 4)) {
> > +return VM_1_10_SV32;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv39", 4)) {
> > +return VM_1_10_SV39;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv48", 4)) {
> > +return VM_1_10_SV48;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv57", 4)) {
> > +return VM_1_10_SV57;
> > +}
> > +
> > +if (!strncmp(satp_mode_str, "sv64", 4)) {
> > +return VM_1_10_SV64;
> > +}
> > +
> > +g_assert_not_reached();
> > +}
> > +
> > +uint8_t satp_mode_max_from_map(uint32_t map)
> > +{
> > +/* map here has at least one bit set, so no problem with clz */
> > +return 31 - __builtin_clz(map);
> > +}
> > +
> > +const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
> > +{
> > +if (is_32_bit) {
> > +switch (satp_mode) {
> > +case VM_1_10_SV32:
> > +return "sv32";
> > +case VM_1_10_MBARE:
> > +return "none";
> > +}
> > +} else {
> > +switch (satp_mode) {
> > +case VM_1_10_SV64:
> > +return "sv64";
> > +case VM_1_10_SV57:
> > +return "sv57";
> > +case VM_1_10_SV48:
> > +return "sv48";
> > +case VM_1_10_S

Re: [PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-24 Thread Alexandre Ghiti
Hi Alistair,

On Tue, Jan 24, 2023 at 1:41 AM Alistair Francis  wrote:
>
> On Mon, Jan 23, 2023 at 7:09 PM Alexandre Ghiti  
> wrote:
> >
> > Currently, the max satp mode is set with the only constraint that it must be
> > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
> >
> > But we actually need to add another level of constraint: what the hw is
> > actually capable of, because currently, a linux booting on a sifive-u54
> > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > capability.
> >
> > So add a new bitmap to RISCVSATPMap which contains this capability and
> > initialize it in every XXX_cpu_init.
> >
> > Finally, we have the following chain of constraints:
> >
> > Qemu capability > HW capability > User choice > Software capability
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 78 +++---
> >  target/riscv/cpu.h |  8 +++--
> >  2 files changed, 59 insertions(+), 27 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index e409e6ab64..19a37fee2b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > is_32_bit)
> >  g_assert_not_reached();
> >  }
> >
> > -/* Sets the satp mode to the max supported */
> > -static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > +const char *satp_mode_str,
> > +bool is_32_bit)
> >  {
> > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > -cpu->cfg.satp_mode.map |=
> > -(1 << satp_mode_from_str(is_32_bit ? "sv32" : 
> > "sv57"));
> > -} else {
> > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > +uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
> > +const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
> > +
> > +for (int i = 0; i <= satp_mode; ++i) {
> > +if (valid_vm[i]) {
> > +cpu->cfg.satp_mode.supported |= (1 << i);
> > +}
> >  }
> >  }
> >
> > +/* Sets the satp mode to the max supported */
> > +static void set_satp_mode_default(RISCVCPU *cpu)
> > +{
> > +uint8_t satp_mode = 
> > satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
> > +
> > +cpu->cfg.satp_mode.map |= (1 << satp_mode);
> > +}
> > +
> >  static void riscv_any_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  #if defined(TARGET_RISCV32)
> >  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, "sv32", true);
> >  #elif defined(TARGET_RISCV64)
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> > +set_satp_mode_max_supported(cpu, "sv57", false);
> >  #endif
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> >  register_cpu_props(obj);
> > @@ -319,18 +334,24 @@ static void riscv_any_cpu_init(Object *obj)
> >  static void rv64_base_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  /* We set this in the realise function */
> >  set_misa(env, MXL_RV64, 0);
> >  register_cpu_props(obj);
> >  /* Set latest version of privileged specification */
> >  set_priv_version(env, PRIV_VERSION_1_12_0);
> > +set_satp_mode_max_supported(cpu, "sv57", false);
> >  }
> >
> >  static void rv64_sifive_u_cpu_init(Object *obj)
> >  {
> >  CPURISCVState *env = _CPU(obj)->env;
> > +RISCVCPU *cpu = RISCV_CPU(obj);
> > +
> >  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
> >  set_priv_version(env, PRIV_VERSION_1_10_0);
> > +set_satp_mode_max_supported(cpu, "sv39", false);
>
> Can we just not expose the properties on these vendor CPUs and then
> not worry about setting maximums?
>

I'm not sure I understand: the properties are actually not exposed to
the vendor cpus from what I see (no calls to register_cpu_props).

The problem this patch fixes is that the only constraint on satp is

Re: [PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-23 Thread Alexandre Ghiti
On Mon, Jan 23, 2023 at 11:51 AM Andrew Jones  wrote:
>
> On Mon, Jan 23, 2023 at 10:03:24AM +0100, Alexandre Ghiti wrote:
> > Currently, the max satp mode is set with the only constraint that it must be
> > implemented in qemu, i.e. set in valid_vm_1_10_[32|64].
> >
> > But we actually need to add another level of constraint: what the hw is
> > actually capable of, because currently, a linux booting on a sifive-u54
> > boots in sv57 mode which is incompatible with the cpu's sv39 max
> > capability.
> >
> > So add a new bitmap to RISCVSATPMap which contains this capability and
> > initialize it in every XXX_cpu_init.
> >
> > Finally, we have the following chain of constraints:
> >
> > Qemu capability > HW capability > User choice > Software capability
>
>   ^ What software is this?
>      I'd think the user's choice would always be last.
>
> >
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  target/riscv/cpu.c | 78 +++---
> >  target/riscv/cpu.h |  8 +++--
> >  2 files changed, 59 insertions(+), 27 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index e409e6ab64..19a37fee2b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
> > is_32_bit)
> >  g_assert_not_reached();
> >  }
> >
> > -/* Sets the satp mode to the max supported */
> > -static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
> > +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> > +const char *satp_mode_str,
> > +bool is_32_bit)
> >  {
> > -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> > -cpu->cfg.satp_mode.map |=
> > -(1 << satp_mode_from_str(is_32_bit ? "sv32" : 
> > "sv57"));
> > -} else {
> > -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> > +uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
> > +const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
> > +
> > +for (int i = 0; i <= satp_mode; ++i) {
> > +if (valid_vm[i]) {
> > +cpu->cfg.satp_mode.supported |= (1 << i);
>
> I don't think we need a new 'supported' bitmap, I think each board that
> needs to further constrain va-bits from what QEMU supports should just set
> valid_vm_1_10_32/64. I.e. drop const from the arrays and add an init
> function something like

This was my first idea too, but those arrays are global and I have to
admit that I thought it was possible to emulate a cpu with different
cores. Anyway, isn't it a bit weird to store this into some global
array whereas it is intimately linked to the CPU? To me, it makes
sense to keep those variables as a way to know what qemu is able to
emulate and have a CPU specific map like in this patch for the hw
capabilities. Does it make sense to you?

>
>  #define QEMU_SATP_MODE_MAX VM_1_10_SV64
>
>  void riscv_cpu_set_satp_mode_max(RISCVCPU *cpu, uint8_t satp_mode_max)
>  {
>  bool is_32_bit = cpu->env.misa_mxl == MXL_RV32;
>  bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
>
>  g_assert(satp_mode_max <= QEMU_SATP_MODE_MAX);
>  g_assert(!is_32_bit || satp_mode_max < 2);
>
>  memset(valid_vm, 0, sizeof(*valid_vm));
>
>  for (int i = 0; i <= satp_mode_max; i++) {
>  valid_vm[i] = true;
>  }
>  }
>
> The valid_vm[] checks already in finalize should then manage the
> validation needed to constrain boards. Only boards that care about
> this need to call this function, otherwise they'll get the default.
>
> Also, this patch should come before the patch that changes the default
> for all boards to sv57 in order to avoid breaking bisection.

As I explained earlier, I didn't change the default to sv57! Just
fixed what was passed via the device tree, which should not be used
anyway :)

Alex

>
> Thanks,
> drew



[PATCH v6 1/5] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-23 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Reviewed-by: Alistair Francis 
Reviewed-by: Frank Chang 
Reviewed-by: Andrew Jones 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v6 5/5] riscv: Introduce satp mode hw capabilities

2023-01-23 Thread Alexandre Ghiti
Currently, the max satp mode is set with the only constraint that it must be
implemented in qemu, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally, we have the following chain of constraints:

Qemu capability > HW capability > User choice > Software capability

Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 78 +++---
 target/riscv/cpu.h |  8 +++--
 2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e409e6ab64..19a37fee2b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -292,24 +292,39 @@ const char *satp_mode_str(uint8_t satp_mode, bool 
is_32_bit)
 g_assert_not_reached();
 }
 
-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+const char *satp_mode_str,
+bool is_32_bit)
 {
-if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
-cpu->cfg.satp_mode.map |=
-(1 << satp_mode_from_str(is_32_bit ? "sv32" : "sv57"));
-} else {
-cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+uint8_t satp_mode = satp_mode_from_str(satp_mode_str);
+const bool *valid_vm = is_32_bit ? valid_vm_1_10_32 : valid_vm_1_10_64;
+
+for (int i = 0; i <= satp_mode; ++i) {
+if (valid_vm[i]) {
+cpu->cfg.satp_mode.supported |= (1 << i);
+}
 }
 }
 
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu)
+{
+uint8_t satp_mode = satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
+
+cpu->cfg.satp_mode.map |= (1 << satp_mode);
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 #if defined(TARGET_RISCV32)
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, "sv32", true);
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_satp_mode_max_supported(cpu, "sv57", false);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
 register_cpu_props(obj);
@@ -319,18 +334,24 @@ static void riscv_any_cpu_init(Object *obj)
 static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, "sv57", false);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+set_satp_mode_max_supported(cpu, "sv39", false);
 }
 
 static void rv64_sifive_e_cpu_init(Object *obj)
@@ -341,6 +362,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 cpu->cfg.mmu = false;
+set_satp_mode_max_supported(cpu, "mbare", false);
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -352,11 +374,13 @@ static void rv128_base_cpu_init(Object *obj)
 exit(EXIT_FAILURE);
 }
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, "sv57", false);
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -367,13 +391,17 @@ static void rv32_base_cpu_init(Object *obj)
 register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
+set_satp_mode_max_supported(cpu, "sv32", true);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
+

[PATCH v6 4/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-01-23 Thread Alexandre Ghiti
The 'mmu-type' should reflect what the hardware is capable of so use the
new satp_mode field in RISCVCPUConfig to do that.

Signed-off-by: Alexandre Ghiti 
---
 hw/riscv/virt.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
-- 
2.37.2




[PATCH v6 3/5] riscv: Allow user to set the satp mode

2023-01-23 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme

And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme

In addition, we now correctly set the device-tree entry 'mmu-type' using
those new properties.

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 204 +
 target/riscv/cpu.h |  19 +
 target/riscv/csr.c |  12 ++-
 3 files changed, 228 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..e409e6ab64 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,79 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "mbare", 5)) {
+return VM_1_10_MBARE;
+}
+
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+case VM_1_10_MBARE:
+return "none";
+}
+} else {
+switch (satp_mode) {
+case VM_1_10_SV64:
+return "sv64";
+case VM_1_10_SV57:
+return "sv57";
+case VM_1_10_SV48:
+return "sv48";
+case VM_1_10_SV39:
+return "sv39";
+case VM_1_10_MBARE:
+return "none";
+}
+}
+
+g_assert_not_reached();
+}
+
+/* Sets the satp mode to the max supported */
+static void set_satp_mode_default(RISCVCPU *cpu, bool is_32_bit)
+{
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+cpu->cfg.satp_mode.map |=
+(1 << satp_mode_from_str(is_32_bit ? "sv32" : "sv57"));
+} else {
+cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
+}
+}
+
 static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
@@ -619,6 +693,82 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 }
 }
 
+static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
+{
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+
+if (cpu->cfg.satp_mode.map == 0) {
+/*
+ * If unset by both the user and the cpu, we fallback to the default
+ * satp mode.
+ */
+if (cpu->cfg.satp_mode.init == 0) {
+set_satp_mode_default(cpu, rv32);
+} else {
+/*
+ * Find the lowest level that was disabled and then enable the
+

[PATCH v6 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-01-23 Thread Alexandre Ghiti
This array is actually used as a boolean so swap its current char type
to a boolean and at the same time, change the type of validate_vm to
bool since it returns valid_vm_1_10_[32|64].

Signed-off-by: Alexandre Ghiti 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c233e5..6b157806a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
-static const char valid_vm_1_10_32[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV32] = 1
+static const bool valid_vm_1_10_32[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV32] = true
 };
 
-static const char valid_vm_1_10_64[16] = {
-[VM_1_10_MBARE] = 1,
-[VM_1_10_SV39] = 1,
-[VM_1_10_SV48] = 1,
-[VM_1_10_SV57] = 1
+static const bool valid_vm_1_10_64[16] = {
+[VM_1_10_MBARE] = true,
+[VM_1_10_SV39] = true,
+[VM_1_10_SV48] = true,
+[VM_1_10_SV57] = true
 };
 
 /* Machine Information Registers */
@@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static int validate_vm(CPURISCVState *env, target_ulong vm)
+static bool validate_vm(CPURISCVState *env, target_ulong vm)
 {
 if (riscv_cpu_mxl(env) == MXL_RV32) {
 return valid_vm_1_10_32[vm & 0xf];
@@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-target_ulong vm, mask;
+target_ulong mask;
+bool vm;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.37.2




[PATCH v6 0/5] riscv: Allow user to set the satp mode

2023-01-23 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 3 for full syntax. In addition, it prevents cpus to boot in a
satp mode they do not support (see patch 5).

v6:
- Remove the valid_vm check in validate_vm and add it to the finalize function
  so that map already contains the constraint, Alex
- Add forgotten mbare to satp_mode_from_str, Alex
- Move satp mode properties handling to riscv_cpu_satp_mode_finalize, Andrew
- Only add satp mode properties corresponding to the cpu, and then remove the
  check against valid_vm_1_10_32/64 in riscv_cpu_satp_mode_finalize,
  Andrew/Alistair/Alex
- Move mmu-type setting to its own patch, Andrew
- patch 5 is new and is a fix, Alex

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (5):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Change type of valid_vm_1_10_[32|64] to bool
  riscv: Allow user to set the satp mode
  riscv: Correctly set the device-tree entry 'mmu-type'
  riscv: Introduce satp mode hw capabilities

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 247 +++--
 target/riscv/cpu.h |  23 +
 target/riscv/csr.c |  29 +++---
 4 files changed, 287 insertions(+), 31 deletions(-)

-- 
2.37.2




Re: [PATCH v5 2/2] riscv: Allow user to set the satp mode

2023-01-20 Thread Alexandre Ghiti
On Fri, Jan 20, 2023 at 10:53 AM Andrew Jones  wrote:
>
> On Fri, Jan 20, 2023 at 09:46:05AM +1000, Alistair Francis wrote:
> > On Thu, Jan 19, 2023 at 11:00 PM Alexandre Ghiti  
> > wrote:
> > >
> > > Hi Alistair, Andrew,
> > >
> > > On Thu, Jan 19, 2023 at 1:25 AM Alistair Francis  
> > > wrote:
> > > >
> > > > On Wed, Jan 18, 2023 at 10:19 PM Andrew Jones  
> > > > wrote:
> > > > >
> > > > > On Wed, Jan 18, 2023 at 10:28:46AM +1000, Alistair Francis wrote:
> > > > > > On Wed, Jan 18, 2023 at 2:32 AM Andrew Jones 
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Fri, Jan 13, 2023 at 11:34:53AM +0100, Alexandre Ghiti wrote:
> > > > > ...
> > > > > > > > +
> > > > > > > > +/* Get rid of 32-bit/64-bit incompatibility */
> > > > > > > > +for (int i = 0; i < 16; ++i) {
> > > > > > > > +if ((cpu->cfg.satp_mode.map & (1 << i)) && 
> > > > > > > > !valid_vm[i]) {
> > > > > > >
> > > > > > > If we ever define mode=1 for rv64, then 'sv32=on' will be 
> > > > > > > incorrectly
> > > > > > > accepted as an alias. I think we should simply not define the sv32
> > > > > > > property for rv64 nor the rv64-only modes for rv32. So, down in
> > > > > > > riscv_add_satp_mode_properties() we can add some
> > > > > > >
> > > > > > >   #if defined(TARGET_RISCV32)
> > > > > > >   ...
> > > > > > >   #elif defined(TARGET_RISCV64)
> > > > > > >   ...
> > > > > > >   #endif
> > > > > >
> > > > > > Do not add any #if defined(TARGET_RISCV32) to QEMU.
> > > > > >
> > > > > > We are aiming for the riscv64-softmmu to be able to emulate 32-bit
> > > > > > CPUs and compile time macros are the wrong solution here. Instead 
> > > > > > you
> > > > > > can get the xlen of the hart and use that.
> > > > > >
> > > > >
> > > > > Does this mean we want to be able to do the following?
> > > > >
> > > > >   qemu-system-riscv64 -cpu rv32,sv32=on ...
> > > >
> > > > That's the plan
> > > >
> > > > >
> > > > > If so, then can we move the object_property_add() for sv32 to
> > > > > rv32_base_cpu_init() and the rest to rv64_base_cpu_init()?
> >
> > Wait! Sorry I didn't read this carefully enough. No, that is not what
> > we want to do. That then won't support the vendor CPUs.
> >
> > We just want to add the properties to all CPUs. Then if an invalid
> > option is set we should return an error.

Maybe I just don't get this part...

> >
> > Note that the 64-bit only configs can be hidden behind a #if
> > defined(TARGET_RISCV64).
>
> OK, so we want the original suggestion of putting an
> 'if defined(TARGET_RISCV64)' in riscv_add_satp_mode_properties(),
> which is called from register_cpu_props(), for the 64-bit only
> configs, but to support emulation we can't put sv32 under an
> 'if defined(TARGET_RISCV32)'. Instead, we need to check the xlen
> supported by the cpu type. That makes sense to me, and I think
> it'd be easiest to do in cpu_riscv_set_satp() with something like
>
>   if (!strncmp(name, "rv32", 4) &&
>   RISCV_CPU(obj)->env.misa_mxl != MXL_RV32) {
>  ... fail with error message ...
>   }
>

...but what about simply using the runtime check when we add the
properties? Like this:

static void riscv_add_satp_mode_properties(Object *obj)
{
RISCVCPU *cpu = RISCV_CPU(obj);

if (cpu->env.misa_mxl == MXL_RV32) {
object_property_add(obj, "sv32", "bool", cpu_riscv_get_satp,
cpu_riscv_set_satp, NULL,
>cfg.satp_mode);
} else {
object_property_add(obj, "sv39", "bool", cpu_riscv_get_satp,
cpu_riscv_set_satp, NULL,
>cfg.satp_mode);
object_property_add(obj, "sv48", "bool", cpu_riscv_get_satp,
cpu_riscv_set_satp, NULL,
>cfg.satp_mode);
object_property_add(obj, "sv57", "bool", cpu_riscv_get_satp,
cpu_riscv_set_satp, NULL,
>cfg.satp_mode);
object_property_add(obj, "sv64", "bool", cpu_riscv_get_satp,
cpu_riscv_set_satp, NULL,
>cfg.satp_mode);
}
}

> Thanks,
> drew



Re: [PATCH v5 2/2] riscv: Allow user to set the satp mode

2023-01-19 Thread Alexandre Ghiti
Hi Alistair, Andrew,

On Thu, Jan 19, 2023 at 1:25 AM Alistair Francis  wrote:
>
> On Wed, Jan 18, 2023 at 10:19 PM Andrew Jones  wrote:
> >
> > On Wed, Jan 18, 2023 at 10:28:46AM +1000, Alistair Francis wrote:
> > > On Wed, Jan 18, 2023 at 2:32 AM Andrew Jones  
> > > wrote:
> > > >
> > > > On Fri, Jan 13, 2023 at 11:34:53AM +0100, Alexandre Ghiti wrote:
> > ...
> > > > > +
> > > > > +/* Get rid of 32-bit/64-bit incompatibility */
> > > > > +for (int i = 0; i < 16; ++i) {
> > > > > +if ((cpu->cfg.satp_mode.map & (1 << i)) && !valid_vm[i]) {
> > > >
> > > > If we ever define mode=1 for rv64, then 'sv32=on' will be incorrectly
> > > > accepted as an alias. I think we should simply not define the sv32
> > > > property for rv64 nor the rv64-only modes for rv32. So, down in
> > > > riscv_add_satp_mode_properties() we can add some
> > > >
> > > >   #if defined(TARGET_RISCV32)
> > > >   ...
> > > >   #elif defined(TARGET_RISCV64)
> > > >   ...
> > > >   #endif
> > >
> > > Do not add any #if defined(TARGET_RISCV32) to QEMU.
> > >
> > > We are aiming for the riscv64-softmmu to be able to emulate 32-bit
> > > CPUs and compile time macros are the wrong solution here. Instead you
> > > can get the xlen of the hart and use that.
> > >
> >
> > Does this mean we want to be able to do the following?
> >
> >   qemu-system-riscv64 -cpu rv32,sv32=on ...
>
> That's the plan
>
> >
> > If so, then can we move the object_property_add() for sv32 to
> > rv32_base_cpu_init() and the rest to rv64_base_cpu_init()?
> > Currently, that would be doing the same thing as proposed above,
> > since those functions are under TARGET_RISCV* defines, but I guess
> > the object_property_add()'s would then be in more or less the right
> > places for when the 32-bit emulation support work is started.
>
> Sounds like a good idea :)

What about riscv_any_cpu_init and riscv_host_cpu_init?

>
> Alistair
>
> >
> > Thanks,
> > drew



Re: [PATCH v5 2/2] riscv: Allow user to set the satp mode

2023-01-18 Thread Alexandre Ghiti
Hey Andrew,

On Tue, Jan 17, 2023 at 5:31 PM Andrew Jones  wrote:
>
> On Fri, Jan 13, 2023 at 11:34:53AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> > "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> > -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64  # Linux will boot using sv57 scheme by default
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> ># enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
> > -cpu rv64,sv32=on,sv32=off # Linux will boot using sv57 scheme (the default)
> >
> > In addition, we now correctly set the device-tree entry 'mmu-type' using
> > those new properties.
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> >  hw/riscv/virt.c|  19 ++--
> >  target/riscv/cpu.c | 221 +
> >  target/riscv/cpu.h |  19 
> >  target/riscv/csr.c |  17 +++-
> >  4 files changed, 262 insertions(+), 14 deletions(-)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index 94ff2a1584..48d034a5f7 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >  int cpu;
> >  uint32_t cpu_phandle;
> >  MachineState *mc = MACHINE(s);
> > -char *name, *cpu_name, *core_name, *intc_name;
> > +uint8_t satp_mode_max;
> > +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
> >
> >  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
> >  cpu_phandle = (*phandle)++;
> > @@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >  cpu_name = g_strdup_printf("/cpus/cpu@%d",
> >  s->soc[socket].hartid_base + cpu);
> >  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> > -if (riscv_feature(>soc[socket].harts[cpu].env,
> > -  RISCV_FEATURE_MMU)) {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -(is_32_bit) ? "riscv,sv32" : 
> > "riscv,sv48");
>
> I just noticed that for the virt machine type, when the user doesn't
> provide a satp mode cpu property on the command line, and hence gets
> the default mode, they'll be silently changed from sv48 to sv57. That
> default change should be a separate patch which comes after this one.
> BTW, why sv57 and not sv48 or sv64?

The device tree entry should match the max available satp mode even
though it makes little sense to have this entry in the first place:
the max satp mode is easily discoverable at runtime (the kernel does
that and does not care about the device tree entry).

But yes, this fix was mentioned at the very end of the commit log,
which was weird anyway, so I'll move that to its own patch.

>
> > -} else {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -"riscv,none");
> > -}
> > +
> > +satp_mode_max = satp_mode_max_from_map(
> > +s->soc[socket].harts[cpu].cfg.satp_mode.map);
> > +sv_name = g_strdup_printf("riscv,%s",
> > +  satp_mode_str(satp_mode_max, is_32_bit));
> > +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
> > +g_free(sv_name);
> > +
> >

[PATCH v5 2/2] riscv: Allow user to set the satp mode

2023-01-13 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on  # Linux will boot using sv57 scheme
-cpu rv64,sv39=on  # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64  # Linux will boot using sv57 scheme by default

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
-cpu rv64,sv32=on,sv32=off # Linux will boot using sv57 scheme (the default)

In addition, we now correctly set the device-tree entry 'mmu-type' using
those new properties.

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 221 +
 target/riscv/cpu.h |  19 
 target/riscv/csr.c |  17 +++-
 4 files changed, 262 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 94ff2a1584..48d034a5f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7181b34f86..1f0d040a80 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -229,6 +230,85 @@ static void set_vext_version(CPURISCVState *env, int 
vext_ver)
 env->vext_ver = vext_ver;
 }
 
+static uint8_t satp_mode_from_str(const char *satp_mode_str)
+{
+if (!strncmp(satp_mode_str, "sv32", 4)) {
+return VM_1_10_SV32;
+}
+
+if (!strncmp(satp_mode_str, "sv39", 4)) {
+return VM_1_10_SV39;
+}
+
+if (!strncmp(satp_mode_str, "sv48", 4)) {
+return VM_1_10_SV48;
+}
+
+if (!strncmp(satp_mode_str, "sv57", 4)) {
+return VM_1_10_SV57;
+}
+
+if (!strncmp(satp_mode_str, "sv64", 4)) {
+return VM_1_10_SV64;
+}
+
+g_assert_not_reached();
+}
+
+uint8_t satp_mode_max_from_map(uint32_t map)
+{
+/* map here has at least one bit set, so no problem with clz */
+return 31 - __builtin_clz(map);
+}
+
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
+{
+if (is_32_bit) {
+switch (satp_mode) {
+case VM_1_10_SV32:
+return "sv32";
+  

[PATCH v5 1/2] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-13 Thread Alexandre Ghiti
One can extract the DeviceState pointer from the Object pointer, so pass
the Object for future commits to access other fields of Object.

No functional changes intended.

Signed-off-by: Alexandre Ghiti 
---
 target/riscv/cpu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..7181b34f86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -247,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -280,7 +280,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -290,7 +290,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 /* Set latest version of privileged specification */
 set_priv_version(env, PRIV_VERSION_1_12_0);
 }
@@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 #endif
 
@@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void register_cpu_props(DeviceState *dev)
+static void register_cpu_props(Object *obj)
 {
 Property *prop;
+DeviceState *dev = DEVICE(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
-- 
2.37.2




[PATCH v5 0/2] riscv: Allow user to set the satp mode

2023-01-13 Thread Alexandre Ghiti
This introduces new properties to allow the user to set the satp mode,
see patch 1 for full syntax.

v5:
- Simplify v4 implementation by leveraging valid_vm_1_10_32/64, as
  suggested by Andrew
- Split the v4 patch into 2 patches as suggested by Andrew
- Lot of other minor corrections, from Andrew
- Set the satp mode N by disabling the satp mode N + 1
- Add a helper to set satp mode from a string, as suggested by Frank

v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

Alexandre Ghiti (2):
  riscv: Pass Object to register_cpu_props instead of DeviceState
  riscv: Allow user to set the satp mode

 hw/riscv/virt.c|  19 ++--
 target/riscv/cpu.c | 236 +++--
 target/riscv/cpu.h |  19 
 target/riscv/csr.c |  17 +++-
 4 files changed, 270 insertions(+), 21 deletions(-)

-- 
2.37.2




Re: [PATCH v4] riscv: Allow user to set the satp mode

2023-01-12 Thread Alexandre Ghiti
Hey Andrew,

Sorry about the response delay, I was traveling.

On Fri, Jan 6, 2023 at 4:30 PM Andrew Jones  wrote:
>
> On Mon, Dec 12, 2022 at 11:22:50AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "mbare", "sv32",
> > "sv39", "sv48", "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on # Linux will boot using sv39 scheme
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> >  # enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are
>  ^ from this #, it looks like a copy+paste
>  mistake

Yes, something is not right here, thanks.

> >
> > In addition, we now correctly set the device-tree entry 'mmu-type' using
> > those new properties.
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> > v4:
> > - Use custom boolean properties instead of OnOffAuto properties, based
> >   on ARMVQMap, as suggested by Andrew
> >
> > v3:
> > - Free sv_name as pointed by Bin
> > - Replace satp-mode with boolean properties as suggested by Andrew
> > - Removed RB from Atish as the patch considerably changed
> >
> > v2:
> > - Use error_setg + return as suggested by Alistair
> > - Add RB from Atish
> > - Fixed checkpatch issues missed in v1
> > - Replaced Ludovic email address with the rivos one
> >
> >  hw/riscv/virt.c|  20 +++--
> >  target/riscv/cpu.c | 217 +++--
> >  target/riscv/cpu.h |  25 ++
> >  target/riscv/csr.c |  13 ++-
> >  4 files changed, 256 insertions(+), 19 deletions(-)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index a5bc7353b4..9bb5ba7366 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >  int cpu;
> >  uint32_t cpu_phandle;
> >  MachineState *mc = MACHINE(s);
> > -char *name, *cpu_name, *core_name, *intc_name;
> > +uint8_t satp_mode_max;
> > +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
> >
> >  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
> >  cpu_phandle = (*phandle)++;
> > @@ -236,14 +237,15 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >  cpu_name = g_strdup_printf("/cpus/cpu@%d",
> >  s->soc[socket].hartid_base + cpu);
> >  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> > -if (riscv_feature(>soc[socket].harts[cpu].env,
> > -  RISCV_FEATURE_MMU)) {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -(is_32_bit) ? "riscv,sv32" : 
> > "riscv,sv48");
> > -} else {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -"riscv,none");
> > -}
> > +
> > +satp_mode_max = satp_mode_max_from_map(
> > +s->soc[socket].harts[cpu].cfg.satp_mode.map,
> > +is_32_bit);
> > +sv_name = g_strdup_printf("riscv,%s",
> > +  satp_mode_str(satp_mode_max, is_32_bit));
> > +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
> > +g_free(sv_name);
> > +
> >  name = riscv_isa_string(>soc[socket].harts[cpu]);
> >  qemu

Re: [PATCH v4] riscv: Allow user to set the satp mode

2023-01-05 Thread Alexandre Ghiti
On Fri, Dec 16, 2022 at 2:03 PM Alexandre Ghiti  wrote:
>
> Hi Frank,
>
> On Fri, Dec 16, 2022 at 10:32 AM Frank Chang  wrote:
> >
> > Hi Alexandre,
> >
> > Thanks for the contribution. This is really helpful.
> >
> > It seems like if we want to specify the SATP mode for the "named" CPUs,
> > we have to do, e.g.:
> > cpu->cfg.satp_mode.map |= (1 << idx_satp_mode_from_str("sv39"));
> > in each CPU's init function.
> >
> > Can we add another helper function to wrap this for the "named" CPUs?
>
> Yes sure, I'll add some helpers for the bit operations in general,
> that will be cleaner. And I'll set the default satp mode for the
> current cpus in each cpu init function too.
>
> Thanks for your remarks,
>
> Alex
>
> >
> > Regards,
> > Frank Chang
> >
> >
> > On Mon, Dec 12, 2022 at 6:23 PM Alexandre Ghiti  
> > wrote:
> >>
> >> RISC-V specifies multiple sizes for addressable memory and Linux probes for
> >> the machine's support at startup via the satp CSR register (done in
> >> csr.c:validate_vm).
> >>
> >> As per the specification, sv64 must support sv57, which in turn must
> >> support sv48...etc. So we can restrict machine support by simply setting 
> >> the
> >> "highest" supported mode and the bare mode is always supported.
> >>
> >> You can set the satp mode using the new properties "mbare", "sv32",
> >> "sv39", "sv48", "sv57" and "sv64" as follows:
> >> -cpu rv64,sv57=on # Linux will boot using sv57 scheme
> >> -cpu rv64,sv39=on # Linux will boot using sv39 scheme
> >>
> >> We take the highest level set by the user:
> >> -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >>
> >> We make sure that invalid configurations are rejected:
> >> -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> >> -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> >># enabled
> >>
> >> We accept "redundant" configurations:
> >> -cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are
> >>
> >> In addition, we now correctly set the device-tree entry 'mmu-type' using
> >> those new properties.
> >>
> >> Co-Developed-by: Ludovic Henry 
> >> Signed-off-by: Ludovic Henry 
> >> Signed-off-by: Alexandre Ghiti 
> >> ---
> >> v4:
> >> - Use custom boolean properties instead of OnOffAuto properties, based
> >>   on ARMVQMap, as suggested by Andrew
> >>
> >> v3:
> >> - Free sv_name as pointed by Bin
> >> - Replace satp-mode with boolean properties as suggested by Andrew
> >> - Removed RB from Atish as the patch considerably changed
> >>
> >> v2:
> >> - Use error_setg + return as suggested by Alistair
> >> - Add RB from Atish
> >> - Fixed checkpatch issues missed in v1
> >> - Replaced Ludovic email address with the rivos one
> >>
> >>  hw/riscv/virt.c|  20 +++--
> >>  target/riscv/cpu.c | 217 +++--
> >>  target/riscv/cpu.h |  25 ++
> >>  target/riscv/csr.c |  13 ++-
> >>  4 files changed, 256 insertions(+), 19 deletions(-)
> >>
> >> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> >> index a5bc7353b4..9bb5ba7366 100644
> >> --- a/hw/riscv/virt.c
> >> +++ b/hw/riscv/virt.c
> >> @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> >> int socket,
> >>  int cpu;
> >>  uint32_t cpu_phandle;
> >>  MachineState *mc = MACHINE(s);
> >> -char *name, *cpu_name, *core_name, *intc_name;
> >> +uint8_t satp_mode_max;
> >> +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
> >>
> >>  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
> >>  cpu_phandle = (*phandle)++;
> >> @@ -236,14 +237,15 @@ static void create_fdt_socket_cpus(RISCVVirtState 
> >> *s, int socket,
> >>  cpu_name = g_strdup_printf("/cpus/cpu@%d",
> >>  s->soc[socket].hartid_base + cpu);
> >>  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> >> -if (riscv_feature(>soc[socket].harts[cpu].env,
> >> -  RISCV_FEATURE_MMU)) {
> >> -qemu_fdt_set

Re: [PATCH v4] riscv: Allow user to set the satp mode

2022-12-16 Thread Alexandre Ghiti
Hi Frank,

On Fri, Dec 16, 2022 at 10:32 AM Frank Chang  wrote:
>
> Hi Alexandre,
>
> Thanks for the contribution. This is really helpful.
>
> It seems like if we want to specify the SATP mode for the "named" CPUs,
> we have to do, e.g.:
> cpu->cfg.satp_mode.map |= (1 << idx_satp_mode_from_str("sv39"));
> in each CPU's init function.
>
> Can we add another helper function to wrap this for the "named" CPUs?

Yes sure, I'll add some helpers for the bit operations in general,
that will be cleaner. And I'll set the default satp mode for the
current cpus in each cpu init function too.

Thanks for your remarks,

Alex

>
> Regards,
> Frank Chang
>
>
> On Mon, Dec 12, 2022 at 6:23 PM Alexandre Ghiti  
> wrote:
>>
>> RISC-V specifies multiple sizes for addressable memory and Linux probes for
>> the machine's support at startup via the satp CSR register (done in
>> csr.c:validate_vm).
>>
>> As per the specification, sv64 must support sv57, which in turn must
>> support sv48...etc. So we can restrict machine support by simply setting the
>> "highest" supported mode and the bare mode is always supported.
>>
>> You can set the satp mode using the new properties "mbare", "sv32",
>> "sv39", "sv48", "sv57" and "sv64" as follows:
>> -cpu rv64,sv57=on # Linux will boot using sv57 scheme
>> -cpu rv64,sv39=on # Linux will boot using sv39 scheme
>>
>> We take the highest level set by the user:
>> -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
>>
>> We make sure that invalid configurations are rejected:
>> -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
>> -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
>># enabled
>>
>> We accept "redundant" configurations:
>> -cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are
>>
>> In addition, we now correctly set the device-tree entry 'mmu-type' using
>> those new properties.
>>
>> Co-Developed-by: Ludovic Henry 
>> Signed-off-by: Ludovic Henry 
>> Signed-off-by: Alexandre Ghiti 
>> ---
>> v4:
>> - Use custom boolean properties instead of OnOffAuto properties, based
>>   on ARMVQMap, as suggested by Andrew
>>
>> v3:
>> - Free sv_name as pointed by Bin
>> - Replace satp-mode with boolean properties as suggested by Andrew
>> - Removed RB from Atish as the patch considerably changed
>>
>> v2:
>> - Use error_setg + return as suggested by Alistair
>> - Add RB from Atish
>> - Fixed checkpatch issues missed in v1
>> - Replaced Ludovic email address with the rivos one
>>
>>  hw/riscv/virt.c|  20 +++--
>>  target/riscv/cpu.c | 217 +++--
>>  target/riscv/cpu.h |  25 ++
>>  target/riscv/csr.c |  13 ++-
>>  4 files changed, 256 insertions(+), 19 deletions(-)
>>
>> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>> index a5bc7353b4..9bb5ba7366 100644
>> --- a/hw/riscv/virt.c
>> +++ b/hw/riscv/virt.c
>> @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
>> int socket,
>>  int cpu;
>>  uint32_t cpu_phandle;
>>  MachineState *mc = MACHINE(s);
>> -char *name, *cpu_name, *core_name, *intc_name;
>> +uint8_t satp_mode_max;
>> +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
>>
>>  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
>>  cpu_phandle = (*phandle)++;
>> @@ -236,14 +237,15 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
>> int socket,
>>  cpu_name = g_strdup_printf("/cpus/cpu@%d",
>>  s->soc[socket].hartid_base + cpu);
>>  qemu_fdt_add_subnode(mc->fdt, cpu_name);
>> -if (riscv_feature(>soc[socket].harts[cpu].env,
>> -  RISCV_FEATURE_MMU)) {
>> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
>> -(is_32_bit) ? "riscv,sv32" : 
>> "riscv,sv48");
>> -} else {
>> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
>> -"riscv,none");
>> -}
>> +
>> +satp_mode_max = satp_mode_max_from_map(
>> +s->soc[socket].harts[cpu].cfg.satp_mode.map,
>> +is_32_bit);
>> + 

[PATCH v4] riscv: Allow user to set the satp mode

2022-12-12 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "mbare", "sv32",
"sv39", "sv48", "sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are

In addition, we now correctly set the device-tree entry 'mmu-type' using
those new properties.

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
v4:
- Use custom boolean properties instead of OnOffAuto properties, based
  on ARMVQMap, as suggested by Andrew

v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

 hw/riscv/virt.c|  20 +++--
 target/riscv/cpu.c | 217 +++--
 target/riscv/cpu.h |  25 ++
 target/riscv/csr.c |  13 ++-
 4 files changed, 256 insertions(+), 19 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a5bc7353b4..9bb5ba7366 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+uint8_t satp_mode_max;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +237,15 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+satp_mode_max = satp_mode_max_from_map(
+s->soc[socket].harts[cpu].cfg.satp_mode.map,
+is_32_bit);
+sv_name = g_strdup_printf("riscv,%s",
+  satp_mode_str(satp_mode_max, is_32_bit));
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d14e95c9dc..639231ce2e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -27,6 +27,7 @@
 #include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -199,7 +200,7 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
-static void register_cpu_props(DeviceState *dev);
+static void register_cpu_props(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -237,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
-register_cpu_props(DEVICE(obj));
+register_cpu_props(obj);
 }
 
 #if defined(TARGET_RISCV64)
@@ -246,7 +247,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa

Re: [PATCH v3] riscv: Allow user to set the satp mode

2022-12-05 Thread Alexandre Ghiti
Hi Andrew,

On Thu, Dec 1, 2022 at 3:47 PM Andrew Jones  wrote:

> On Thu, Dec 01, 2022 at 10:36:23AM +0100, Alexandre Ghiti wrote:
> > RISC-V specifies multiple sizes for addressable memory and Linux probes
> for
> > the machine's support at startup via the satp CSR register (done in
> > csr.c:validate_vm).
> >
> > As per the specification, sv64 must support sv57, which in turn must
> > support sv48...etc. So we can restrict machine support by simply setting
> the
> > "highest" supported mode and the bare mode is always supported.
> >
> > You can set the satp mode using the new properties "mbare", "sv32",
> > "sv39", "sv48", "sv57" and "sv64" as follows:
> > -cpu rv64,sv57=on # Linux will boot using sv57 scheme
> > -cpu rv64,sv39=on # Linux will boot using sv39 scheme
> >
> > We take the highest level set by the user:
> > -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
> >
> > We make sure that invalid configurations are rejected:
> > -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> > -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
> >  # enabled
> >
> > We accept "redundant" configurations:
> > -cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are
> >
> > In addition, we now correctly set the device-tree entry 'mmu-type' using
> > those new properties.
> >
> > Co-Developed-by: Ludovic Henry 
> > Signed-off-by: Ludovic Henry 
> > Signed-off-by: Alexandre Ghiti 
> > ---
> > v3:
> > - Free sv_name as pointed by Bin
> > - Replace satp-mode with boolean properties as suggested by Andrew
> > - Removed RB from Atish as the patch considerably changed
> >
> > v2:
> > - Use error_setg + return as suggested by Alistair
> > - Add RB from Atish
> > - Fixed checkpatch issues missed in v1
> > - Replaced Ludovic email address with the rivos one
> >
> >  hw/riscv/virt.c |  16 ++--
> >  target/riscv/cpu.c  | 164 
> >  target/riscv/cpu.h  |   8 ++
> >  target/riscv/cpu_bits.h |   1 +
> >  target/riscv/csr.c  |   8 +-
> >  5 files changed, 186 insertions(+), 11 deletions(-)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index a5bc7353b4..bb7c739a74 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -228,7 +228,7 @@ static void create_fdt_socket_cpus(RISCVVirtState
> *s, int socket,
> >  int cpu;
> >  uint32_t cpu_phandle;
> >  MachineState *mc = MACHINE(s);
> > -char *name, *cpu_name, *core_name, *intc_name;
> > +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
> >
> >  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
> >  cpu_phandle = (*phandle)++;
> > @@ -236,14 +236,12 @@ static void create_fdt_socket_cpus(RISCVVirtState
> *s, int socket,
> >  cpu_name = g_strdup_printf("/cpus/cpu@%d",
> >  s->soc[socket].hartid_base + cpu);
> >  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> > -if (riscv_feature(>soc[socket].harts[cpu].env,
> > -  RISCV_FEATURE_MMU)) {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -(is_32_bit) ? "riscv,sv32" :
> "riscv,sv48");
> > -} else {
> > -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> > -"riscv,none");
> > -}
> > +
> > +sv_name = g_strdup_printf("riscv,%s",
> > +
> s->soc[socket].harts[cpu].cfg.satp_mode_str);
> > +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
> > +g_free(sv_name);
> > +
> >  name = riscv_isa_string(>soc[socket].harts[cpu]);
> >  qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
> >  g_free(name);
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index d14e95c9dc..51c06ed057 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -907,6 +907,66 @@ static void riscv_cpu_realize(DeviceState *dev,
> Error **errp)
> >   }
> >  #endif
> >
> > +/*
> > + * Either a cpu sets its supported satp_mode in XXX_cpu_init
> > + * or the user sets this value using

[PATCH v3] riscv: Allow user to set the satp mode

2022-12-01 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.

You can set the satp mode using the new properties "mbare", "sv32",
"sv39", "sv48", "sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme

We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme

We make sure that invalid configurations are rejected:
-cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
   # enabled

We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are

In addition, we now correctly set the device-tree entry 'mmu-type' using
those new properties.

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
v3:
- Free sv_name as pointed by Bin
- Replace satp-mode with boolean properties as suggested by Andrew
- Removed RB from Atish as the patch considerably changed

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

 hw/riscv/virt.c |  16 ++--
 target/riscv/cpu.c  | 164 
 target/riscv/cpu.h  |   8 ++
 target/riscv/cpu_bits.h |   1 +
 target/riscv/csr.c  |   8 +-
 5 files changed, 186 insertions(+), 11 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a5bc7353b4..bb7c739a74 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +236,12 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+sv_name = g_strdup_printf("riscv,%s",
+  s->soc[socket].harts[cpu].cfg.satp_mode_str);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+g_free(sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d14e95c9dc..51c06ed057 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -907,6 +907,66 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
  }
 #endif
 
+/*
+ * Either a cpu sets its supported satp_mode in XXX_cpu_init
+ * or the user sets this value using satp_mode property.
+ */
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+
+cpu->cfg.satp_mode = VM_1_10_UNDEF;
+
+if (rv32) {
+if (cpu->cfg.sv32 == ON_OFF_AUTO_ON) {
+cpu->cfg.satp_mode_str = g_strdup("sv32");
+cpu->cfg.satp_mode = VM_1_10_SV32;
+} else if (cpu->cfg.mbare == ON_OFF_AUTO_ON) {
+cpu->cfg.satp_mode_str = g_strdup("none");
+cpu->cfg.satp_mode = VM_1_10_MBARE;
+}
+} else {
+if (cpu->cfg.sv64 == ON_OFF_AUTO_ON) {
+cpu->cfg.satp_mode_str = g_strdup("sv64");
+cpu->cfg.satp_mode = VM_1_10_SV64;
+} else if (cpu->cfg.sv57 == ON_OFF_AUTO_ON) {
+cpu->cfg.satp_mode_str = g_strdup("sv57");
+cpu->cfg.satp_mode = VM_1_10_SV57;
+} else if (cpu->cfg.sv48 == ON_OFF_AUTO_ON) {
+cpu->cfg.satp_mode_str = g_strdup("sv48");
+cpu->cfg.satp_mode = VM_1_10_SV48;
+} els

[PATCH v2] riscv: Add RISCVCPUConfig.satp_mode to set sv48, sv57, etc.

2022-11-25 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode in the satp_mode property. And the bare mode is
always supported.

You can set this new property as follows:
-cpu rv64,satp-mode=sv48 # Linux will boot using sv48 scheme
-cpu rv64,satp-mode=sv39 # Linux will boot using sv39 scheme

In addition, we now correctly set the device-tree entry 'mmu-type' using
this new satp_mode property.

Reviewed-by: Atish Patra 
Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---

v2:
- Use error_setg + return as suggested by Alistair
- Add RB from Atish
- Fixed checkpatch issues missed in v1
- Replaced Ludovic email address with the rivos one

 hw/riscv/virt.c| 15 ++-
 target/riscv/cpu.c | 45 +
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c |  8 ++--
 4 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a5bc7353b4..77484b5cae 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +236,11 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+sv_name = g_strdup_printf("riscv,%s",
+  s->soc[socket].harts[cpu].cfg.satp_mode_str);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d14e95c9dc..c86dc5058d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -907,6 +907,48 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
  }
 #endif
 
+/*
+ * Either a cpu sets its supported satp_mode in XXX_cpu_init
+ * or the user sets this value using satp_mode property.
+ */
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+if (cpu->cfg.satp_mode_str) {
+if (!g_strcmp0(cpu->cfg.satp_mode_str, "none"))
+cpu->cfg.satp_mode = VM_1_10_MBARE;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv32") && rv32)
+cpu->cfg.satp_mode = VM_1_10_SV32;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv39") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV39;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv48") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV48;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv57") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV57;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv64") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV64;
+else {
+error_setg(errp, "Unknown option for satp_mode: %s",
+   cpu->cfg.satp_mode_str);
+return;
+}
+} else {
+/*
+ * If unset by both the user and the cpu, we fallback to sv32 for 
32-bit
+ * or sv57 for 64-bit when a MMU is present, and bare otherwise.
+ */
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+if (rv32) {
+cpu->cfg.satp_mode_str = g_strdup("sv32");
+cpu->cfg.satp_mode = VM_1_10_SV32;
+} else {
+cpu->cfg.satp_mode_str = g_strdup("sv57");
+cpu->cfg.satp_mode = VM_1_10_SV57;
+}
+} else {
+cpu->cfg.satp_mode_str = g_strdup("none");
+

[PATCH] riscv: Add RISCVCPUConfig.satp_mode to set sv48, sv57, etc.

2022-11-17 Thread Alexandre Ghiti
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).

As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode in the satp_mode property. And the bare mode is
always supported.

You can set this new property as follows:
-cpu rv64,satp-mode=sv48 # Linux will boot using sv48 scheme
-cpu rv64,satp-mode=sv39 # Linux will boot using sv39 scheme

In addition, we now correctly set the device-tree entry 'mmu-type' using
this new satp_mode property.

Co-Developed-by: Ludovic Henry 
Signed-off-by: Ludovic Henry 
Signed-off-by: Alexandre Ghiti 
---
 hw/riscv/virt.c| 15 ++-
 target/riscv/cpu.c | 45 +
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c |  6 --
 4 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a5bc7353b4..77484b5cae 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -228,7 +228,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 int cpu;
 uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
-char *name, *cpu_name, *core_name, *intc_name;
+char *name, *cpu_name, *core_name, *intc_name, *sv_name;
 
 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
 cpu_phandle = (*phandle)++;
@@ -236,14 +236,11 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 cpu_name = g_strdup_printf("/cpus/cpu@%d",
 s->soc[socket].hartid_base + cpu);
 qemu_fdt_add_subnode(mc->fdt, cpu_name);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_MMU)) {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
-} else {
-qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
-"riscv,none");
-}
+
+sv_name = g_strdup_printf("riscv,%s",
+  s->soc[socket].harts[cpu].cfg.satp_mode_str);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
+
 name = riscv_isa_string(>soc[socket].harts[cpu]);
 qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
 g_free(name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d14e95c9dc..efdb530ad9 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -907,6 +907,48 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
  }
 #endif
 
+/*
+ * Either a cpu sets its supported satp_mode in XXX_cpu_init
+ * or the user sets this value using satp_mode property.
+ */
+bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
+if (cpu->cfg.satp_mode_str) {
+if (!g_strcmp0(cpu->cfg.satp_mode_str, "none"))
+cpu->cfg.satp_mode = VM_1_10_MBARE;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv32") && rv32)
+cpu->cfg.satp_mode = VM_1_10_SV32;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv39") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV39;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv48") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV48;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv57") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV57;
+else if (!g_strcmp0(cpu->cfg.satp_mode_str, "sv64") && !rv32)
+cpu->cfg.satp_mode = VM_1_10_SV64;
+else {
+error_report("Unknown option for satp_mode: %s",
+ cpu->cfg.satp_mode_str);
+exit(EXIT_FAILURE);
+}
+} else {
+/*
+ * If unset by both the user and the cpu, we fallback to sv32 for 
32-bit
+ * or sv57 for 64-bit when a MMU is present, and bare otherwise.
+ */
+if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
+if (rv32) {
+cpu->cfg.satp_mode_str = g_strdup("sv32");
+cpu->cfg.satp_mode = VM_1_10_SV32;
+} else {
+cpu->cfg.satp_mode_str = g_strdup("sv57");
+cpu->cfg.satp_mode = VM_1_10_SV57;
+}
+} else {
+cpu->cfg.satp_mode_str = g_strdup("none");
+cpu->cfg.satp_mode = VM_1_10_MBARE;
+}
+}
+
 riscv_cpu_register_gdb_regs_for_features(cs);
 
 qemu_init_vcpu(cs);
@@ -1094,6 +1136,9 @@ static Property riscv_cpu