qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 00/36]  Add RISC-V Hypervisor Extension v0.5
@ 2019-12-09 18:10 Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Alistair Francis
                   ` (59 more replies)
  0 siblings, 60 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

This patch series adds the RISC-V Hypervisor extension v0.5. This is the
latest draft spec of the Hypervisor extension.

The Hypervisor extension is disabled by default, so this series should
result in no changes to anyone using QEMU unless they enable the
extension. The extention can be enabled with the -cpu property (see
below).

Testing of this implementation has been done by using the baremetal
Xvisor Hypervisor. We are able to run two Linux guests (that's all I
have tried) as guests in 64-bit. In 32-bit so far I can only run
baremetal guests, but I think this is a baremetal boot loader issue and
not an issue in QEMU.

The RISC-V KVM implementation was also written using these patches. The
KVM implementation is currently under review.

At the moment this spec is in a draft state and is subject to change. As
QEMU is extreamly useful in early bring up I think it makes sense for
QEMU to support non-frozen extensions.

Thanks to Anup for doing the initial port of Xvisor. The port is avaliable here:
https://github.com/avpatel/xvisor-next and will run on QEMU.

Also thanks to Atish for implementing the SBI call support in Xvisor and
for lots of help debugging.

To run this yourself:
 1. Apply this patch series to QEMU. The latest branch can be found here:
      https://github.com/alistair23/qemu/tree/mainline/alistair/riscv-hyp-ext-v0.5.next
 2. Get the version of OpenSBI that supports the H extension. This can
    be found here:
      https://github.com/avpatel/opensbi/tree/riscv_hyp_ext_0_5_v1
 3. Build the next release of Xvisor. It is available here:
      https://github.com/avpatel/xvisor-next
 4. Make sure you build the Xvisor tests, see here for details:
      https://github.com/avpatel/xvisor-next/tree/master/tests/riscv/virt64/linux
 5. Run QEMU:
     ./riscv64-softmmu/qemu-system-riscv64 -nographic \
       -machine virt -cpu rv64,x-h=true \
       -serial mon:stdio -serial null -m 4G \
       -device loader,file=vmm.bin,addr=0x80200000 \
       -kernel fw_jump.elf \
       -initrd vmm-disk-linux.img \
       -append "vmm.console=uart@10000000 vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""

   Once you get to the prompt you can start the geust by running:
     guest kick guest0
   You can then bind to the serial port using:
     vserial bind guest0/uart0
   Then you can start Linux using:
     autoexec

 This was all tested with the mainline 5.2/5.3 kernels.

There is very early work on a Xen port as well which is avaliable here:
https://github.com/alistair23/xen/tree/alistair/riscv-port

ToDo/Issues
 - Get 32-bit fully working



Alistair Francis (36):
  target/riscv: Convert MIP CSR to target_ulong
  target/riscv: Don't set write permissions on dirty PTEs
  target/riscv: Add the Hypervisor extension
  target/riscv: Add the Hypervisor CSRs to CPUState
  target/riscv: Add support for the new execption numbers
  target/riscv: Rename the H irqs to VS irqs
  target/riscv: Add the virtulisation mode
  target/riscv: Add the force HS exception mode
  target/riscv: Fix CSR perm checking for HS mode
  target/riscv: Print priv and virt in disas log
  target/riscv: Dump Hypervisor registers if enabled
  target/riscv: Add Hypervisor CSR access functions
  target/riscv: Add Hypervisor virtual CSRs accesses
  target/riscv: Add Hypervisor virtual CSRs accesses
  target/riscv: Convert mstatus to pointers
  target/riscv: Add virtual register swapping function
  target/riscv: Set VS bits in mideleg for Hyp extension
  target/riscv: Extend the MIE CSR to support virtulisation
  target/riscv: Extend the SIP CSR to support virtulisation
  target/riscv: Add support for virtual interrupt setting
  target/ricsv: Flush the TLB on virtulisation mode changes
  target/riscv: Generate illegal instruction on WFI when V=1
  target/riscv: Add hypvervisor trap support
  target/riscv: Add Hypervisor trap return support
  target/riscv: Add hfence instructions
  target/riscv: Remove the hret instruction
  target/riscv: Disable guest FP support based on virtual status
  target/riscv: Mark both sstatus and vsstatus as dirty
  target/riscv: Respect MPRV and SPRV for floating point ops
  target/riscv: Allow specifying MMU stage
  target/riscv: Implement second stage MMU
  target/riscv: Raise the new execptions when 2nd stage translation
    fails
  target/riscv: Set htval and mtval2 on execptions
  target/riscv: Add support for the 32-bit MSTATUSH CSR
  target/riscv: Add the MSTATUS_MPV_ISSET helper macro
  target/riscv: Allow enabling the Hypervisor extension

 target/riscv/cpu.c                            |  71 ++-
 target/riscv/cpu.h                            |  58 +-
 target/riscv/cpu_bits.h                       | 111 ++--
 target/riscv/cpu_helper.c                     | 501 +++++++++++++++---
 target/riscv/csr.c                            | 389 +++++++++++++-
 target/riscv/gdbstub.c                        |  11 +-
 target/riscv/insn32.decode                    |  22 +-
 .../riscv/insn_trans/trans_privileged.inc.c   |  45 +-
 target/riscv/op_helper.c                      |  81 ++-
 target/riscv/translate.c                      |  34 ++
 10 files changed, 1161 insertions(+), 162 deletions(-)

-- 
2.24.0



^ permalink raw reply	[flat|nested] 78+ messages in thread

* [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Alistair Francis
                   ` (58 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

The MIP CSR is a xlen CSR, it was only 32-bits to allow atomic access.
Now that we don't use atomics for MIP we can change this back to a xlen
CSR.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c | 2 +-
 target/riscv/cpu.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d37861a430..e521ebe2e1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -224,7 +224,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 #ifndef CONFIG_USER_ONLY
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
-    qemu_fprintf(f, " %s 0x%x\n", "mip     ", env->mip);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ", env->mip);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e59343e13c..f889427869 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,7 +121,7 @@ struct CPURISCVState {
     target_ulong mhartid;
     target_ulong mstatus;
 
-    uint32_t mip;
+    target_ulong mip;
     uint32_t miclaim;
 
     target_ulong mie;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 03/36] target/riscv: Add the Hypervisor extension Alistair Francis
                   ` (57 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Setting write permission on dirty PTEs results in userspace inside a
Hypervisor guest (VU) becoming corrupted. This appears to be because it
ends up with write permission in the second stage translation in cases
where we aren't doing a store.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
 target/riscv/cpu_helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 767c8762ac..0de3a468eb 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -344,10 +344,8 @@ restart:
             if ((pte & PTE_X)) {
                 *prot |= PAGE_EXEC;
             }
-            /* add write permission on stores or if the page is already dirty,
-               so that we TLB miss on later writes to update the dirty bit */
-            if ((pte & PTE_W) &&
-                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
+            /* add write permission on stores */
+            if ((pte & PTE_W) && (access_type == MMU_DATA_STORE)) {
                 *prot |= PAGE_WRITE;
             }
             return TRANSLATE_SUCCESS;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 03/36] target/riscv: Add the Hypervisor extension
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Alistair Francis
                   ` (56 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Chih-Min Chao <chihmin.chao@sifive.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f889427869..91e1c56fc4 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -67,6 +67,7 @@
 #define RVC RV('C')
 #define RVS RV('S')
 #define RVU RV('U')
+#define RVH RV('H')
 
 /* S extension denotes that Supervisor mode exists, however it is possible
    to have a core that support S mode but does not have an MMU and there
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (2 preceding siblings ...)
  2019-12-09 18:10 ` [PATCH v1 03/36] target/riscv: Add the Hypervisor extension Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Alistair Francis
                   ` (55 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Add the Hypervisor CSRs to CPUState and at the same time (to avoid
bisect issues) update the CSR macros for the v0.5 Hyp spec.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h      | 21 +++++++++++++++++++++
 target/riscv/cpu_bits.h | 34 +++++++++++++++++++++-------------
 target/riscv/gdbstub.c  | 11 ++++++-----
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 91e1c56fc4..bab938103d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -143,6 +143,27 @@ struct CPURISCVState {
     target_ulong mcause;
     target_ulong mtval;  /* since: priv-1.10.0 */
 
+    /* Hypervisor CSRs */
+    target_ulong hstatus;
+    target_ulong hedeleg;
+    target_ulong hideleg;
+    target_ulong hcounteren;
+    target_ulong htval;
+    target_ulong htinst;
+    target_ulong hgatp;
+
+    /* Virtual CSRs */
+    target_ulong vsstatus;
+    target_ulong vstvec;
+    target_ulong vsscratch;
+    target_ulong vsepc;
+    target_ulong vscause;
+    target_ulong vstval;
+    target_ulong vsatp;
+
+    target_ulong mtval2;
+    target_ulong mtinst;
+
     target_ulong scounteren;
     target_ulong mcounteren;
 
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index e99834856c..25c0fb258d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -177,8 +177,14 @@
 #define CSR_HSTATUS         0x600
 #define CSR_HEDELEG         0x602
 #define CSR_HIDELEG         0x603
-#define CSR_HCOUNTERNEN     0x606
+#define CSR_HIE             0x604
+#define CSR_HCOUNTEREN      0x606
+#define CSR_HTVAL           0x643
+#define CSR_HIP             0x644
+#define CSR_HTINST          0x64A
 #define CSR_HGATP           0x680
+#define CSR_HTIMEDELTA      0x605
+#define CSR_HTIMEDELTAH     0x615
 
 #if defined(TARGET_RISCV32)
 #define HGATP_MODE           SATP32_MODE
@@ -191,6 +197,20 @@
 #define HGATP_PPN            SATP64_PPN
 #endif
 
+/* Virtual CSRs */
+#define CSR_VSSTATUS        0x200
+#define CSR_VSIE            0x204
+#define CSR_VSTVEC          0x205
+#define CSR_VSSCRATCH       0x240
+#define CSR_VSEPC           0x241
+#define CSR_VSCAUSE         0x242
+#define CSR_VSTVAL          0x243
+#define CSR_VSIP            0x244
+#define CSR_VSATP           0x280
+
+#define CSR_MTINST          0x34a
+#define CSR_MTVAL2          0x34b
+
 /* Physical Memory Protection */
 #define CSR_PMPCFG0         0x3a0
 #define CSR_PMPCFG1         0x3a1
@@ -313,17 +333,6 @@
 #define CSR_MHPMCOUNTER30H  0xb9e
 #define CSR_MHPMCOUNTER31H  0xb9f
 
-/* Legacy Hypervisor Trap Setup (priv v1.9.1) */
-#define CSR_HIE             0x204
-#define CSR_HTVEC           0x205
-
-/* Legacy Hypervisor Trap Handling (priv v1.9.1) */
-#define CSR_HSCRATCH        0x240
-#define CSR_HEPC            0x241
-#define CSR_HCAUSE          0x242
-#define CSR_HBADADDR        0x243
-#define CSR_HIP             0x244
-
 /* Legacy Machine Protection and Translation (priv v1.9.1) */
 #define CSR_MBASE           0x380
 #define CSR_MBOUND          0x381
@@ -400,7 +409,6 @@
 
 /* hstatus CSR bits */
 #define HSTATUS_SPRV         0x00000001
-#define HSTATUS_STL          0x00000040
 #define HSTATUS_SPV          0x00000080
 #define HSTATUS_SP2P         0x00000100
 #define HSTATUS_SP2V         0x00000200
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 1a7947e019..6d606f0d90 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -130,6 +130,8 @@ static int csr_register_map[] = {
     CSR_MCAUSE,
     CSR_MTVAL,
     CSR_MIP,
+    CSR_MTINST,
+    CSR_MTVAL2,
     CSR_PMPCFG0,
     CSR_PMPCFG1,
     CSR_PMPCFG2,
@@ -252,12 +254,11 @@ static int csr_register_map[] = {
     CSR_HEDELEG,
     CSR_HIDELEG,
     CSR_HIE,
-    CSR_HTVEC,
-    CSR_HSCRATCH,
-    CSR_HEPC,
-    CSR_HCAUSE,
-    CSR_HBADADDR,
+    CSR_HCOUNTEREN,
+    CSR_HTVAL,
     CSR_HIP,
+    CSR_HTINST,
+    CSR_HGATP,
     CSR_MBASE,
     CSR_MBOUND,
     CSR_MIBASE,
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 05/36] target/riscv: Add support for the new execption numbers
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (3 preceding siblings ...)
  2019-12-09 18:10 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Alistair Francis
                   ` (54 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

The v0.5 Hypervisor spec add new execption numbers, let's add support
for those.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c        |  8 ++++++++
 target/riscv/cpu_bits.h   | 35 +++++++++++++++++++----------------
 target/riscv/cpu_helper.c |  7 +++++--
 target/riscv/csr.c        |  7 +++++--
 4 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e521ebe2e1..d23d2cba64 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -67,6 +67,14 @@ const char * const riscv_excp_names[] = {
     "load_page_fault",
     "reserved",
     "store_page_fault"
+    "reserved",
+    "reserved",
+    "reserved",
+    "reserved",
+    "guest_exec_page_fault",
+    "guest_load_page_fault",
+    "reserved",
+    "guest_store_page_fault"
 };
 
 const char * const riscv_intr_names[] = {
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 25c0fb258d..9ce73c36de 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -488,22 +488,25 @@
 #define DEFAULT_RSTVEC      0x1000
 
 /* Exception causes */
-#define EXCP_NONE                          -1 /* sentinel value */
-#define RISCV_EXCP_INST_ADDR_MIS           0x0
-#define RISCV_EXCP_INST_ACCESS_FAULT       0x1
-#define RISCV_EXCP_ILLEGAL_INST            0x2
-#define RISCV_EXCP_BREAKPOINT              0x3
-#define RISCV_EXCP_LOAD_ADDR_MIS           0x4
-#define RISCV_EXCP_LOAD_ACCESS_FAULT       0x5
-#define RISCV_EXCP_STORE_AMO_ADDR_MIS      0x6
-#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT  0x7
-#define RISCV_EXCP_U_ECALL                 0x8
-#define RISCV_EXCP_S_ECALL                 0x9
-#define RISCV_EXCP_H_ECALL                 0xa
-#define RISCV_EXCP_M_ECALL                 0xb
-#define RISCV_EXCP_INST_PAGE_FAULT         0xc /* since: priv-1.10.0 */
-#define RISCV_EXCP_LOAD_PAGE_FAULT         0xd /* since: priv-1.10.0 */
-#define RISCV_EXCP_STORE_PAGE_FAULT        0xf /* since: priv-1.10.0 */
+#define EXCP_NONE                                -1 /* sentinel value */
+#define RISCV_EXCP_INST_ADDR_MIS                 0x0
+#define RISCV_EXCP_INST_ACCESS_FAULT             0x1
+#define RISCV_EXCP_ILLEGAL_INST                  0x2
+#define RISCV_EXCP_BREAKPOINT                    0x3
+#define RISCV_EXCP_LOAD_ADDR_MIS                 0x4
+#define RISCV_EXCP_LOAD_ACCESS_FAULT             0x5
+#define RISCV_EXCP_STORE_AMO_ADDR_MIS            0x6
+#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT        0x7
+#define RISCV_EXCP_U_ECALL                       0x8
+#define RISCV_EXCP_S_ECALL                      0x9
+#define RISCV_EXCP_VS_ECALL                      0xa
+#define RISCV_EXCP_M_ECALL                       0xb
+#define RISCV_EXCP_INST_PAGE_FAULT               0xc /* since: priv-1.10.0 */
+#define RISCV_EXCP_LOAD_PAGE_FAULT               0xd /* since: priv-1.10.0 */
+#define RISCV_EXCP_STORE_PAGE_FAULT              0xf /* since: priv-1.10.0 */
+#define RISCV_EXCP_INST_GUEST_PAGE_FAULT         0x14
+#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT       0x15
+#define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT  0x17
 
 #define RISCV_EXCP_INT_FLAG                0x80000000
 #define RISCV_EXCP_INT_MASK                0x7fffffff
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 0de3a468eb..c201919c54 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -526,7 +526,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     static const int ecall_cause_map[] = {
         [PRV_U] = RISCV_EXCP_U_ECALL,
         [PRV_S] = RISCV_EXCP_S_ECALL,
-        [PRV_H] = RISCV_EXCP_H_ECALL,
+        [PRV_H] = RISCV_EXCP_VS_ECALL,
         [PRV_M] = RISCV_EXCP_M_ECALL
     };
 
@@ -542,6 +542,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         case RISCV_EXCP_INST_PAGE_FAULT:
         case RISCV_EXCP_LOAD_PAGE_FAULT:
         case RISCV_EXCP_STORE_PAGE_FAULT:
+        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
+        case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
+        case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
             tval = env->badaddr;
             break;
         default:
@@ -554,7 +557,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         }
     }
 
-    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 16 ?
+    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 23 ?
         (async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)");
 
     if (env->priv <= PRV_S &&
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index da02f9f0b1..6a0a59edfd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -242,11 +242,14 @@ static const target_ulong delegable_excps =
     (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) |
     (1ULL << (RISCV_EXCP_U_ECALL)) |
     (1ULL << (RISCV_EXCP_S_ECALL)) |
-    (1ULL << (RISCV_EXCP_H_ECALL)) |
+    (1ULL << (RISCV_EXCP_VS_ECALL)) |
     (1ULL << (RISCV_EXCP_M_ECALL)) |
     (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) |
     (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) |
-    (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT));
+    (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) |
+    (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
+    (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
+    (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT));
 static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE |
     SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
     SSTATUS_SUM | SSTATUS_SD;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (4 preceding siblings ...)
  2019-12-09 18:10 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:10 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Alistair Francis
                   ` (53 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c      |  6 +++---
 target/riscv/cpu_bits.h | 12 ++++++------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d23d2cba64..e8ae07107e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -80,14 +80,14 @@ const char * const riscv_excp_names[] = {
 const char * const riscv_intr_names[] = {
     "u_software",
     "s_software",
-    "h_software",
+    "vs_software",
     "m_software",
     "u_timer",
     "s_timer",
-    "h_timer",
+    "vs_timer",
     "m_timer",
     "u_external",
-    "s_external",
+    "vs_external",
     "h_external",
     "m_external",
     "reserved",
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 9ce73c36de..eeaa03c0f8 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -514,29 +514,29 @@
 /* Interrupt causes */
 #define IRQ_U_SOFT                         0
 #define IRQ_S_SOFT                         1
-#define IRQ_H_SOFT                         2  /* reserved */
+#define IRQ_VS_SOFT                        2
 #define IRQ_M_SOFT                         3
 #define IRQ_U_TIMER                        4
 #define IRQ_S_TIMER                        5
-#define IRQ_H_TIMER                        6  /* reserved */
+#define IRQ_VS_TIMER                       6
 #define IRQ_M_TIMER                        7
 #define IRQ_U_EXT                          8
 #define IRQ_S_EXT                          9
-#define IRQ_H_EXT                          10 /* reserved */
+#define IRQ_VS_EXT                         10
 #define IRQ_M_EXT                          11
 
 /* mip masks */
 #define MIP_USIP                           (1 << IRQ_U_SOFT)
 #define MIP_SSIP                           (1 << IRQ_S_SOFT)
-#define MIP_HSIP                           (1 << IRQ_H_SOFT)
+#define MIP_VSSIP                          (1 << IRQ_VS_SOFT)
 #define MIP_MSIP                           (1 << IRQ_M_SOFT)
 #define MIP_UTIP                           (1 << IRQ_U_TIMER)
 #define MIP_STIP                           (1 << IRQ_S_TIMER)
-#define MIP_HTIP                           (1 << IRQ_H_TIMER)
+#define MIP_VSTIP                          (1 << IRQ_VS_TIMER)
 #define MIP_MTIP                           (1 << IRQ_M_TIMER)
 #define MIP_UEIP                           (1 << IRQ_U_EXT)
 #define MIP_SEIP                           (1 << IRQ_S_EXT)
-#define MIP_HEIP                           (1 << IRQ_H_EXT)
+#define MIP_VSEIP                          (1 << IRQ_VS_EXT)
 #define MIP_MEIP                           (1 << IRQ_M_EXT)
 
 /* sip masks */
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 07/36] target/riscv: Add the virtulisation mode
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (5 preceding siblings ...)
  2019-12-09 18:10 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Alistair Francis
@ 2019-12-09 18:10 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 08/36] target/riscv: Add the force HS exception mode Alistair Francis
                   ` (52 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:10 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h        |  4 ++++
 target/riscv/cpu_bits.h   |  3 +++
 target/riscv/cpu_helper.c | 18 ++++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index bab938103d..a73292cd20 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -117,6 +117,8 @@ struct CPURISCVState {
 
 #ifndef CONFIG_USER_ONLY
     target_ulong priv;
+    /* This contains QEMU specific information about the virt state. */
+    target_ulong virt;
     target_ulong resetvec;
 
     target_ulong mhartid;
@@ -269,6 +271,8 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
 bool riscv_cpu_fp_enabled(CPURISCVState *env);
+bool riscv_cpu_virt_enabled(CPURISCVState *env);
+void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index eeaa03c0f8..2cdb0de4fe 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -430,6 +430,9 @@
 #define PRV_H 2 /* Reserved */
 #define PRV_M 3
 
+/* Virtulisation Register Fields */
+#define VIRT_ONOFF          1
+
 /* RV32 satp CSR field masks */
 #define SATP32_MODE         0x80000000
 #define SATP32_ASID         0x7fc00000
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c201919c54..046f3549cc 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -82,6 +82,24 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
     return false;
 }
 
+bool riscv_cpu_virt_enabled(CPURISCVState *env)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return false;
+    }
+
+    return get_field(env->virt, VIRT_ONOFF);
+}
+
+void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return;
+    }
+
+    env->virt = set_field(env->virt, VIRT_ONOFF, enable);
+}
+
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
 {
     CPURISCVState *env = &cpu->env;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 08/36] target/riscv: Add the force HS exception mode
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (6 preceding siblings ...)
  2019-12-09 18:10 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Alistair Francis
                   ` (51 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Add a FORCE_HS_EXCEP mode to the RISC-V virtulisation status. This bit
specifies if an exeption should be taken to HS mode no matter the
current delegation status. This is used when an exeption must be taken
to HS mode, such as when handling interrupts.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h        |  2 ++
 target/riscv/cpu_bits.h   |  6 ++++++
 target/riscv/cpu_helper.c | 18 ++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a73292cd20..21ae5a8b19 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -273,6 +273,8 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
 bool riscv_cpu_fp_enabled(CPURISCVState *env);
 bool riscv_cpu_virt_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
+bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
+void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 2cdb0de4fe..ad6479796c 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -432,6 +432,12 @@
 
 /* Virtulisation Register Fields */
 #define VIRT_ONOFF          1
+/* This is used to save state for when we take an exception. If this is set
+ * that means that we want to force a HS level exception (no matter what the
+ * delegation is set to). This will occur for things such as a second level
+ * page table fault.
+ */
+#define FORCE_HS_EXCEP      2
 
 /* RV32 satp CSR field masks */
 #define SATP32_MODE         0x80000000
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 046f3549cc..b00f66824a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -100,6 +100,24 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
     env->virt = set_field(env->virt, VIRT_ONOFF, enable);
 }
 
+bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return false;
+    }
+
+    return get_field(env->virt, FORCE_HS_EXCEP);
+}
+
+void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return;
+    }
+
+    env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable);
+}
+
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
 {
     CPURISCVState *env = &cpu->env;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (7 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 08/36] target/riscv: Add the force HS exception mode Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 10/36] target/riscv: Print priv and virt in disas log Alistair Francis
                   ` (50 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Update the CSR permission checking to work correctly when we are in
HS-mode.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6a0a59edfd..eebfc1823d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -802,12 +802,22 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
 
     /* check privileges and return -1 if check fails */
 #if !defined(CONFIG_USER_ONLY)
-    int csr_priv = get_field(csrno, 0x300);
+    int effective_priv = env->priv;
     int read_only = get_field(csrno, 0xC00) == 3;
-    if ((!env->debugger) && (env->priv < csr_priv)) {
-        return -1;
+
+    if (riscv_has_ext(env, RVH) &&
+        env->priv == PRV_S &&
+        !riscv_cpu_virt_enabled(env)) {
+        /*
+         * We are in S mode without virtualisation, therefore we are in HS Mode.
+         * Add 1 to the effective privledge level to allow us to access the
+         * Hypervisor CSRs.
+         */
+        effective_priv++;
     }
-    if (write_mask && read_only) {
+
+    if ((write_mask && read_only) ||
+        (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) {
         return -1;
     }
 #endif
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 10/36] target/riscv: Print priv and virt in disas log
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (8 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 11/36] target/riscv: Dump Hypervisor registers if enabled Alistair Francis
                   ` (49 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/translate.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ab6a891dc3..1a379bd2ae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -808,7 +808,15 @@ static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
 
 static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
 {
+#ifndef CONFIG_USER_ONLY
+    RISCVCPU *rvcpu = RISCV_CPU(cpu);
+    CPURISCVState *env = &rvcpu->env;
+#endif
+
     qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+#ifndef CONFIG_USER_ONLY
+    qemu_log("Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n", env->priv, env->virt);
+#endif
     log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
 }
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 11/36] target/riscv: Dump Hypervisor registers if enabled
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (9 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 10/36] target/riscv: Print priv and virt in disas log Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Alistair Francis
                   ` (48 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Dump the Hypervisor registers and the current Hypervisor state.

While we are editing this code let's also dump stvec and scause.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e8ae07107e..a07c5689b3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -228,17 +228,50 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
     CPURISCVState *env = &cpu->env;
     int i;
 
+#if !defined(CONFIG_USER_ONLY)
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s %d\n", "V      =  ", riscv_cpu_virt_enabled(env));
+    }
+#endif
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
 #ifndef CONFIG_USER_ONLY
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
+    }
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ", env->mip);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
+    }
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
+    }
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec   ", env->stvec);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec  ", env->vstvec);
+    }
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc    ", env->mepc);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc    ", env->sepc);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc   ", env->vsepc);
+    }
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause  ", env->scause);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
+    }
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->sbadaddr);
+    if (riscv_has_ext(env, RVH)) {
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
+        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
+    }
 #endif
 
     for (i = 0; i < 32; i++) {
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (10 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 11/36] target/riscv: Dump Hypervisor registers if enabled Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 13/36] target/riscv: Add Hypervisor virtual CSRs accesses Alistair Francis
                   ` (47 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 134 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index eebfc1823d..b582d78529 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -98,6 +98,20 @@ static int smode(CPURISCVState *env, int csrno)
     return -!riscv_has_ext(env, RVS);
 }
 
+static int hmode(CPURISCVState *env, int csrno)
+{
+    if (riscv_has_ext(env, RVS) &&
+        riscv_has_ext(env, RVH)) {
+        /* Hypervisor extension is supported */
+        if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
+            env->priv == PRV_M) {
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
 static int pmp(CPURISCVState *env, int csrno)
 {
     return -!riscv_feature(env, RISCV_FEATURE_PMP);
@@ -226,8 +240,9 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
 
 /* Machine constants */
 
-#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
-#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
+#define M_MODE_INTERRUPTS  (MIP_MSIP | MIP_MTIP | MIP_MEIP)
+#define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
+#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
 
 static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
 static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
@@ -257,6 +272,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
     SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
     SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
+static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
 
 #if defined(TARGET_RISCV32)
 static const char valid_vm_1_09[16] = {
@@ -757,6 +773,112 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
+/* Hypervisor Extensions */
+static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->hstatus;
+    return 0;
+}
+
+static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->hstatus = val;
+    return 0;
+}
+
+static int read_hedeleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->hedeleg;
+    return 0;
+}
+
+static int write_hedeleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->hedeleg = val;
+    return 0;
+}
+
+static int read_hideleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->hideleg;
+    return 0;
+}
+
+static int write_hideleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->hideleg = val;
+    return 0;
+}
+
+static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value,
+                   target_ulong new_value, target_ulong write_mask)
+{
+    int ret = rmw_mip(env, 0, ret_value, new_value,
+                      write_mask & hip_writable_mask);
+
+    return ret;
+}
+
+static int read_hie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mie & VS_MODE_INTERRUPTS;
+    return 0;
+}
+
+static int write_hie(CPURISCVState *env, int csrno, target_ulong val)
+{
+    target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & VS_MODE_INTERRUPTS);
+    return write_mie(env, CSR_MIE, newval);
+}
+
+static int read_hcounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->hcounteren;
+    return 0;
+}
+
+static int write_hcounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->hcounteren = val;
+    return 0;
+}
+
+static int read_htval(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->htval;
+    return 0;
+}
+
+static int write_htval(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->htval = val;
+    return 0;
+}
+
+static int read_htinst(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->htinst;
+    return 0;
+}
+
+static int write_htinst(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->htinst = val;
+    return 0;
+}
+
+static int read_hgatp(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->hgatp;
+    return 0;
+}
+
+static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->hgatp = val;
+    return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -960,6 +1082,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
     /* Supervisor Protection and Translation */
     [CSR_SATP] =                { smode, read_satp,        write_satp        },
 
+    [CSR_HSTATUS] =             { hmode,   read_hstatus,     write_hstatus    },
+    [CSR_HEDELEG] =             { hmode,   read_hedeleg,     write_hedeleg    },
+    [CSR_HIDELEG] =             { hmode,   read_hideleg,     write_hideleg    },
+    [CSR_HIP] =                 { hmode,   NULL,     NULL,     rmw_hip        },
+    [CSR_HIE] =                 { hmode,   read_hie,         write_hie        },
+    [CSR_HCOUNTEREN] =          { hmode,   read_hcounteren,  write_hcounteren },
+    [CSR_HTVAL] =               { hmode,   read_htval,       write_htval      },
+    [CSR_HTINST] =              { hmode,   read_htinst,      write_htinst     },
+    [CSR_HGATP] =               { hmode,   read_hgatp,       write_hgatp      },
+
     /* Physical Memory Protection */
     [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
     [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 13/36] target/riscv: Add Hypervisor virtual CSRs accesses
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (11 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 14/36] " Alistair Francis
                   ` (46 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/csr.c | 116 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 116 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b582d78529..aaca1a6a0f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -273,6 +273,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
     SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
+static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
 #if defined(TARGET_RISCV32)
 static const char valid_vm_1_09[16] = {
@@ -879,6 +880,111 @@ static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
+/* Virtual CSR Registers */
+static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vsstatus;
+    return 0;
+}
+
+static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vsstatus = val;
+    return 0;
+}
+
+static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
+                    target_ulong new_value, target_ulong write_mask)
+{
+    int ret = rmw_mip(env, 0, ret_value, new_value,
+                      write_mask & env->mideleg & vsip_writable_mask);
+    return ret;
+}
+
+static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mie & env->mideleg & VS_MODE_INTERRUPTS;
+    return 0;
+}
+
+static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
+{
+    target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg & MIP_VSSIP);
+    return write_mie(env, CSR_MIE, newval);
+}
+
+static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vstvec;
+    return 0;
+}
+
+static int write_vstvec(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vstvec = val;
+    return 0;
+}
+
+static int read_vsscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vsscratch;
+    return 0;
+}
+
+static int write_vsscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vsscratch = val;
+    return 0;
+}
+
+static int read_vsepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vsepc;
+    return 0;
+}
+
+static int write_vsepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vsepc = val;
+    return 0;
+}
+
+static int read_vscause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vscause;
+    return 0;
+}
+
+static int write_vscause(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vscause = val;
+    return 0;
+}
+
+static int read_vstval(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vstval;
+    return 0;
+}
+
+static int write_vstval(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vstval = val;
+    return 0;
+}
+
+static int read_vsatp(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->vsatp;
+    return 0;
+}
+
+static int write_vsatp(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->vsatp = val;
+    return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -1092,6 +1198,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
     [CSR_HTINST] =              { hmode,   read_htinst,      write_htinst     },
     [CSR_HGATP] =               { hmode,   read_hgatp,       write_hgatp      },
 
+    [CSR_VSSTATUS] =            { hmode,   read_vsstatus,    write_vsstatus   },
+    [CSR_VSIP] =                { hmode,   NULL,     NULL,     rmw_vsip       },
+    [CSR_VSIE] =                { hmode,   read_vsie,        write_vsie       },
+    [CSR_VSTVEC] =              { hmode,   read_vstvec,      write_vstvec     },
+    [CSR_VSSCRATCH] =           { hmode,   read_vsscratch,   write_vsscratch  },
+    [CSR_VSEPC] =               { hmode,   read_vsepc,       write_vsepc      },
+    [CSR_VSCAUSE] =             { hmode,   read_vscause,     write_vscause    },
+    [CSR_VSTVAL] =              { hmode,   read_vstval,      write_vstval     },
+    [CSR_VSATP] =               { hmode,   read_vsatp,       write_vsatp      },
+
     /* Physical Memory Protection */
     [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
     [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 14/36] target/riscv: Add Hypervisor virtual CSRs accesses
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (12 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 13/36] target/riscv: Add Hypervisor virtual CSRs accesses Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Alistair Francis
                   ` (45 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index aaca1a6a0f..74e911af08 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -985,6 +985,30 @@ static int write_vsatp(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
+static int read_mtval2(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mtval2;
+    return 0;
+}
+
+static int write_mtval2(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mtval2 = val;
+    return 0;
+}
+
+static int read_mtinst(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mtinst;
+    return 0;
+}
+
+static int write_mtinst(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mtinst = val;
+    return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -1208,6 +1232,9 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
     [CSR_VSTVAL] =              { hmode,   read_vstval,      write_vstval     },
     [CSR_VSATP] =               { hmode,   read_vsatp,       write_vsatp      },
 
+    [CSR_MTVAL2] =              { hmode,   read_mtval2,      write_mtval2     },
+    [CSR_MTINST] =              { hmode,   read_mtinst,      write_mtinst     },
+
     /* Physical Memory Protection */
     [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
     [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (13 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 14/36] " Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Alistair Francis
                   ` (44 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

To handle the new Hypervisor CSR register aliasing let's use pointers.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c        | 11 +++++++++--
 target/riscv/cpu.h        |  9 ++++++++-
 target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
 target/riscv/csr.c        | 20 ++++++++++----------
 target/riscv/op_helper.c  | 14 +++++++-------
 5 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a07c5689b3..e61cf46a73 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
 #ifndef CONFIG_USER_ONLY
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
-    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
     if (riscv_has_ext(env, RVH)) {
         qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
         qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
@@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
     mcc->parent_reset(cs);
 #ifndef CONFIG_USER_ONLY
     env->priv = PRV_M;
-    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
+    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
     env->mcause = 0;
     env->pc = env->resetvec;
 #endif
@@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 static void riscv_cpu_init(Object *obj)
 {
     RISCVCPU *cpu = RISCV_CPU(obj);
+#ifndef CONFIG_USER_ONLY
+    CPURISCVState *env = &cpu->env;
+#endif
 
     cpu_set_cpustate_pointers(cpu);
+
+#ifndef CONFIG_USER_ONLY
+    env->mstatus = &env->mstatus_novirt;
+#endif
 }
 
 static const VMStateDescription vmstate_riscv_cpu = {
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 21ae5a8b19..9dc8303c62 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -122,7 +122,7 @@ struct CPURISCVState {
     target_ulong resetvec;
 
     target_ulong mhartid;
-    target_ulong mstatus;
+    target_ulong *mstatus;
 
     target_ulong mip;
     uint32_t miclaim;
@@ -145,6 +145,13 @@ struct CPURISCVState {
     target_ulong mcause;
     target_ulong mtval;  /* since: priv-1.10.0 */
 
+    /* The following registers are the "real" versions that the pointer
+     * versions point to. These should never be used unless you know what you
+     * are doing. To access these use the pointer versions instead. This is
+     * required to handle the Hypervisor register swapping.
+     */
+    target_ulong mstatus_novirt;
+
     /* Hypervisor CSRs */
     target_ulong hstatus;
     target_ulong hedeleg;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b00f66824a..9684da7f7d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
-    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
-    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
+    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
+    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
     target_ulong pending = env->mip & env->mie;
     target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
     target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
@@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 /* Return true is floating point support is currently enabled */
 bool riscv_cpu_fp_enabled(CPURISCVState *env)
 {
-    if (env->mstatus & MSTATUS_FS) {
+    if (*env->mstatus & MSTATUS_FS) {
         return true;
     }
 
@@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     int mode = mmu_idx;
 
     if (mode == PRV_M && access_type != MMU_INST_FETCH) {
-        if (get_field(env->mstatus, MSTATUS_MPRV)) {
-            mode = get_field(env->mstatus, MSTATUS_MPP);
+        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
+            mode = get_field(*env->mstatus, MSTATUS_MPP);
         }
     }
 
@@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 
     hwaddr base;
     int levels, ptidxbits, ptesize, vm, sum;
-    int mxr = get_field(env->mstatus, MSTATUS_MXR);
+    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
 
     if (env->priv_ver >= PRIV_VERSION_1_10_0) {
         base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
-        sum = get_field(env->mstatus, MSTATUS_SUM);
+        sum = get_field(*env->mstatus, MSTATUS_SUM);
         vm = get_field(env->satp, SATP_MODE);
         switch (vm) {
         case VM_1_10_SV32:
@@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         }
     } else {
         base = (hwaddr)(env->sptbr) << PGSHIFT;
-        sum = !get_field(env->mstatus, MSTATUS_PUM);
-        vm = get_field(env->mstatus, MSTATUS_VM);
+        sum = !get_field(*env->mstatus, MSTATUS_PUM);
+        vm = get_field(*env->mstatus, MSTATUS_VM);
         switch (vm) {
         case VM_1_09_SV32:
           levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
 
     if (mode == PRV_M && access_type != MMU_INST_FETCH) {
-        if (get_field(env->mstatus, MSTATUS_MPRV)) {
-            mode = get_field(env->mstatus, MSTATUS_MPP);
+        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
+            mode = get_field(*env->mstatus, MSTATUS_MPP);
         }
     }
 
@@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     if (env->priv <= PRV_S &&
             cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
         /* handle the trap in S-mode */
-        target_ulong s = env->mstatus;
+        target_ulong s = *env->mstatus;
         s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
             get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
         s = set_field(s, MSTATUS_SPP, env->priv);
         s = set_field(s, MSTATUS_SIE, 0);
-        env->mstatus = s;
+        *env->mstatus = s;
         env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
         env->sepc = env->pc;
         env->sbadaddr = tval;
@@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         riscv_cpu_set_mode(env, PRV_S);
     } else {
         /* handle the trap in M-mode */
-        target_ulong s = env->mstatus;
+        target_ulong s = *env->mstatus;
         s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
             get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
         s = set_field(s, MSTATUS_MPP, env->priv);
         s = set_field(s, MSTATUS_MIE, 0);
-        env->mstatus = s;
+        *env->mstatus = s;
         env->mcause = cause | ~(((target_ulong)-1) >> async);
         env->mepc = env->pc;
         env->mbadaddr = tval;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 74e911af08..a4b598d49a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
     if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
         return -1;
     }
-    env->mstatus |= MSTATUS_FS;
+    *env->mstatus |= MSTATUS_FS;
 #endif
     riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
     return 0;
@@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
     if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
         return -1;
     }
-    env->mstatus |= MSTATUS_FS;
+    *env->mstatus |= MSTATUS_FS;
 #endif
     env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
     return 0;
@@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
     if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
         return -1;
     }
-    env->mstatus |= MSTATUS_FS;
+    *env->mstatus |= MSTATUS_FS;
 #endif
     env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
     riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
@@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
 /* Machine Trap Setup */
 static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
 {
-    *val = env->mstatus;
+    *val = *env->mstatus;
     return 0;
 }
 
@@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
 
 static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
 {
-    target_ulong mstatus = env->mstatus;
+    target_ulong mstatus = *env->mstatus;
     target_ulong mask = 0;
     int dirty;
 
@@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
              ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
             ((mstatus & MSTATUS_XS) == MSTATUS_XS);
     mstatus = set_field(mstatus, MSTATUS_SD, dirty);
-    env->mstatus = mstatus;
+    *env->mstatus = mstatus;
 
     return 0;
 }
@@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
 {
     target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
                          sstatus_v1_10_mask : sstatus_v1_9_mask);
-    *val = env->mstatus & mask;
+    *val = *env->mstatus & mask;
     return 0;
 }
 
@@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
 {
     target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
                          sstatus_v1_10_mask : sstatus_v1_9_mask);
-    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
+    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
     return write_mstatus(env, CSR_MSTATUS, newval);
 }
 
@@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
     if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
         *val = 0;
     } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
             return -1;
         } else {
             *val = env->satp;
@@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
         validate_vm(env, get_field(val, SATP_MODE)) &&
         ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
     {
-        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
             return -1;
         } else {
             if((val ^ env->satp) & SATP_ASID) {
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 331cc36232..d150551bc9 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
     }
 
     if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
-        get_field(env->mstatus, MSTATUS_TSR)) {
+        get_field(*env->mstatus, MSTATUS_TSR)) {
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
-    target_ulong mstatus = env->mstatus;
+    target_ulong mstatus = *env->mstatus;
     target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
     mstatus = set_field(mstatus,
         env->priv_ver >= PRIV_VERSION_1_10_0 ?
@@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
     mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
     mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
     riscv_cpu_set_mode(env, prev_priv);
-    env->mstatus = mstatus;
+    *env->mstatus = mstatus;
 
     return retpc;
 }
@@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
         riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
     }
 
-    target_ulong mstatus = env->mstatus;
+    target_ulong mstatus = *env->mstatus;
     target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
     mstatus = set_field(mstatus,
         env->priv_ver >= PRIV_VERSION_1_10_0 ?
@@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
     mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
     mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
     riscv_cpu_set_mode(env, prev_priv);
-    env->mstatus = mstatus;
+    *env->mstatus = mstatus;
 
     return retpc;
 }
@@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
 
     if (env->priv == PRV_S &&
         env->priv_ver >= PRIV_VERSION_1_10_0 &&
-        get_field(env->mstatus, MSTATUS_TW)) {
+        get_field(*env->mstatus, MSTATUS_TW)) {
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     } else {
         cs->halted = 1;
@@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
     if (!(env->priv >= PRV_S) ||
         (env->priv == PRV_S &&
          env->priv_ver >= PRIV_VERSION_1_10_0 &&
-         get_field(env->mstatus, MSTATUS_TVM))) {
+         get_field(*env->mstatus, MSTATUS_TVM))) {
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     } else {
         tlb_flush(cs);
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 16/36] target/riscv: Add virtual register swapping function
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (14 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Alistair Francis
                   ` (43 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h        | 10 +++++++
 target/riscv/cpu_bits.h   |  7 +++++
 target/riscv/cpu_helper.c | 63 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9dc8303c62..eb089fbdb6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -125,6 +125,7 @@ struct CPURISCVState {
     target_ulong *mstatus;
 
     target_ulong mip;
+
     uint32_t miclaim;
 
     target_ulong mie;
@@ -173,6 +174,14 @@ struct CPURISCVState {
     target_ulong mtval2;
     target_ulong mtinst;
 
+    /* HS Backup CSRs */
+    target_ulong stvec_hs;
+    target_ulong sscratch_hs;
+    target_ulong sepc_hs;
+    target_ulong scause_hs;
+    target_ulong stval_hs;
+    target_ulong satp_hs;
+
     target_ulong scounteren;
     target_ulong mcounteren;
 
@@ -303,6 +312,7 @@ void riscv_cpu_list(void);
 #define cpu_mmu_index riscv_cpu_mmu_index
 
 #ifndef CONFIG_USER_ONLY
+void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index ad6479796c..a24654d137 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -553,4 +553,11 @@
 #define SIP_STIP                           MIP_STIP
 #define SIP_SEIP                           MIP_SEIP
 
+/* MIE masks */
+#define MIE_SEIE                           (1 << IRQ_S_EXT)
+#define MIE_UEIE                           (1 << IRQ_U_EXT)
+#define MIE_STIE                           (1 << IRQ_S_TIMER)
+#define MIE_UTIE                           (1 << IRQ_U_TIMER)
+#define MIE_SSIE                           (1 << IRQ_S_SOFT)
+#define MIE_USIE                           (1 << IRQ_U_SOFT)
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9684da7f7d..63439c9370 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -82,6 +82,69 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
     return false;
 }
 
+void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
+{
+    target_ulong mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
+                                MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE;
+    bool current_virt = riscv_cpu_virt_enabled(env);
+
+    g_assert(riscv_has_ext(env, RVH));
+
+#if defined(TARGET_RISCV64)
+    mstatus_mask |= MSTATUS64_UXL;
+#endif
+
+    if (current_virt) {
+        /* Current V=1 and we are about to change to V=0 */
+        env->mstatus = &env->mstatus_novirt;
+        *env->mstatus &= mstatus_mask;
+        *env->mstatus |= env->vsstatus & ~mstatus_mask;
+        /* Ensure that vsstatus only holds the correct bits */
+        env->vsstatus &= mstatus_mask;
+
+        env->vstvec = env->stvec;
+        env->stvec = env->stvec_hs;
+
+        env->vsscratch = env->sscratch;
+        env->sscratch = env->sscratch_hs;
+
+        env->vsepc = env->sepc;
+        env->sepc = env->sepc_hs;
+
+        env->vscause = env->scause;
+        env->scause = env->scause_hs;
+
+        env->vstval = env->sbadaddr;
+        env->sbadaddr = env->stval_hs;
+
+        env->vsatp = env->satp;
+        env->satp = env->satp_hs;
+    } else {
+        /* Current V=0 and we are about to change to V=1 */
+        env->mstatus = &env->vsstatus;
+        *env->mstatus &= mstatus_mask;
+        *env->mstatus |= env->mstatus_novirt & ~mstatus_mask;
+
+        env->stvec_hs = env->stvec;
+        env->stvec = env->vstvec;
+
+        env->sscratch_hs = env->sscratch;
+        env->sscratch = env->vsscratch;
+
+        env->sepc_hs = env->sepc;
+        env->sepc = env->vsepc;
+
+        env->scause_hs = env->scause;
+        env->scause = env->vscause;
+
+        env->stval_hs = env->sbadaddr;
+        env->sbadaddr = env->vstval;
+
+        env->satp_hs = env->satp;
+        env->satp = env->vsatp;
+    }
+}
+
 bool riscv_cpu_virt_enabled(CPURISCVState *env)
 {
     if (!riscv_has_ext(env, RVH)) {
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (15 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Alistair Francis
                   ` (42 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index a4b598d49a..fc38c45a7e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -449,6 +449,9 @@ static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
 static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
 {
     env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
+    if (riscv_has_ext(env, RVH)) {
+        env->mideleg |= VS_MODE_INTERRUPTS;
+    }
     return 0;
 }
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (16 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Alistair Francis
                   ` (41 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index fc38c45a7e..54edfb280e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -244,8 +244,10 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
 #define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
 #define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
 
-static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
-static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
+static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
+                                           VS_MODE_INTERRUPTS;
+static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
+                                     VS_MODE_INTERRUPTS;
 static const target_ulong delegable_excps =
     (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) |
     (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) |
@@ -631,13 +633,27 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
 
 static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
 {
-    *val = env->mie & env->mideleg;
+    if (riscv_cpu_virt_enabled(env)) {
+        /* Tell the guest the VS bits, shifted to the S bit locations */
+        *val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
+    } else {
+        *val = env->mie & env->mideleg;
+    }
     return 0;
 }
 
 static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
 {
-    target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg);
+    target_ulong newval;
+
+    if (riscv_cpu_virt_enabled(env)) {
+        /* Shift the guests S bits to VS */
+        newval = (env->mie & ~VS_MODE_INTERRUPTS) |
+                 ((val << 1) & VS_MODE_INTERRUPTS);
+    } else {
+        newval = (env->mie & ~S_MODE_INTERRUPTS) | (val & S_MODE_INTERRUPTS);
+    }
+
     return write_mie(env, CSR_MIE, newval);
 }
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 19/36] target/riscv: Extend the SIP CSR to support virtulisation
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (17 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Alistair Francis
                   ` (40 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 54edfb280e..d028dfb60b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -744,8 +744,19 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
 static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
                    target_ulong new_value, target_ulong write_mask)
 {
-    int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
+    int ret;
+
+    if (riscv_cpu_virt_enabled(env)) {
+        /* Shift the new values to line up with the VS bits */
+        ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
+                      (write_mask & sip_writable_mask) << 1 & env->mideleg);
+        ret &= vsip_writable_mask;
+        ret >>= 1;
+    } else {
+        ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
                       write_mask & env->mideleg & sip_writable_mask);
+    }
+
     *ret_value &= env->mideleg;
     return ret;
 }
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (18 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 21/36] target/ricsv: Flush the TLB on virtulisation mode changes Alistair Francis
                   ` (39 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_helper.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 63439c9370..85eed5d885 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -37,13 +37,36 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
+    target_ulong irqs;
+
     target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
     target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
-    target_ulong pending = env->mip & env->mie;
-    target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
-    target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
-    target_ulong irqs = (pending & ~env->mideleg & -mie) |
-                        (pending &  env->mideleg & -sie);
+    target_ulong hs_mstatus_sie = get_field(env->mstatus_novirt, MSTATUS_SIE);
+
+    target_ulong pending = env->mip & env->mie &
+                               ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
+    target_ulong vspending = (env->mip & env->mie &
+                              (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) >> 1;
+
+    target_ulong mie    = env->priv < PRV_M ||
+                          (env->priv == PRV_M && mstatus_mie);
+    target_ulong sie    = env->priv < PRV_S ||
+                          (env->priv == PRV_S && mstatus_sie);
+    target_ulong hs_sie = env->priv < PRV_S ||
+                          (env->priv == PRV_S && hs_mstatus_sie);
+
+    if (riscv_cpu_virt_enabled(env)) {
+        target_ulong pending_hs_irq = pending & -hs_sie;
+
+        if (pending_hs_irq) {
+            riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
+            return ctz64(pending_hs_irq);
+        }
+
+        pending = vspending;
+    }
+
+    irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);
 
     if (irqs) {
         return ctz64(irqs); /* since non-zero */
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 21/36] target/ricsv: Flush the TLB on virtulisation mode changes
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (19 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 22/36] target/riscv: Generate illegal instruction on WFI when V=1 Alistair Francis
                   ` (38 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

To ensure our TLB isn't out-of-date we flush it on all virt mode
changes. Unlike priv mode this isn't saved in the mmu_idx as all
guests share V=1. The easiest option is just to flush on all changes.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu_helper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 85eed5d885..1b747abf93 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -183,6 +183,11 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
         return;
     }
 
+    /* Flush the TLB on all virt mode changes. */
+    if (get_field(env->virt, VIRT_ONOFF) != enable) {
+        tlb_flush(env_cpu(env));
+    }
+
     env->virt = set_field(env->virt, VIRT_ONOFF, enable);
 }
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 22/36] target/riscv: Generate illegal instruction on WFI when V=1
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (20 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 21/36] target/ricsv: Flush the TLB on virtulisation mode changes Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 23/36] target/riscv: Add hypvervisor trap support Alistair Francis
                   ` (37 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/op_helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index d150551bc9..beb34e705b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -130,9 +130,10 @@ void helper_wfi(CPURISCVState *env)
 {
     CPUState *cs = env_cpu(env);
 
-    if (env->priv == PRV_S &&
+    if ((env->priv == PRV_S &&
         env->priv_ver >= PRIV_VERSION_1_10_0 &&
-        get_field(*env->mstatus, MSTATUS_TW)) {
+        get_field(*env->mstatus, MSTATUS_TW)) ||
+        riscv_cpu_virt_enabled(env)) {
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     } else {
         cs->halted = 1;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (21 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 22/36] target/riscv: Generate illegal instruction on WFI when V=1 Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2020-01-20  8:34   ` Jiangyifei
  2019-12-09 18:11 ` [PATCH v1 24/36] target/riscv: Add Hypervisor trap return support Alistair Francis
                   ` (36 subsequent siblings)
  59 siblings, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu_helper.c | 65 +++++++++++++++++++++++++++++++++------
 1 file changed, 55 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 1b747abf93..2c6d2bc3a3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -641,6 +641,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
+    target_ulong s;
 
     /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
      * so we mask off the MSB and separate into trap type and cause.
@@ -650,13 +651,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong deleg = async ? env->mideleg : env->medeleg;
     target_ulong tval = 0;
 
-    static const int ecall_cause_map[] = {
-        [PRV_U] = RISCV_EXCP_U_ECALL,
-        [PRV_S] = RISCV_EXCP_S_ECALL,
-        [PRV_H] = RISCV_EXCP_VS_ECALL,
-        [PRV_M] = RISCV_EXCP_M_ECALL
-    };
-
     if (!async) {
         /* set tval to badaddr for traps with address information */
         switch (cause) {
@@ -680,7 +674,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         /* ecall is dispatched as one cause so translate based on mode */
         if (cause == RISCV_EXCP_U_ECALL) {
             assert(env->priv <= 3);
-            cause = ecall_cause_map[env->priv];
+
+            if (env->priv == PRV_M) {
+                cause = RISCV_EXCP_M_ECALL;
+            } else if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
+                cause = RISCV_EXCP_VS_ECALL;
+            } else if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) {
+                cause = RISCV_EXCP_S_ECALL;
+            } else if (env->priv == PRV_U) {
+                cause = RISCV_EXCP_U_ECALL;
+            }
         }
     }
 
@@ -690,7 +693,36 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     if (env->priv <= PRV_S &&
             cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
         /* handle the trap in S-mode */
-        target_ulong s = *env->mstatus;
+        if (riscv_has_ext(env, RVH)) {
+            target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
+
+            if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
+                !riscv_cpu_force_hs_excep_enabled(env)) {
+                /* Trap to VS mode */
+            } else if (riscv_cpu_virt_enabled(env)) {
+                /* Trap into HS mode, from virt */
+                riscv_cpu_swap_hypervisor_regs(env);
+                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
+                                         get_field(env->hstatus, HSTATUS_SPV));
+                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
+                                         get_field(*env->mstatus, SSTATUS_SPP));
+                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
+                                         riscv_cpu_virt_enabled(env));
+
+                riscv_cpu_set_virt_enabled(env, 0);
+                riscv_cpu_set_force_hs_excep(env, 0);
+            } else {
+                /* Trap into HS mode */
+                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
+                                         get_field(env->hstatus, HSTATUS_SPV));
+                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
+                                         get_field(*env->mstatus, SSTATUS_SPP));
+                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
+                                         riscv_cpu_virt_enabled(env));
+            }
+        }
+
+        s = *env->mstatus;
         s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
             get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
         s = set_field(s, MSTATUS_SPP, env->priv);
@@ -704,7 +736,20 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         riscv_cpu_set_mode(env, PRV_S);
     } else {
         /* handle the trap in M-mode */
-        target_ulong s = *env->mstatus;
+        if (riscv_has_ext(env, RVH)) {
+            if (riscv_cpu_virt_enabled(env)) {
+                riscv_cpu_swap_hypervisor_regs(env);
+            }
+            *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
+                                      riscv_cpu_virt_enabled(env));
+            *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
+                                      riscv_cpu_force_hs_excep_enabled(env));
+
+            /* Trapping to M mode, virt is disabled */
+            riscv_cpu_set_virt_enabled(env, 0);
+        }
+
+        s = *env->mstatus;
         s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
             get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
         s = set_field(s, MSTATUS_MPP, env->priv);
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 24/36] target/riscv: Add Hypervisor trap return support
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (22 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 23/36] target/riscv: Add hypvervisor trap support Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 25/36] target/riscv: Add hfence instructions Alistair Francis
                   ` (35 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/op_helper.c | 66 ++++++++++++++++++++++++++++++++--------
 1 file changed, 54 insertions(+), 12 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index beb34e705b..e5128570e6 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -73,6 +73,8 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
 {
+    target_ulong prev_priv, prev_virt, mstatus;
+
     if (!(env->priv >= PRV_S)) {
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
@@ -87,16 +89,46 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
-    target_ulong mstatus = *env->mstatus;
-    target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
-    mstatus = set_field(mstatus,
-        env->priv_ver >= PRIV_VERSION_1_10_0 ?
-        MSTATUS_SIE : MSTATUS_UIE << prev_priv,
-        get_field(mstatus, MSTATUS_SPIE));
-    mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
-    mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
+    mstatus = *env->mstatus;
+
+    if (riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
+        /* We support Hypervisor extensions and virtulisation is disabled */
+        target_ulong hstatus = env->hstatus;
+
+        prev_priv = get_field(mstatus, MSTATUS_SPP);
+        prev_virt = get_field(hstatus, HSTATUS_SPV);
+
+        hstatus = set_field(hstatus, HSTATUS_SPV,
+                                 get_field(hstatus, HSTATUS_SP2V));
+        mstatus = set_field(mstatus, MSTATUS_SPP,
+                            get_field(hstatus, HSTATUS_SP2P));
+        hstatus = set_field(hstatus, HSTATUS_SP2V, 0);
+        hstatus = set_field(hstatus, HSTATUS_SP2P, 0);
+        mstatus = set_field(mstatus, SSTATUS_SIE,
+                            get_field(mstatus, SSTATUS_SPIE));
+        mstatus = set_field(mstatus, SSTATUS_SPIE, 1);
+
+        *env->mstatus = mstatus;
+        env->hstatus = hstatus;
+
+        if (prev_virt) {
+            riscv_cpu_swap_hypervisor_regs(env);
+        }
+
+        riscv_cpu_set_virt_enabled(env, prev_virt);
+    } else {
+        prev_priv = get_field(mstatus, MSTATUS_SPP);
+
+        mstatus = set_field(mstatus,
+            env->priv_ver >= PRIV_VERSION_1_10_0 ?
+            MSTATUS_SIE : MSTATUS_UIE << prev_priv,
+            get_field(mstatus, MSTATUS_SPIE));
+        mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
+        mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
+        *env->mstatus = mstatus;
+    }
+
     riscv_cpu_set_mode(env, prev_priv);
-    *env->mstatus = mstatus;
 
     return retpc;
 }
@@ -114,14 +146,24 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
 
     target_ulong mstatus = *env->mstatus;
     target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
+    target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
     mstatus = set_field(mstatus,
         env->priv_ver >= PRIV_VERSION_1_10_0 ?
         MSTATUS_MIE : MSTATUS_UIE << prev_priv,
         get_field(mstatus, MSTATUS_MPIE));
-    mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
-    mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
-    riscv_cpu_set_mode(env, prev_priv);
+    mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
+    mstatus = set_field(mstatus, MSTATUS_MPP, 0);
+    mstatus = set_field(mstatus, MSTATUS_MPV, 0);
     *env->mstatus = mstatus;
+    riscv_cpu_set_mode(env, prev_priv);
+
+    if (riscv_has_ext(env, RVH)) {
+        if (prev_virt) {
+            riscv_cpu_swap_hypervisor_regs(env);
+        }
+
+        riscv_cpu_set_virt_enabled(env, prev_virt);
+    }
 
     return retpc;
 }
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 25/36] target/riscv: Add hfence instructions
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (23 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 24/36] target/riscv: Add Hypervisor trap return support Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Alistair Francis
                   ` (34 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/insn32.decode                    | 23 ++++++-----
 .../riscv/insn_trans/trans_privileged.inc.c   | 40 +++++++++++++++++++
 2 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 77f794ed70..cfd9ca6d2b 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -63,20 +63,25 @@
 @r2_rm   .......   ..... ..... ... ..... ....... %rs1 %rm %rd
 @r2      .......   ..... ..... ... ..... ....... %rs1 %rd
 
+@hfence_gvma ....... ..... .....   ... ..... ....... %rs2 %rs1
+@hfence_bvma ....... ..... .....   ... ..... ....... %rs2 %rs1
+
 @sfence_vma ....... ..... .....   ... ..... ....... %rs2 %rs1
 @sfence_vm  ....... ..... .....   ... ..... ....... %rs1
 
 
 # *** Privileged Instructions ***
-ecall      000000000000     00000 000 00000 1110011
-ebreak     000000000001     00000 000 00000 1110011
-uret       0000000    00010 00000 000 00000 1110011
-sret       0001000    00010 00000 000 00000 1110011
-hret       0010000    00010 00000 000 00000 1110011
-mret       0011000    00010 00000 000 00000 1110011
-wfi        0001000    00101 00000 000 00000 1110011
-sfence_vma 0001001    ..... ..... 000 00000 1110011 @sfence_vma
-sfence_vm  0001000    00100 ..... 000 00000 1110011 @sfence_vm
+ecall       000000000000     00000 000 00000 1110011
+ebreak      000000000001     00000 000 00000 1110011
+uret        0000000    00010 00000 000 00000 1110011
+sret        0001000    00010 00000 000 00000 1110011
+hret        0010000    00010 00000 000 00000 1110011
+mret        0011000    00010 00000 000 00000 1110011
+wfi         0001000    00101 00000 000 00000 1110011
+hfence_gvma 0110001    ..... ..... 000 00000 1110011 @hfence_gvma
+hfence_bvma 0010001    ..... ..... 000 00000 1110011 @hfence_bvma
+sfence_vma  0001001    ..... ..... 000 00000 1110011 @sfence_vma
+sfence_vm   0001000    00100 ..... 000 00000 1110011 @sfence_vm
 
 # *** RV32I Base Instruction Set ***
 lui      ....................       ..... 0110111 @u
diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c
index c5e4b3e49a..b9b5a89b52 100644
--- a/target/riscv/insn_trans/trans_privileged.inc.c
+++ b/target/riscv/insn_trans/trans_privileged.inc.c
@@ -108,3 +108,43 @@ static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a)
 #endif
     return false;
 }
+
+static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
+{
+#ifndef CONFIG_USER_ONLY
+    if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
+        has_ext(ctx, RVH)) {
+        /* Hpervisor extensions exist */
+        /*
+         * if (env->priv == PRV_M ||
+         *   (env->priv == PRV_S &&
+         *    !riscv_cpu_virt_enabled(env) &&
+         *    get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
+         */
+            gen_helper_tlb_flush(cpu_env);
+            return true;
+        /* } */
+    }
+#endif
+    return false;
+}
+
+static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a)
+{
+#ifndef CONFIG_USER_ONLY
+    if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
+        has_ext(ctx, RVH)) {
+        /* Hpervisor extensions exist */
+        /*
+         * if (env->priv == PRV_M ||
+         *   (env->priv == PRV_S &&
+         *    !riscv_cpu_virt_enabled(env) &&
+         *    get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
+         */
+            gen_helper_tlb_flush(cpu_env);
+            return true;
+        /* } */
+    }
+#endif
+    return false;
+}
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 26/36] target/riscv: Remove the hret instruction
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (24 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 25/36] target/riscv: Add hfence instructions Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 27/36] target/riscv: Disable guest FP support based on virtual status Alistair Francis
                   ` (33 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

The hret instruction does not exist in the new spec versions, so remove
it from QEMU.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/insn32.decode                     | 1 -
 target/riscv/insn_trans/trans_privileged.inc.c | 5 -----
 2 files changed, 6 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index cfd9ca6d2b..b883672e63 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -75,7 +75,6 @@ ecall       000000000000     00000 000 00000 1110011
 ebreak      000000000001     00000 000 00000 1110011
 uret        0000000    00010 00000 000 00000 1110011
 sret        0001000    00010 00000 000 00000 1110011
-hret        0010000    00010 00000 000 00000 1110011
 mret        0011000    00010 00000 000 00000 1110011
 wfi         0001000    00101 00000 000 00000 1110011
 hfence_gvma 0110001    ..... ..... 000 00000 1110011 @hfence_gvma
diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c
index b9b5a89b52..76c2fad71c 100644
--- a/target/riscv/insn_trans/trans_privileged.inc.c
+++ b/target/riscv/insn_trans/trans_privileged.inc.c
@@ -58,11 +58,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
 #endif
 }
 
-static bool trans_hret(DisasContext *ctx, arg_hret *a)
-{
-    return false;
-}
-
 static bool trans_mret(DisasContext *ctx, arg_mret *a)
 {
 #ifndef CONFIG_USER_ONLY
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 27/36] target/riscv: Disable guest FP support based on virtual status
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (25 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 28/36] target/riscv: Mark both sstatus and vsstatus as dirty Alistair Francis
                   ` (32 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

When the Hypervisor extension is in use we only enable floating point
support when both status and vsstatus have enabled floating point
support.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu_helper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 2c6d2bc3a3..2040fc0208 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -99,6 +99,9 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 bool riscv_cpu_fp_enabled(CPURISCVState *env)
 {
     if (*env->mstatus & MSTATUS_FS) {
+        if (riscv_cpu_virt_enabled(env) && !(env->vsstatus & MSTATUS_FS)) {
+            return false;
+        }
         return true;
     }
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 28/36] target/riscv: Mark both sstatus and vsstatus as dirty
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (26 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 27/36] target/riscv: Disable guest FP support based on virtual status Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Alistair Francis
                   ` (31 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Mark both sstatus and vsstatus as dirty (3).

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/translate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1a379bd2ae..1d879b34db 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -44,6 +44,7 @@ typedef struct DisasContext {
     /* pc_succ_insn points to the instruction following base.pc_next */
     target_ulong pc_succ_insn;
     target_ulong priv_ver;
+    bool virt_enabled;
     uint32_t opcode;
     uint32_t mstatus_fs;
     uint32_t misa;
@@ -396,6 +397,12 @@ static void mark_fs_dirty(DisasContext *ctx)
     tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
     tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
     tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
+
+    if (ctx->virt_enabled) {
+        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, vsstatus));
+        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
+        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, vsstatus));
+    }
     tcg_temp_free(tmp);
 }
 #else
@@ -740,6 +747,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
     ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
     ctx->priv_ver = env->priv_ver;
+#if !defined(CONFIG_USER_ONLY)
+    ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+#else
+    ctx->virt_enabled = false;
+#endif
     ctx->misa = env->misa;
     ctx->frm = -1;  /* unknown rounding mode */
     ctx->ext_ifencei = cpu->cfg.ext_ifencei;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (27 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 28/36] target/riscv: Mark both sstatus and vsstatus as dirty Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:11 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Alistair Francis
                   ` (30 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

mark_fs_dirty() is the only place in translate.c that uses the
virt_enabled bool. Let's respect the contents of MSTATUS.MPRV and
HSTATUS.SPRV when setting the bool as this is used for performing
floating point operations when V=0.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/translate.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1d879b34db..dd93e12b45 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -748,7 +748,21 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
     ctx->priv_ver = env->priv_ver;
 #if !defined(CONFIG_USER_ONLY)
-    ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+    if (riscv_has_ext(env, RVH)) {
+        ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+        if (env->priv_ver == PRV_M &&
+            get_field(*env->mstatus, MSTATUS_MPRV) &&
+            get_field(*env->mstatus, MSTATUS_MPV)) {
+            ctx->virt_enabled = true;
+        } else if (env->priv == PRV_S &&
+                   !riscv_cpu_virt_enabled(env) &&
+                   get_field(env->hstatus, HSTATUS_SPRV) &&
+                   get_field(env->hstatus, HSTATUS_SPV)) {
+            ctx->virt_enabled = true;
+        }
+    } else {
+        ctx->virt_enabled = false;
+    }
 #else
     ctx->virt_enabled = false;
 #endif
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 30/36] target/riscv: Allow specifying MMU stage
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (28 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Alistair Francis
@ 2019-12-09 18:11 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Alistair Francis
                   ` (29 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_helper.c | 39 ++++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 2040fc0208..8b234790a7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -279,10 +279,19 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
  *
  * Adapted from Spike's mmu_t::translate and mmu_t::walk
  *
+ * @env: CPURISCVState
+ * @physical: This will be set to the calculated physical address
+ * @prot: The returned protection attributes
+ * @addr: The virtual address to be translated
+ * @access_type: The type of MMU access
+ * @mmu_idx: Indicates current privilege level
+ * @first_stage: Are we in first stage translation?
+ *               Second stage is used for hypervisor guest translation
  */
 static int get_physical_address(CPURISCVState *env, hwaddr *physical,
                                 int *prot, target_ulong addr,
-                                int access_type, int mmu_idx)
+                                int access_type, int mmu_idx,
+                                bool first_stage)
 {
     /* NOTE: the env->pc value visible here will not be
      * correct, but the value visible to the exception handler
@@ -485,13 +494,23 @@ restart:
 }
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
-                                MMUAccessType access_type, bool pmp_violation)
+                                MMUAccessType access_type, bool pmp_violation,
+                                bool first_stage)
 {
     CPUState *cs = env_cpu(env);
-    int page_fault_exceptions =
-        (env->priv_ver >= PRIV_VERSION_1_10_0) &&
-        get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
-        !pmp_violation;
+    int page_fault_exceptions;
+    if (first_stage) {
+        page_fault_exceptions =
+            (env->priv_ver >= PRIV_VERSION_1_10_0) &&
+            get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
+            !pmp_violation;
+        riscv_cpu_set_force_hs_excep(env, 0);
+    } else {
+        page_fault_exceptions =
+            get_field(env->hgatp, HGATP_MODE) != VM_1_10_MBARE &&
+            !pmp_violation;
+        riscv_cpu_set_force_hs_excep(env, 1);
+    }
     switch (access_type) {
     case MMU_INST_FETCH:
         cs->exception_index = page_fault_exceptions ?
@@ -518,7 +537,8 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     int prot;
     int mmu_idx = cpu_mmu_index(&cpu->env, false);
 
-    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx)) {
+    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx,
+                             true)) {
         return -1;
     }
     return phys_addr;
@@ -583,7 +603,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
                   __func__, address, access_type, mmu_idx);
 
-    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
+    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx,
+                               true);
 
     if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(*env->mstatus, MSTATUS_MPRV)) {
@@ -610,7 +631,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     } else if (probe) {
         return false;
     } else {
-        raise_mmu_exception(env, address, access_type, pmp_violation);
+        raise_mmu_exception(env, address, access_type, pmp_violation, true);
         riscv_raise_exception(env, cs->exception_index, retaddr);
     }
 #else
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 31/36] target/riscv: Implement second stage MMU
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (29 preceding siblings ...)
  2019-12-09 18:11 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Alistair Francis
                   ` (28 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h        |   1 +
 target/riscv/cpu_helper.c | 193 ++++++++++++++++++++++++++++++++++----
 2 files changed, 175 insertions(+), 19 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index eb089fbdb6..b411a1f900 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -104,6 +104,7 @@ struct CPURISCVState {
     target_ulong frm;
 
     target_ulong badaddr;
+    target_ulong guest_phys_fault_addr;
 
     target_ulong priv_ver;
     target_ulong misa;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8b234790a7..8667e5ffce 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -287,11 +287,12 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
  * @mmu_idx: Indicates current privilege level
  * @first_stage: Are we in first stage translation?
  *               Second stage is used for hypervisor guest translation
+ * @two_stage: Are we going to perform two stage translation
  */
 static int get_physical_address(CPURISCVState *env, hwaddr *physical,
                                 int *prot, target_ulong addr,
                                 int access_type, int mmu_idx,
-                                bool first_stage)
+                                bool first_stage, bool two_stage)
 {
     /* NOTE: the env->pc value visible here will not be
      * correct, but the value visible to the exception handler
@@ -299,13 +300,40 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     MemTxResult res;
     MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
     int mode = mmu_idx;
+    bool use_background = false;
 
+    /*
+     * Check if we should use the background registers for the two
+     * stage translation. We don't need to check if we actually need
+     * two stage translation as that happened before this function
+     * was called. Background registers will be used if the guest has
+     * forced a two stage translation to be on (in HS or M mode).
+     */
     if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(*env->mstatus, MSTATUS_MPRV)) {
             mode = get_field(*env->mstatus, MSTATUS_MPP);
+
+            if (riscv_has_ext(env, RVH) &&
+                get_field(*env->mstatus, MSTATUS_MPV)) {
+                use_background = true;
+            }
+        }
+    }
+
+    if (mode == PRV_S && access_type != MMU_INST_FETCH &&
+        riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
+        if (get_field(env->hstatus, HSTATUS_SPRV)) {
+            mode = get_field(*env->mstatus, SSTATUS_SPP);
+            use_background = true;
         }
     }
 
+    if (first_stage == false) {
+        /* We are in stage 2 translation, this is similar to stage 1. */
+        /* Stage 2 is always taken as U-mode */
+        mode = PRV_U;
+    }
+
     if (mode == PRV_M || !riscv_feature(env, RISCV_FEATURE_MMU)) {
         *physical = addr;
         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -315,13 +343,30 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     *prot = 0;
 
     hwaddr base;
-    int levels, ptidxbits, ptesize, vm, sum;
-    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
+    int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
+
+    if (first_stage == true) {
+        mxr = get_field(*env->mstatus, MSTATUS_MXR);
+    } else {
+        mxr = get_field(env->vsstatus, MSTATUS_MXR);
+    }
 
     if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-        base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
+        if (first_stage == true) {
+            if (use_background) {
+                base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
+                vm = get_field(env->vsatp, SATP_MODE);
+            } else {
+                base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
+                vm = get_field(env->satp, SATP_MODE);
+            }
+            widened = 0;
+        } else {
+            base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
+            vm = get_field(env->hgatp, HGATP_MODE);
+            widened = 2;
+        }
         sum = get_field(*env->mstatus, MSTATUS_SUM);
-        vm = get_field(env->satp, SATP_MODE);
         switch (vm) {
         case VM_1_10_SV32:
           levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -339,6 +384,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
           g_assert_not_reached();
         }
     } else {
+        widened = 0;
         base = (hwaddr)(env->sptbr) << PGSHIFT;
         sum = !get_field(*env->mstatus, MSTATUS_PUM);
         vm = get_field(*env->mstatus, MSTATUS_VM);
@@ -359,9 +405,16 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     }
 
     CPUState *cs = env_cpu(env);
-    int va_bits = PGSHIFT + levels * ptidxbits;
-    target_ulong mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
-    target_ulong masked_msbs = (addr >> (va_bits - 1)) & mask;
+    int va_bits = PGSHIFT + levels * ptidxbits + widened;
+    target_ulong mask, masked_msbs;
+
+    if (TARGET_LONG_BITS > (va_bits - 1)) {
+        mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+    } else {
+        mask = 0;
+    }
+    masked_msbs = (addr >> (va_bits - 1)) & mask;
+
     if (masked_msbs != 0 && masked_msbs != mask) {
         return TRANSLATE_FAIL;
     }
@@ -373,11 +426,29 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 restart:
 #endif
     for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
-        target_ulong idx = (addr >> (PGSHIFT + ptshift)) &
+        target_ulong idx;
+        if (i == 0) {
+            idx = (addr >> (PGSHIFT + ptshift)) &
+                           ((1 << (ptidxbits + widened)) - 1);
+        } else {
+            idx = (addr >> (PGSHIFT + ptshift)) &
                            ((1 << ptidxbits) - 1);
+        }
 
         /* check that physical address of PTE is legal */
-        hwaddr pte_addr = base + idx * ptesize;
+        hwaddr pte_addr;
+
+        if (two_stage && first_stage) {
+            hwaddr vbase;
+
+            /* Do the second stage translation on the base PTE address. */
+            get_physical_address(env, &vbase, prot, base, access_type,
+                                 mmu_idx, false, true);
+
+            pte_addr = vbase + idx * ptesize;
+        } else {
+            pte_addr = base + idx * ptesize;
+        }
 
         if (riscv_feature(env, RISCV_FEATURE_PMP) &&
             !pmp_hart_has_privs(env, pte_addr, sizeof(target_ulong),
@@ -474,7 +545,12 @@ restart:
             /* for superpage mappings, make a fake leaf PTE for the TLB's
                benefit. */
             target_ulong vpn = addr >> PGSHIFT;
-            *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
+            if (i == 0) {
+                *physical = (ppn | (vpn & ((1L << (ptshift + widened)) - 1))) <<
+                             PGSHIFT;
+            } else {
+                *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
+            }
 
             /* set permissions on the TLB entry */
             if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
@@ -533,14 +609,23 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
     hwaddr phys_addr;
     int prot;
     int mmu_idx = cpu_mmu_index(&cpu->env, false);
 
-    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx,
-                             true)) {
+    if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx,
+                             true, riscv_cpu_virt_enabled(env))) {
         return -1;
     }
+
+    if (riscv_cpu_virt_enabled(env)) {
+        if (get_physical_address(env, &phys_addr, &prot, phys_addr,
+                                 0, mmu_idx, false, true)) {
+            return -1;
+        }
+    }
+
     return phys_addr;
 }
 
@@ -594,17 +679,37 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
 #ifndef CONFIG_USER_ONLY
+    vaddr im_address;
     hwaddr pa = 0;
     int prot;
     bool pmp_violation = false;
+    bool m_mode_two_stage = false;
+    bool hs_mode_two_stage = false;
+    bool first_stage_error = true;
     int ret = TRANSLATE_FAIL;
     int mode = mmu_idx;
 
+    env->guest_phys_fault_addr = 0;
+
     qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
                   __func__, address, access_type, mmu_idx);
 
-    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx,
-                               true);
+    /*
+     * Determine if we are in M mode and MPRV is set or in HS mode and SPRV is
+     * set and we want to access a virtulisation address.
+     */
+    if (riscv_has_ext(env, RVH)) {
+        m_mode_two_stage = env->priv == PRV_M &&
+                           access_type != MMU_INST_FETCH &&
+                           get_field(*env->mstatus, MSTATUS_MPRV) &&
+                           get_field(*env->mstatus, MSTATUS_MPV);
+
+        hs_mode_two_stage = env->priv == PRV_S &&
+                            !riscv_cpu_virt_enabled(env) &&
+                            access_type != MMU_INST_FETCH &&
+                            get_field(env->hstatus, HSTATUS_SPRV) &&
+                            get_field(env->hstatus, HSTATUS_SPV);
+    }
 
     if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(*env->mstatus, MSTATUS_MPRV)) {
@@ -612,9 +717,55 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
         }
     }
 
-    qemu_log_mask(CPU_LOG_MMU,
-                  "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
-                  " prot %d\n", __func__, address, ret, pa, prot);
+    if (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) {
+        /* Two stage lookup */
+        ret = get_physical_address(env, &pa, &prot, address, access_type,
+                                   mmu_idx, true, true);
+
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
+                      TARGET_FMT_plx " prot %d\n",
+                      __func__, address, ret, pa, prot);
+
+        if (ret != TRANSLATE_FAIL) {
+            /* Second stage lookup */
+            im_address = pa;
+
+            ret = get_physical_address(env, &pa, &prot, im_address,
+                                       access_type, mmu_idx, false, true);
+
+            qemu_log_mask(CPU_LOG_MMU,
+                    "%s 2nd-stage address=%" VADDR_PRIx " ret %d physical "
+                    TARGET_FMT_plx " prot %d\n",
+                    __func__, im_address, ret, pa, prot);
+
+            if (riscv_feature(env, RISCV_FEATURE_PMP) &&
+                (ret == TRANSLATE_SUCCESS) &&
+                !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
+                ret = TRANSLATE_PMP_FAIL;
+            }
+
+            if (ret != TRANSLATE_SUCCESS) {
+                /*
+                 * Guest physical address translation failed, this is a HS
+                 * level exception
+                 */
+                first_stage_error = false;
+                env->guest_phys_fault_addr = (im_address |
+                                              (address &
+                                               (TARGET_PAGE_SIZE - 1))) >> 2;
+            }
+        }
+    } else {
+        /* Single stage lookup */
+        ret = get_physical_address(env, &pa, &prot, address, access_type,
+                                   mmu_idx, true, false);
+
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s address=%" VADDR_PRIx " ret %d physical "
+                      TARGET_FMT_plx " prot %d\n",
+                      __func__, address, ret, pa, prot);
+    }
 
     if (riscv_feature(env, RISCV_FEATURE_PMP) &&
         (ret == TRANSLATE_SUCCESS) &&
@@ -624,6 +775,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     if (ret == TRANSLATE_PMP_FAIL) {
         pmp_violation = true;
     }
+
     if (ret == TRANSLATE_SUCCESS) {
         tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
                      prot, mmu_idx, TARGET_PAGE_SIZE);
@@ -631,9 +783,12 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     } else if (probe) {
         return false;
     } else {
-        raise_mmu_exception(env, address, access_type, pmp_violation, true);
+        raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error);
         riscv_raise_exception(env, cs->exception_index, retaddr);
     }
+
+    return true;
+
 #else
     switch (access_type) {
     case MMU_INST_FETCH:
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (30 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Alistair Francis
                   ` (27 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_helper.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8667e5ffce..43c6629014 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -589,16 +589,28 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
     }
     switch (access_type) {
     case MMU_INST_FETCH:
-        cs->exception_index = page_fault_exceptions ?
-            RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+        if (riscv_cpu_virt_enabled(env) && !first_stage) {
+            cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+        }
         break;
     case MMU_DATA_LOAD:
-        cs->exception_index = page_fault_exceptions ?
-            RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+        if (riscv_cpu_virt_enabled(env) && !first_stage) {
+            cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+        }
         break;
     case MMU_DATA_STORE:
-        cs->exception_index = page_fault_exceptions ?
-            RISCV_EXCP_STORE_PAGE_FAULT : RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+        if (riscv_cpu_virt_enabled(env) && !first_stage) {
+            cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_STORE_PAGE_FAULT : RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+        }
         break;
     default:
         g_assert_not_reached();
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (31 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Alistair Francis
                   ` (26 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_helper.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 43c6629014..aa033b8590 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -841,6 +841,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
     target_ulong deleg = async ? env->mideleg : env->medeleg;
     target_ulong tval = 0;
+    target_ulong htval = 0;
+    target_ulong mtval2 = 0;
 
     if (!async) {
         /* set tval to badaddr for traps with address information */
@@ -900,6 +902,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                 env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
                                          riscv_cpu_virt_enabled(env));
 
+                htval = env->guest_phys_fault_addr;
+
                 riscv_cpu_set_virt_enabled(env, 0);
                 riscv_cpu_set_force_hs_excep(env, 0);
             } else {
@@ -910,6 +914,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                                          get_field(*env->mstatus, SSTATUS_SPP));
                 env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
                                          riscv_cpu_virt_enabled(env));
+
+                htval = env->guest_phys_fault_addr;
             }
         }
 
@@ -922,6 +928,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
         env->sepc = env->pc;
         env->sbadaddr = tval;
+        env->htval = htval;
         env->pc = (env->stvec >> 2 << 2) +
             ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
         riscv_cpu_set_mode(env, PRV_S);
@@ -936,6 +943,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
                                       riscv_cpu_force_hs_excep_enabled(env));
 
+            mtval2 = env->guest_phys_fault_addr;
+
             /* Trapping to M mode, virt is disabled */
             riscv_cpu_set_virt_enabled(env, 0);
         }
@@ -949,6 +958,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         env->mcause = cause | ~(((target_ulong)-1) >> async);
         env->mepc = env->pc;
         env->mbadaddr = tval;
+        env->mtval2 = mtval2;
         env->pc = (env->mtvec >> 2 << 2) +
             ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
         riscv_cpu_set_mode(env, PRV_M);
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (32 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Alistair Francis
                   ` (25 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c        |  6 ++++++
 target/riscv/cpu.h        |  7 +++++++
 target/riscv/cpu_bits.h   |  3 +++
 target/riscv/cpu_helper.c |  7 +++++++
 target/riscv/csr.c        | 25 +++++++++++++++++++++++++
 target/riscv/op_helper.c  |  4 ++++
 6 files changed, 52 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e61cf46a73..ac8f53a49d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -237,6 +237,9 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 #ifndef CONFIG_USER_ONLY
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
+#ifdef TARGET_RISCV32
+    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", *env->mstatush);
+#endif
     if (riscv_has_ext(env, RVH)) {
         qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
         qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
@@ -473,6 +476,9 @@ static void riscv_cpu_init(Object *obj)
 
 #ifndef CONFIG_USER_ONLY
     env->mstatus = &env->mstatus_novirt;
+# ifdef TARGET_RISCV32
+    env->mstatush = &env->mstatush_novirt;
+# endif
 #endif
 }
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b411a1f900..84a07971dc 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -127,6 +127,10 @@ struct CPURISCVState {
 
     target_ulong mip;
 
+#ifdef TARGET_RISCV32
+    target_ulong *mstatush;
+#endif
+
     uint32_t miclaim;
 
     target_ulong mie;
@@ -153,6 +157,9 @@ struct CPURISCVState {
      * required to handle the Hypervisor register swapping.
      */
     target_ulong mstatus_novirt;
+#ifdef TARGET_RISCV32
+    target_ulong mstatush_novirt;
+#endif
 
     /* Hypervisor CSRs */
     target_ulong hstatus;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a24654d137..049032f2ae 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -135,6 +135,9 @@
 #define CSR_MTVEC           0x305
 #define CSR_MCOUNTEREN      0x306
 
+/* 32-bit only */
+#define CSR_MSTATUSH        0x310
+
 /* Legacy Counter Setup (priv v1.9.1) */
 /* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */
 #define CSR_MUCOUNTEREN     0x320
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index aa033b8590..c2ad0bbce7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -938,10 +938,17 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             if (riscv_cpu_virt_enabled(env)) {
                 riscv_cpu_swap_hypervisor_regs(env);
             }
+#ifdef TARGET_RISCV32
+            *env->mstatush = set_field(*env->mstatush, MSTATUS_MPV,
+                                       riscv_cpu_virt_enabled(env));
+            *env->mstatush = set_field(*env->mstatush, MSTATUS_MTL,
+                                       riscv_cpu_force_hs_excep_enabled(env));
+#else
             *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
                                       riscv_cpu_virt_enabled(env));
             *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
                                       riscv_cpu_force_hs_excep_enabled(env));
+#endif
 
             mtval2 = env->guest_phys_fault_addr;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d028dfb60b..b28058f9d5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -372,6 +372,27 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
+#ifdef TARGET_RISCV32
+static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = *env->mstatush;
+    return 0;
+}
+
+static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if ((val ^ *env->mstatush) & (MSTATUS_MPV)) {
+        tlb_flush(env_cpu(env));
+    }
+
+    val &= MSTATUS_MPV | MSTATUS_MTL;
+
+    *env->mstatush = val;
+
+    return 0;
+}
+#endif
+
 static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
 {
     *val = env->misa;
@@ -1215,6 +1236,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
     [CSR_MTVEC] =               { any,  read_mtvec,       write_mtvec       },
     [CSR_MCOUNTEREN] =          { any,  read_mcounteren,  write_mcounteren  },
 
+#if defined(TARGET_RISCV32)
+    [CSR_MSTATUSH] =            { any,  read_mstatush,    write_mstatush    },
+#endif
+
     /* Legacy Counter Setup (priv v1.9.1) */
     [CSR_MUCOUNTEREN] =         { any,  read_mucounteren, write_mucounteren },
     [CSR_MSCOUNTEREN] =         { any,  read_mscounteren, write_mscounteren },
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index e5128570e6..a0a631d722 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -153,7 +153,11 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
         get_field(mstatus, MSTATUS_MPIE));
     mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
     mstatus = set_field(mstatus, MSTATUS_MPP, 0);
+#ifdef TARGET_RISCV32
+    *env->mstatush = set_field(*env->mstatush, MSTATUS_MPV, 0);
+#else
     mstatus = set_field(mstatus, MSTATUS_MPV, 0);
+#endif
     *env->mstatus = mstatus;
     riscv_cpu_set_mode(env, prev_priv);
 
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (33 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 18:12 ` [PATCH v1 36/36] target/riscv: Allow enabling the Hypervisor extension Alistair Francis
                   ` (24 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Add a helper macro MSTATUS_MPV_ISSET() which will determine if the
MSTATUS_MPV bit is set for both 32-bit and 64-bit RISC-V.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_bits.h   | 11 +++++++++++
 target/riscv/cpu_helper.c |  4 ++--
 target/riscv/op_helper.c  |  2 +-
 target/riscv/translate.c  |  2 +-
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 049032f2ae..dd012a514e 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -363,8 +363,19 @@
 #define MSTATUS_TVM         0x00100000 /* since: priv-1.10 */
 #define MSTATUS_TW          0x20000000 /* since: priv-1.10 */
 #define MSTATUS_TSR         0x40000000 /* since: priv-1.10 */
+#if defined(TARGET_RISCV64)
 #define MSTATUS_MTL         0x4000000000ULL
 #define MSTATUS_MPV         0x8000000000ULL
+#elif defined(TARGET_RISCV32)
+#define MSTATUS_MTL         0x00000040
+#define MSTATUS_MPV         0x00000080
+#endif
+
+#ifdef TARGET_RISCV32
+# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatush, MSTATUS_MPV)
+#else
+# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatus, MSTATUS_MPV)
+#endif
 
 #define MSTATUS64_UXL       0x0000000300000000ULL
 #define MSTATUS64_SXL       0x0000000C00000000ULL
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c2ad0bbce7..7166e6199e 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -314,7 +314,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
             mode = get_field(*env->mstatus, MSTATUS_MPP);
 
             if (riscv_has_ext(env, RVH) &&
-                get_field(*env->mstatus, MSTATUS_MPV)) {
+                MSTATUS_MPV_ISSET(env)) {
                 use_background = true;
             }
         }
@@ -714,7 +714,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
         m_mode_two_stage = env->priv == PRV_M &&
                            access_type != MMU_INST_FETCH &&
                            get_field(*env->mstatus, MSTATUS_MPRV) &&
-                           get_field(*env->mstatus, MSTATUS_MPV);
+                           MSTATUS_MPV_ISSET(env);
 
         hs_mode_two_stage = env->priv == PRV_S &&
                             !riscv_cpu_virt_enabled(env) &&
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index a0a631d722..b0b9890a15 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -146,7 +146,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
 
     target_ulong mstatus = *env->mstatus;
     target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
-    target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
+    target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
     mstatus = set_field(mstatus,
         env->priv_ver >= PRIV_VERSION_1_10_0 ?
         MSTATUS_MIE : MSTATUS_UIE << prev_priv,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index dd93e12b45..0a28f208a2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -752,7 +752,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
         ctx->virt_enabled = riscv_cpu_virt_enabled(env);
         if (env->priv_ver == PRV_M &&
             get_field(*env->mstatus, MSTATUS_MPRV) &&
-            get_field(*env->mstatus, MSTATUS_MPV)) {
+            MSTATUS_MPV_ISSET(env)) {
             ctx->virt_enabled = true;
         } else if (env->priv == PRV_S &&
                    !riscv_cpu_virt_enabled(env) &&
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [PATCH v1 36/36] target/riscv: Allow enabling the Hypervisor extension
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (34 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Alistair Francis
@ 2019-12-09 18:12 ` Alistair Francis
  2019-12-09 22:55 ` [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Aleksandar Markovic
                   ` (23 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2019-12-09 18:12 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: alistair.francis, palmer, alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu.c | 5 +++++
 target/riscv/cpu.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ac8f53a49d..f087bc2c8b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -453,6 +453,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
         if (cpu->cfg.ext_u) {
             target_misa |= RVU;
         }
+        if (cpu->cfg.ext_h) {
+            target_misa |= RVH;
+        }
 
         set_misa(env, RVXLEN | target_misa);
     }
@@ -498,6 +501,8 @@ static Property riscv_cpu_properties[] = {
     DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
     DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
     DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
+    /* This is experimental so mark with 'x-' */
+    DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
     DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
     DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
     DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 84a07971dc..53bc6af5f7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -261,6 +261,7 @@ typedef struct RISCVCPU {
         bool ext_c;
         bool ext_s;
         bool ext_u;
+        bool ext_h;
         bool ext_counters;
         bool ext_ifencei;
         bool ext_icsr;
-- 
2.24.0



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (35 preceding siblings ...)
  2019-12-09 18:12 ` [PATCH v1 36/36] target/riscv: Allow enabling the Hypervisor extension Alistair Francis
@ 2019-12-09 22:55 ` Aleksandar Markovic
  2019-12-10  0:03   ` Alistair Francis
  2020-01-02 18:18 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Palmer Dabbelt
                   ` (22 subsequent siblings)
  59 siblings, 1 reply; 78+ messages in thread
From: Aleksandar Markovic @ 2019-12-09 22:55 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Peter Maydell, palmer, qemu-riscv, qemu-devel, alistair23

[-- Attachment #1: Type: text/plain, Size: 6107 bytes --]

On Monday, December 9, 2019, Alistair Francis <alistair.francis@wdc.com>
wrote:

> This patch series adds the RISC-V Hypervisor extension v0.5. This is the
> latest draft spec of the Hypervisor extension.
>
>
Hi, Alistair,

I have a question for you:

Let's say this series is accepted. And let's say, next year, the draft spec
of RISC-V Hypervisor extension v0.6 is released, and you or somebody else
comes up with series on QEMU support for it, and that series is accepted
too. What would happen afterwards:

A. Both support for v0.5 and v0.6 would continue to coexist perpetually

B. Support for v0.5 would be deprecated according to QEMU deprecation
rules, and in two cycle would disappear

C. Support for v0.5 would abruptly stop existing

D. Something else

?

Thanks,
Aleksandar



> The Hypervisor extension is disabled by default, so this series should
> result in no changes to anyone using QEMU unless they enable the
> extension. The extention can be enabled with the -cpu property (see
> below).
>
> Testing of this implementation has been done by using the baremetal
> Xvisor Hypervisor. We are able to run two Linux guests (that's all I
> have tried) as guests in 64-bit. In 32-bit so far I can only run
> baremetal guests, but I think this is a baremetal boot loader issue and
> not an issue in QEMU.
>
> The RISC-V KVM implementation was also written using these patches. The
> KVM implementation is currently under review.
>
> At the moment this spec is in a draft state and is subject to change. As
> QEMU is extreamly useful in early bring up I think it makes sense for
> QEMU to support non-frozen extensions.
>
> Thanks to Anup for doing the initial port of Xvisor. The port is avaliable
> here:
> https://github.com/avpatel/xvisor-next and will run on QEMU.
>
> Also thanks to Atish for implementing the SBI call support in Xvisor and
> for lots of help debugging.
>
> To run this yourself:
>  1. Apply this patch series to QEMU. The latest branch can be found here:
>       https://github.com/alistair23/qemu/tree/mainline/alistair/
> riscv-hyp-ext-v0.5.next
>  2. Get the version of OpenSBI that supports the H extension. This can
>     be found here:
>       https://github.com/avpatel/opensbi/tree/riscv_hyp_ext_0_5_v1
>  3. Build the next release of Xvisor. It is available here:
>       https://github.com/avpatel/xvisor-next
>  4. Make sure you build the Xvisor tests, see here for details:
>       https://github.com/avpatel/xvisor-next/tree/master/tests/
> riscv/virt64/linux
>  5. Run QEMU:
>      ./riscv64-softmmu/qemu-system-riscv64 -nographic \
>        -machine virt -cpu rv64,x-h=true \
>        -serial mon:stdio -serial null -m 4G \
>        -device loader,file=vmm.bin,addr=0x80200000 \
>        -kernel fw_jump.elf \
>        -initrd vmm-disk-linux.img \
>        -append "vmm.console=uart@10000000 vmm.bootcmd=\"vfs mount initrd
> /;vfs run /boot.xscript;vfs cat /system/banner.txt\""
>
>    Once you get to the prompt you can start the geust by running:
>      guest kick guest0
>    You can then bind to the serial port using:
>      vserial bind guest0/uart0
>    Then you can start Linux using:
>      autoexec
>
>  This was all tested with the mainline 5.2/5.3 kernels.
>
> There is very early work on a Xen port as well which is avaliable here:
> https://github.com/alistair23/xen/tree/alistair/riscv-port
>
> ToDo/Issues
>  - Get 32-bit fully working
>
>
>
> Alistair Francis (36):
>   target/riscv: Convert MIP CSR to target_ulong
>   target/riscv: Don't set write permissions on dirty PTEs
>   target/riscv: Add the Hypervisor extension
>   target/riscv: Add the Hypervisor CSRs to CPUState
>   target/riscv: Add support for the new execption numbers
>   target/riscv: Rename the H irqs to VS irqs
>   target/riscv: Add the virtulisation mode
>   target/riscv: Add the force HS exception mode
>   target/riscv: Fix CSR perm checking for HS mode
>   target/riscv: Print priv and virt in disas log
>   target/riscv: Dump Hypervisor registers if enabled
>   target/riscv: Add Hypervisor CSR access functions
>   target/riscv: Add Hypervisor virtual CSRs accesses
>   target/riscv: Add Hypervisor virtual CSRs accesses
>   target/riscv: Convert mstatus to pointers
>   target/riscv: Add virtual register swapping function
>   target/riscv: Set VS bits in mideleg for Hyp extension
>   target/riscv: Extend the MIE CSR to support virtulisation
>   target/riscv: Extend the SIP CSR to support virtulisation
>   target/riscv: Add support for virtual interrupt setting
>   target/ricsv: Flush the TLB on virtulisation mode changes
>   target/riscv: Generate illegal instruction on WFI when V=1
>   target/riscv: Add hypvervisor trap support
>   target/riscv: Add Hypervisor trap return support
>   target/riscv: Add hfence instructions
>   target/riscv: Remove the hret instruction
>   target/riscv: Disable guest FP support based on virtual status
>   target/riscv: Mark both sstatus and vsstatus as dirty
>   target/riscv: Respect MPRV and SPRV for floating point ops
>   target/riscv: Allow specifying MMU stage
>   target/riscv: Implement second stage MMU
>   target/riscv: Raise the new execptions when 2nd stage translation
>     fails
>   target/riscv: Set htval and mtval2 on execptions
>   target/riscv: Add support for the 32-bit MSTATUSH CSR
>   target/riscv: Add the MSTATUS_MPV_ISSET helper macro
>   target/riscv: Allow enabling the Hypervisor extension
>
>  target/riscv/cpu.c                            |  71 ++-
>  target/riscv/cpu.h                            |  58 +-
>  target/riscv/cpu_bits.h                       | 111 ++--
>  target/riscv/cpu_helper.c                     | 501 +++++++++++++++---
>  target/riscv/csr.c                            | 389 +++++++++++++-
>  target/riscv/gdbstub.c                        |  11 +-
>  target/riscv/insn32.decode                    |  22 +-
>  .../riscv/insn_trans/trans_privileged.inc.c   |  45 +-
>  target/riscv/op_helper.c                      |  81 ++-
>  target/riscv/translate.c                      |  34 ++
>  10 files changed, 1161 insertions(+), 162 deletions(-)
>
> --
> 2.24.0
>
>
>

[-- Attachment #2: Type: text/html, Size: 7874 bytes --]

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5
  2019-12-09 22:55 ` [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Aleksandar Markovic
@ 2019-12-10  0:03   ` Alistair Francis
  2019-12-10 19:05     ` Aleksandar Markovic
  0 siblings, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2019-12-10  0:03 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: qemu-riscv, palmer, Alistair Francis, qemu-devel, Peter Maydell

On Mon, Dec 9, 2019 at 2:55 PM Aleksandar Markovic
<aleksandar.m.mail@gmail.com> wrote:
>
>
>
> On Monday, December 9, 2019, Alistair Francis <alistair.francis@wdc.com> wrote:
>>
>> This patch series adds the RISC-V Hypervisor extension v0.5. This is the
>> latest draft spec of the Hypervisor extension.
>>
>
> Hi, Alistair,
>
> I have a question for you:
>
> Let's say this series is accepted. And let's say, next year, the draft spec of RISC-V Hypervisor extension v0.6 is released, and you or somebody else comes up with series on QEMU support for it, and that series is accepted too. What would happen afterwards:
>
> A. Both support for v0.5 and v0.6 would continue to coexist perpetually
>
> B. Support for v0.5 would be deprecated according to QEMU deprecation rules, and in two cycle would disappear
>
> C. Support for v0.5 would abruptly stop existing

My current plan is to upgrade the implementation to the next version
and drop v0.5 when a new spec release. happens.

The justification for this is that the Hypervisor is a draft
extension, disabled by default and marked as experimental. Therefore I
think it's ok to just support the latest version of the spec.

Alistair

>
> D. Something else
>
> ?
>
> Thanks,
> Aleksandar
>
>
>>
>> The Hypervisor extension is disabled by default, so this series should
>> result in no changes to anyone using QEMU unless they enable the
>> extension. The extention can be enabled with the -cpu property (see
>> below).
>>
>> Testing of this implementation has been done by using the baremetal
>> Xvisor Hypervisor. We are able to run two Linux guests (that's all I
>> have tried) as guests in 64-bit. In 32-bit so far I can only run
>> baremetal guests, but I think this is a baremetal boot loader issue and
>> not an issue in QEMU.
>>
>> The RISC-V KVM implementation was also written using these patches. The
>> KVM implementation is currently under review.
>>
>> At the moment this spec is in a draft state and is subject to change. As
>> QEMU is extreamly useful in early bring up I think it makes sense for
>> QEMU to support non-frozen extensions.
>>
>> Thanks to Anup for doing the initial port of Xvisor. The port is avaliable here:
>> https://github.com/avpatel/xvisor-next and will run on QEMU.
>>
>> Also thanks to Atish for implementing the SBI call support in Xvisor and
>> for lots of help debugging.
>>
>> To run this yourself:
>>  1. Apply this patch series to QEMU. The latest branch can be found here:
>>       https://github.com/alistair23/qemu/tree/mainline/alistair/riscv-hyp-ext-v0.5.next
>>  2. Get the version of OpenSBI that supports the H extension. This can
>>     be found here:
>>       https://github.com/avpatel/opensbi/tree/riscv_hyp_ext_0_5_v1
>>  3. Build the next release of Xvisor. It is available here:
>>       https://github.com/avpatel/xvisor-next
>>  4. Make sure you build the Xvisor tests, see here for details:
>>       https://github.com/avpatel/xvisor-next/tree/master/tests/riscv/virt64/linux
>>  5. Run QEMU:
>>      ./riscv64-softmmu/qemu-system-riscv64 -nographic \
>>        -machine virt -cpu rv64,x-h=true \
>>        -serial mon:stdio -serial null -m 4G \
>>        -device loader,file=vmm.bin,addr=0x80200000 \
>>        -kernel fw_jump.elf \
>>        -initrd vmm-disk-linux.img \
>>        -append "vmm.console=uart@10000000 vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""
>>
>>    Once you get to the prompt you can start the geust by running:
>>      guest kick guest0
>>    You can then bind to the serial port using:
>>      vserial bind guest0/uart0
>>    Then you can start Linux using:
>>      autoexec
>>
>>  This was all tested with the mainline 5.2/5.3 kernels.
>>
>> There is very early work on a Xen port as well which is avaliable here:
>> https://github.com/alistair23/xen/tree/alistair/riscv-port
>>
>> ToDo/Issues
>>  - Get 32-bit fully working
>>
>>
>>
>> Alistair Francis (36):
>>   target/riscv: Convert MIP CSR to target_ulong
>>   target/riscv: Don't set write permissions on dirty PTEs
>>   target/riscv: Add the Hypervisor extension
>>   target/riscv: Add the Hypervisor CSRs to CPUState
>>   target/riscv: Add support for the new execption numbers
>>   target/riscv: Rename the H irqs to VS irqs
>>   target/riscv: Add the virtulisation mode
>>   target/riscv: Add the force HS exception mode
>>   target/riscv: Fix CSR perm checking for HS mode
>>   target/riscv: Print priv and virt in disas log
>>   target/riscv: Dump Hypervisor registers if enabled
>>   target/riscv: Add Hypervisor CSR access functions
>>   target/riscv: Add Hypervisor virtual CSRs accesses
>>   target/riscv: Add Hypervisor virtual CSRs accesses
>>   target/riscv: Convert mstatus to pointers
>>   target/riscv: Add virtual register swapping function
>>   target/riscv: Set VS bits in mideleg for Hyp extension
>>   target/riscv: Extend the MIE CSR to support virtulisation
>>   target/riscv: Extend the SIP CSR to support virtulisation
>>   target/riscv: Add support for virtual interrupt setting
>>   target/ricsv: Flush the TLB on virtulisation mode changes
>>   target/riscv: Generate illegal instruction on WFI when V=1
>>   target/riscv: Add hypvervisor trap support
>>   target/riscv: Add Hypervisor trap return support
>>   target/riscv: Add hfence instructions
>>   target/riscv: Remove the hret instruction
>>   target/riscv: Disable guest FP support based on virtual status
>>   target/riscv: Mark both sstatus and vsstatus as dirty
>>   target/riscv: Respect MPRV and SPRV for floating point ops
>>   target/riscv: Allow specifying MMU stage
>>   target/riscv: Implement second stage MMU
>>   target/riscv: Raise the new execptions when 2nd stage translation
>>     fails
>>   target/riscv: Set htval and mtval2 on execptions
>>   target/riscv: Add support for the 32-bit MSTATUSH CSR
>>   target/riscv: Add the MSTATUS_MPV_ISSET helper macro
>>   target/riscv: Allow enabling the Hypervisor extension
>>
>>  target/riscv/cpu.c                            |  71 ++-
>>  target/riscv/cpu.h                            |  58 +-
>>  target/riscv/cpu_bits.h                       | 111 ++--
>>  target/riscv/cpu_helper.c                     | 501 +++++++++++++++---
>>  target/riscv/csr.c                            | 389 +++++++++++++-
>>  target/riscv/gdbstub.c                        |  11 +-
>>  target/riscv/insn32.decode                    |  22 +-
>>  .../riscv/insn_trans/trans_privileged.inc.c   |  45 +-
>>  target/riscv/op_helper.c                      |  81 ++-
>>  target/riscv/translate.c                      |  34 ++
>>  10 files changed, 1161 insertions(+), 162 deletions(-)
>>
>> --
>> 2.24.0
>>
>>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5
  2019-12-10  0:03   ` Alistair Francis
@ 2019-12-10 19:05     ` Aleksandar Markovic
  0 siblings, 0 replies; 78+ messages in thread
From: Aleksandar Markovic @ 2019-12-10 19:05 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-riscv, palmer, Alistair Francis, qemu-devel, Peter Maydell

On Tue, Dec 10, 2019 at 1:04 AM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Mon, Dec 9, 2019 at 2:55 PM Aleksandar Markovic
> <aleksandar.m.mail@gmail.com> wrote:
> >
> >
> >
> > On Monday, December 9, 2019, Alistair Francis <alistair.francis@wdc.com> wrote:
> >>
> >> This patch series adds the RISC-V Hypervisor extension v0.5. This is the
> >> latest draft spec of the Hypervisor extension.
> >>
> >
> > Hi, Alistair,
> >
> > I have a question for you:
> >
> > Let's say this series is accepted. And let's say, next year, the draft spec of RISC-V Hypervisor extension v0.6 is released, and you or somebody else comes up with series on QEMU support for it, and that series is accepted too. What would happen afterwards:
> >
> > A. Both support for v0.5 and v0.6 would continue to coexist perpetually
> >
> > B. Support for v0.5 would be deprecated according to QEMU deprecation rules, and in two cycle would disappear
> >
> > C. Support for v0.5 would abruptly stop existing
>
> My current plan is to upgrade the implementation to the next version
> and drop v0.5 when a new spec release. happens.
>
> The justification for this is that the Hypervisor is a draft
> extension, disabled by default and marked as experimental. Therefore I
> think it's ok to just support the latest version of the spec.
>

OK. Thanks for clarification.

> Alistair
>
> >
> > D. Something else
> >
> > ?
> >
> > Thanks,
> > Aleksandar
> >
> >
> >>
> >> The Hypervisor extension is disabled by default, so this series should
> >> result in no changes to anyone using QEMU unless they enable the
> >> extension. The extention can be enabled with the -cpu property (see
> >> below).
> >>
> >> Testing of this implementation has been done by using the baremetal
> >> Xvisor Hypervisor. We are able to run two Linux guests (that's all I
> >> have tried) as guests in 64-bit. In 32-bit so far I can only run
> >> baremetal guests, but I think this is a baremetal boot loader issue and
> >> not an issue in QEMU.
> >>
> >> The RISC-V KVM implementation was also written using these patches. The
> >> KVM implementation is currently under review.
> >>
> >> At the moment this spec is in a draft state and is subject to change. As
> >> QEMU is extreamly useful in early bring up I think it makes sense for
> >> QEMU to support non-frozen extensions.
> >>
> >> Thanks to Anup for doing the initial port of Xvisor. The port is avaliable here:
> >> https://github.com/avpatel/xvisor-next and will run on QEMU.
> >>
> >> Also thanks to Atish for implementing the SBI call support in Xvisor and
> >> for lots of help debugging.
> >>
> >> To run this yourself:
> >>  1. Apply this patch series to QEMU. The latest branch can be found here:
> >>       https://github.com/alistair23/qemu/tree/mainline/alistair/riscv-hyp-ext-v0.5.next
> >>  2. Get the version of OpenSBI that supports the H extension. This can
> >>     be found here:
> >>       https://github.com/avpatel/opensbi/tree/riscv_hyp_ext_0_5_v1
> >>  3. Build the next release of Xvisor. It is available here:
> >>       https://github.com/avpatel/xvisor-next
> >>  4. Make sure you build the Xvisor tests, see here for details:
> >>       https://github.com/avpatel/xvisor-next/tree/master/tests/riscv/virt64/linux
> >>  5. Run QEMU:
> >>      ./riscv64-softmmu/qemu-system-riscv64 -nographic \
> >>        -machine virt -cpu rv64,x-h=true \
> >>        -serial mon:stdio -serial null -m 4G \
> >>        -device loader,file=vmm.bin,addr=0x80200000 \
> >>        -kernel fw_jump.elf \
> >>        -initrd vmm-disk-linux.img \
> >>        -append "vmm.console=uart@10000000 vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""
> >>
> >>    Once you get to the prompt you can start the geust by running:
> >>      guest kick guest0
> >>    You can then bind to the serial port using:
> >>      vserial bind guest0/uart0
> >>    Then you can start Linux using:
> >>      autoexec
> >>
> >>  This was all tested with the mainline 5.2/5.3 kernels.
> >>
> >> There is very early work on a Xen port as well which is avaliable here:
> >> https://github.com/alistair23/xen/tree/alistair/riscv-port
> >>
> >> ToDo/Issues
> >>  - Get 32-bit fully working
> >>
> >>
> >>
> >> Alistair Francis (36):
> >>   target/riscv: Convert MIP CSR to target_ulong
> >>   target/riscv: Don't set write permissions on dirty PTEs
> >>   target/riscv: Add the Hypervisor extension
> >>   target/riscv: Add the Hypervisor CSRs to CPUState
> >>   target/riscv: Add support for the new execption numbers
> >>   target/riscv: Rename the H irqs to VS irqs
> >>   target/riscv: Add the virtulisation mode
> >>   target/riscv: Add the force HS exception mode
> >>   target/riscv: Fix CSR perm checking for HS mode
> >>   target/riscv: Print priv and virt in disas log
> >>   target/riscv: Dump Hypervisor registers if enabled
> >>   target/riscv: Add Hypervisor CSR access functions
> >>   target/riscv: Add Hypervisor virtual CSRs accesses
> >>   target/riscv: Add Hypervisor virtual CSRs accesses
> >>   target/riscv: Convert mstatus to pointers
> >>   target/riscv: Add virtual register swapping function
> >>   target/riscv: Set VS bits in mideleg for Hyp extension
> >>   target/riscv: Extend the MIE CSR to support virtulisation
> >>   target/riscv: Extend the SIP CSR to support virtulisation
> >>   target/riscv: Add support for virtual interrupt setting
> >>   target/ricsv: Flush the TLB on virtulisation mode changes
> >>   target/riscv: Generate illegal instruction on WFI when V=1
> >>   target/riscv: Add hypvervisor trap support
> >>   target/riscv: Add Hypervisor trap return support
> >>   target/riscv: Add hfence instructions
> >>   target/riscv: Remove the hret instruction
> >>   target/riscv: Disable guest FP support based on virtual status
> >>   target/riscv: Mark both sstatus and vsstatus as dirty
> >>   target/riscv: Respect MPRV and SPRV for floating point ops
> >>   target/riscv: Allow specifying MMU stage
> >>   target/riscv: Implement second stage MMU
> >>   target/riscv: Raise the new execptions when 2nd stage translation
> >>     fails
> >>   target/riscv: Set htval and mtval2 on execptions
> >>   target/riscv: Add support for the 32-bit MSTATUSH CSR
> >>   target/riscv: Add the MSTATUS_MPV_ISSET helper macro
> >>   target/riscv: Allow enabling the Hypervisor extension
> >>
> >>  target/riscv/cpu.c                            |  71 ++-
> >>  target/riscv/cpu.h                            |  58 +-
> >>  target/riscv/cpu_bits.h                       | 111 ++--
> >>  target/riscv/cpu_helper.c                     | 501 +++++++++++++++---
> >>  target/riscv/csr.c                            | 389 +++++++++++++-
> >>  target/riscv/gdbstub.c                        |  11 +-
> >>  target/riscv/insn32.decode                    |  22 +-
> >>  .../riscv/insn_trans/trans_privileged.inc.c   |  45 +-
> >>  target/riscv/op_helper.c                      |  81 ++-
> >>  target/riscv/translate.c                      |  34 ++
> >>  10 files changed, 1161 insertions(+), 162 deletions(-)
> >>
> >> --
> >> 2.24.0
> >>
> >>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (36 preceding siblings ...)
  2019-12-09 22:55 ` [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Aleksandar Markovic
@ 2020-01-02 18:18 ` Palmer Dabbelt
  2020-01-03  2:08   ` Alistair Francis
  2020-01-06 17:51 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Palmer Dabbelt
                   ` (21 subsequent siblings)
  59 siblings, 1 reply; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-02 18:18 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:43 PST (-0800), Alistair Francis wrote:
> The MIP CSR is a xlen CSR, it was only 32-bits to allow atomic access.
> Now that we don't use atomics for MIP we can change this back to a xlen
> CSR.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.c | 2 +-
>  target/riscv/cpu.h | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index d37861a430..e521ebe2e1 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -224,7 +224,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
>  #ifndef CONFIG_USER_ONLY
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> -    qemu_fprintf(f, " %s 0x%x\n", "mip     ", env->mip);
> +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ", env->mip);
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index e59343e13c..f889427869 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -121,7 +121,7 @@ struct CPURISCVState {
>      target_ulong mhartid;
>      target_ulong mstatus;
>
> -    uint32_t mip;
> +    target_ulong mip;
>      uint32_t miclaim;
>
>      target_ulong mie;

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong
  2020-01-02 18:18 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Palmer Dabbelt
@ 2020-01-03  2:08   ` Alistair Francis
  0 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2020-01-03  2:08 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: open list:RISC-V, Alistair Francis, qemu-devel@nongnu.org Developers

On Thu, Jan 2, 2020 at 10:18 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>
> On Mon, 09 Dec 2019 10:10:43 PST (-0800), Alistair Francis wrote:
> > The MIP CSR is a xlen CSR, it was only 32-bits to allow atomic access.
> > Now that we don't use atomics for MIP we can change this back to a xlen
> > CSR.
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > ---
> >  target/riscv/cpu.c | 2 +-
> >  target/riscv/cpu.h | 2 +-
> >  2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index d37861a430..e521ebe2e1 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -224,7 +224,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> >  #ifndef CONFIG_USER_ONLY
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> > -    qemu_fprintf(f, " %s 0x%x\n", "mip     ", env->mip);
> > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ", env->mip);
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index e59343e13c..f889427869 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -121,7 +121,7 @@ struct CPURISCVState {
> >      target_ulong mhartid;
> >      target_ulong mstatus;
> >
> > -    uint32_t mip;
> > +    target_ulong mip;
> >      uint32_t miclaim;
> >
> >      target_ulong mie;
>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

Thanks!

Can you just apply the patches from this series as they are reviewed?

Also, can you review this series :)

Alistair


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (37 preceding siblings ...)
  2020-01-02 18:18 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Palmer Dabbelt
@ 2020-01-06 17:51 ` Palmer Dabbelt
  2020-01-07  1:33   ` Alistair Francis
  2020-01-07 18:28 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Palmer Dabbelt
                   ` (20 subsequent siblings)
  59 siblings, 1 reply; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-06 17:51 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:45 PST (-0800), Alistair Francis wrote:
> Setting write permission on dirty PTEs results in userspace inside a
> Hypervisor guest (VU) becoming corrupted. This appears to be because it
> ends up with write permission in the second stage translation in cases
> where we aren't doing a store.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>  target/riscv/cpu_helper.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 767c8762ac..0de3a468eb 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -344,10 +344,8 @@ restart:
>              if ((pte & PTE_X)) {
>                  *prot |= PAGE_EXEC;
>              }
> -            /* add write permission on stores or if the page is already dirty,
> -               so that we TLB miss on later writes to update the dirty bit */
> -            if ((pte & PTE_W) &&
> -                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> +            /* add write permission on stores */
> +            if ((pte & PTE_W) && (access_type == MMU_DATA_STORE)) {
>                  *prot |= PAGE_WRITE;
>              }
>              return TRANSLATE_SUCCESS;

This is at least the second time I've spent a day or two trying to figure out
what the right thing to do here is, and once again I'm lost.  I think what's
really getting me is the original comment: why would this cause us to TLB miss,
wouldn't it cause us to not TLB miss?

Assuming that's the case, it seems to me more like there's some missing fence
in whatever program is blowing up due to this -- maybe it's just reading from
the page before marking it as read-only, then relying on writes to trap without
doing the requisite fence.


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs
  2020-01-06 17:51 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Palmer Dabbelt
@ 2020-01-07  1:33   ` Alistair Francis
  0 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2020-01-07  1:33 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: open list:RISC-V, Alistair Francis, qemu-devel@nongnu.org Developers

On Mon, Jan 6, 2020 at 9:51 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>
> On Mon, 09 Dec 2019 10:10:45 PST (-0800), Alistair Francis wrote:
> > Setting write permission on dirty PTEs results in userspace inside a
> > Hypervisor guest (VU) becoming corrupted. This appears to be because it
> > ends up with write permission in the second stage translation in cases
> > where we aren't doing a store.
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> > ---
> >  target/riscv/cpu_helper.c | 6 ++----
> >  1 file changed, 2 insertions(+), 4 deletions(-)
> >
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index 767c8762ac..0de3a468eb 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -344,10 +344,8 @@ restart:
> >              if ((pte & PTE_X)) {
> >                  *prot |= PAGE_EXEC;
> >              }
> > -            /* add write permission on stores or if the page is already dirty,
> > -               so that we TLB miss on later writes to update the dirty bit */
> > -            if ((pte & PTE_W) &&
> > -                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> > +            /* add write permission on stores */
> > +            if ((pte & PTE_W) && (access_type == MMU_DATA_STORE)) {
> >                  *prot |= PAGE_WRITE;
> >              }
> >              return TRANSLATE_SUCCESS;
>
> This is at least the second time I've spent a day or two trying to figure out
> what the right thing to do here is, and once again I'm lost.  I think what's
> really getting me is the original comment: why would this cause us to TLB miss,
> wouldn't it cause us to not TLB miss?
>
> Assuming that's the case, it seems to me more like there's some missing fence
> in whatever program is blowing up due to this -- maybe it's just reading from
> the page before marking it as read-only, then relying on writes to trap without
> doing the requisite fence.

Ok, let's drop this for now then. I'll reinvestigate and if this is
still needed I'll add a more detailed explanation.

Alistair


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (38 preceding siblings ...)
  2020-01-06 17:51 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Palmer Dabbelt
@ 2020-01-07 18:28 ` Palmer Dabbelt
  2020-01-07 18:28 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Palmer Dabbelt
                   ` (19 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-07 18:28 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:50 PST (-0800), Alistair Francis wrote:
> Add the Hypervisor CSRs to CPUState and at the same time (to avoid
> bisect issues) update the CSR macros for the v0.5 Hyp spec.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.h      | 21 +++++++++++++++++++++
>  target/riscv/cpu_bits.h | 34 +++++++++++++++++++++-------------
>  target/riscv/gdbstub.c  | 11 ++++++-----
>  3 files changed, 48 insertions(+), 18 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 91e1c56fc4..bab938103d 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -143,6 +143,27 @@ struct CPURISCVState {
>      target_ulong mcause;
>      target_ulong mtval;  /* since: priv-1.10.0 */
>
> +    /* Hypervisor CSRs */
> +    target_ulong hstatus;
> +    target_ulong hedeleg;
> +    target_ulong hideleg;
> +    target_ulong hcounteren;
> +    target_ulong htval;
> +    target_ulong htinst;
> +    target_ulong hgatp;
> +
> +    /* Virtual CSRs */
> +    target_ulong vsstatus;
> +    target_ulong vstvec;
> +    target_ulong vsscratch;
> +    target_ulong vsepc;
> +    target_ulong vscause;
> +    target_ulong vstval;
> +    target_ulong vsatp;
> +
> +    target_ulong mtval2;
> +    target_ulong mtinst;
> +
>      target_ulong scounteren;
>      target_ulong mcounteren;
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index e99834856c..25c0fb258d 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -177,8 +177,14 @@
>  #define CSR_HSTATUS         0x600
>  #define CSR_HEDELEG         0x602
>  #define CSR_HIDELEG         0x603
> -#define CSR_HCOUNTERNEN     0x606
> +#define CSR_HIE             0x604
> +#define CSR_HCOUNTEREN      0x606
> +#define CSR_HTVAL           0x643
> +#define CSR_HIP             0x644
> +#define CSR_HTINST          0x64A
>  #define CSR_HGATP           0x680
> +#define CSR_HTIMEDELTA      0x605
> +#define CSR_HTIMEDELTAH     0x615
>
>  #if defined(TARGET_RISCV32)
>  #define HGATP_MODE           SATP32_MODE
> @@ -191,6 +197,20 @@
>  #define HGATP_PPN            SATP64_PPN
>  #endif
>
> +/* Virtual CSRs */
> +#define CSR_VSSTATUS        0x200
> +#define CSR_VSIE            0x204
> +#define CSR_VSTVEC          0x205
> +#define CSR_VSSCRATCH       0x240
> +#define CSR_VSEPC           0x241
> +#define CSR_VSCAUSE         0x242
> +#define CSR_VSTVAL          0x243
> +#define CSR_VSIP            0x244
> +#define CSR_VSATP           0x280
> +
> +#define CSR_MTINST          0x34a
> +#define CSR_MTVAL2          0x34b
> +
>  /* Physical Memory Protection */
>  #define CSR_PMPCFG0         0x3a0
>  #define CSR_PMPCFG1         0x3a1
> @@ -313,17 +333,6 @@
>  #define CSR_MHPMCOUNTER30H  0xb9e
>  #define CSR_MHPMCOUNTER31H  0xb9f
>
> -/* Legacy Hypervisor Trap Setup (priv v1.9.1) */
> -#define CSR_HIE             0x204
> -#define CSR_HTVEC           0x205
> -
> -/* Legacy Hypervisor Trap Handling (priv v1.9.1) */
> -#define CSR_HSCRATCH        0x240
> -#define CSR_HEPC            0x241
> -#define CSR_HCAUSE          0x242
> -#define CSR_HBADADDR        0x243
> -#define CSR_HIP             0x244
> -
>  /* Legacy Machine Protection and Translation (priv v1.9.1) */
>  #define CSR_MBASE           0x380
>  #define CSR_MBOUND          0x381
> @@ -400,7 +409,6 @@
>
>  /* hstatus CSR bits */
>  #define HSTATUS_SPRV         0x00000001
> -#define HSTATUS_STL          0x00000040
>  #define HSTATUS_SPV          0x00000080
>  #define HSTATUS_SP2P         0x00000100
>  #define HSTATUS_SP2V         0x00000200
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index 1a7947e019..6d606f0d90 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -130,6 +130,8 @@ static int csr_register_map[] = {
>      CSR_MCAUSE,
>      CSR_MTVAL,
>      CSR_MIP,
> +    CSR_MTINST,
> +    CSR_MTVAL2,
>      CSR_PMPCFG0,
>      CSR_PMPCFG1,
>      CSR_PMPCFG2,
> @@ -252,12 +254,11 @@ static int csr_register_map[] = {
>      CSR_HEDELEG,
>      CSR_HIDELEG,
>      CSR_HIE,
> -    CSR_HTVEC,
> -    CSR_HSCRATCH,
> -    CSR_HEPC,
> -    CSR_HCAUSE,
> -    CSR_HBADADDR,
> +    CSR_HCOUNTEREN,
> +    CSR_HTVAL,
>      CSR_HIP,
> +    CSR_HTINST,
> +    CSR_HGATP,
>      CSR_MBASE,
>      CSR_MBOUND,
>      CSR_MIBASE,

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 05/36] target/riscv: Add support for the new execption numbers
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (39 preceding siblings ...)
  2020-01-07 18:28 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Palmer Dabbelt
@ 2020-01-07 18:28 ` Palmer Dabbelt
  2020-01-07 18:28 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Palmer Dabbelt
                   ` (18 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-07 18:28 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:53 PST (-0800), Alistair Francis wrote:
> The v0.5 Hypervisor spec add new execption numbers, let's add support
> for those.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.c        |  8 ++++++++
>  target/riscv/cpu_bits.h   | 35 +++++++++++++++++++----------------
>  target/riscv/cpu_helper.c |  7 +++++--
>  target/riscv/csr.c        |  7 +++++--
>  4 files changed, 37 insertions(+), 20 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e521ebe2e1..d23d2cba64 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -67,6 +67,14 @@ const char * const riscv_excp_names[] = {
>      "load_page_fault",
>      "reserved",
>      "store_page_fault"
> +    "reserved",
> +    "reserved",
> +    "reserved",
> +    "reserved",
> +    "guest_exec_page_fault",
> +    "guest_load_page_fault",
> +    "reserved",
> +    "guest_store_page_fault"
>  };
>
>  const char * const riscv_intr_names[] = {
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 25c0fb258d..9ce73c36de 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -488,22 +488,25 @@
>  #define DEFAULT_RSTVEC      0x1000
>
>  /* Exception causes */
> -#define EXCP_NONE                          -1 /* sentinel value */
> -#define RISCV_EXCP_INST_ADDR_MIS           0x0
> -#define RISCV_EXCP_INST_ACCESS_FAULT       0x1
> -#define RISCV_EXCP_ILLEGAL_INST            0x2
> -#define RISCV_EXCP_BREAKPOINT              0x3
> -#define RISCV_EXCP_LOAD_ADDR_MIS           0x4
> -#define RISCV_EXCP_LOAD_ACCESS_FAULT       0x5
> -#define RISCV_EXCP_STORE_AMO_ADDR_MIS      0x6
> -#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT  0x7
> -#define RISCV_EXCP_U_ECALL                 0x8
> -#define RISCV_EXCP_S_ECALL                 0x9
> -#define RISCV_EXCP_H_ECALL                 0xa
> -#define RISCV_EXCP_M_ECALL                 0xb
> -#define RISCV_EXCP_INST_PAGE_FAULT         0xc /* since: priv-1.10.0 */
> -#define RISCV_EXCP_LOAD_PAGE_FAULT         0xd /* since: priv-1.10.0 */
> -#define RISCV_EXCP_STORE_PAGE_FAULT        0xf /* since: priv-1.10.0 */
> +#define EXCP_NONE                                -1 /* sentinel value */
> +#define RISCV_EXCP_INST_ADDR_MIS                 0x0
> +#define RISCV_EXCP_INST_ACCESS_FAULT             0x1
> +#define RISCV_EXCP_ILLEGAL_INST                  0x2
> +#define RISCV_EXCP_BREAKPOINT                    0x3
> +#define RISCV_EXCP_LOAD_ADDR_MIS                 0x4
> +#define RISCV_EXCP_LOAD_ACCESS_FAULT             0x5
> +#define RISCV_EXCP_STORE_AMO_ADDR_MIS            0x6
> +#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT        0x7
> +#define RISCV_EXCP_U_ECALL                       0x8
> +#define RISCV_EXCP_S_ECALL                      0x9
> +#define RISCV_EXCP_VS_ECALL                      0xa
> +#define RISCV_EXCP_M_ECALL                       0xb
> +#define RISCV_EXCP_INST_PAGE_FAULT               0xc /* since: priv-1.10.0 */
> +#define RISCV_EXCP_LOAD_PAGE_FAULT               0xd /* since: priv-1.10.0 */
> +#define RISCV_EXCP_STORE_PAGE_FAULT              0xf /* since: priv-1.10.0 */
> +#define RISCV_EXCP_INST_GUEST_PAGE_FAULT         0x14
> +#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT       0x15
> +#define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT  0x17
>
>  #define RISCV_EXCP_INT_FLAG                0x80000000
>  #define RISCV_EXCP_INT_MASK                0x7fffffff
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 0de3a468eb..c201919c54 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -526,7 +526,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      static const int ecall_cause_map[] = {
>          [PRV_U] = RISCV_EXCP_U_ECALL,
>          [PRV_S] = RISCV_EXCP_S_ECALL,
> -        [PRV_H] = RISCV_EXCP_H_ECALL,
> +        [PRV_H] = RISCV_EXCP_VS_ECALL,
>          [PRV_M] = RISCV_EXCP_M_ECALL
>      };
>
> @@ -542,6 +542,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          case RISCV_EXCP_INST_PAGE_FAULT:
>          case RISCV_EXCP_LOAD_PAGE_FAULT:
>          case RISCV_EXCP_STORE_PAGE_FAULT:
> +        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> +        case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
> +        case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
>              tval = env->badaddr;
>              break;
>          default:
> @@ -554,7 +557,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          }
>      }
>
> -    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 16 ?
> +    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 23 ?
>          (async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)");
>
>      if (env->priv <= PRV_S &&
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index da02f9f0b1..6a0a59edfd 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -242,11 +242,14 @@ static const target_ulong delegable_excps =
>      (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) |
>      (1ULL << (RISCV_EXCP_U_ECALL)) |
>      (1ULL << (RISCV_EXCP_S_ECALL)) |
> -    (1ULL << (RISCV_EXCP_H_ECALL)) |
> +    (1ULL << (RISCV_EXCP_VS_ECALL)) |
>      (1ULL << (RISCV_EXCP_M_ECALL)) |
>      (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) |
>      (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) |
> -    (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT));
> +    (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) |
> +    (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
> +    (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
> +    (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT));
>  static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE |
>      SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
>      SSTATUS_SUM | SSTATUS_SD;

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (40 preceding siblings ...)
  2020-01-07 18:28 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Palmer Dabbelt
@ 2020-01-07 18:28 ` Palmer Dabbelt
  2020-01-07 18:28 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Palmer Dabbelt
                   ` (17 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-07 18:28 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:56 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.c      |  6 +++---
>  target/riscv/cpu_bits.h | 12 ++++++------
>  2 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index d23d2cba64..e8ae07107e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -80,14 +80,14 @@ const char * const riscv_excp_names[] = {
>  const char * const riscv_intr_names[] = {
>      "u_software",
>      "s_software",
> -    "h_software",
> +    "vs_software",
>      "m_software",
>      "u_timer",
>      "s_timer",
> -    "h_timer",
> +    "vs_timer",
>      "m_timer",
>      "u_external",
> -    "s_external",
> +    "vs_external",
>      "h_external",
>      "m_external",
>      "reserved",
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 9ce73c36de..eeaa03c0f8 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -514,29 +514,29 @@
>  /* Interrupt causes */
>  #define IRQ_U_SOFT                         0
>  #define IRQ_S_SOFT                         1
> -#define IRQ_H_SOFT                         2  /* reserved */
> +#define IRQ_VS_SOFT                        2
>  #define IRQ_M_SOFT                         3
>  #define IRQ_U_TIMER                        4
>  #define IRQ_S_TIMER                        5
> -#define IRQ_H_TIMER                        6  /* reserved */
> +#define IRQ_VS_TIMER                       6
>  #define IRQ_M_TIMER                        7
>  #define IRQ_U_EXT                          8
>  #define IRQ_S_EXT                          9
> -#define IRQ_H_EXT                          10 /* reserved */
> +#define IRQ_VS_EXT                         10
>  #define IRQ_M_EXT                          11
>
>  /* mip masks */
>  #define MIP_USIP                           (1 << IRQ_U_SOFT)
>  #define MIP_SSIP                           (1 << IRQ_S_SOFT)
> -#define MIP_HSIP                           (1 << IRQ_H_SOFT)
> +#define MIP_VSSIP                          (1 << IRQ_VS_SOFT)
>  #define MIP_MSIP                           (1 << IRQ_M_SOFT)
>  #define MIP_UTIP                           (1 << IRQ_U_TIMER)
>  #define MIP_STIP                           (1 << IRQ_S_TIMER)
> -#define MIP_HTIP                           (1 << IRQ_H_TIMER)
> +#define MIP_VSTIP                          (1 << IRQ_VS_TIMER)
>  #define MIP_MTIP                           (1 << IRQ_M_TIMER)
>  #define MIP_UEIP                           (1 << IRQ_U_EXT)
>  #define MIP_SEIP                           (1 << IRQ_S_EXT)
> -#define MIP_HEIP                           (1 << IRQ_H_EXT)
> +#define MIP_VSEIP                          (1 << IRQ_VS_EXT)
>  #define MIP_MEIP                           (1 << IRQ_M_EXT)
>
>  /* sip masks */

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 07/36] target/riscv: Add the virtulisation mode
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (41 preceding siblings ...)
  2020-01-07 18:28 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Palmer Dabbelt
@ 2020-01-07 18:28 ` Palmer Dabbelt
  2020-01-08  0:06 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Palmer Dabbelt
                   ` (16 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-07 18:28 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:10:58 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.h        |  4 ++++
>  target/riscv/cpu_bits.h   |  3 +++
>  target/riscv/cpu_helper.c | 18 ++++++++++++++++++
>  3 files changed, 25 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index bab938103d..a73292cd20 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -117,6 +117,8 @@ struct CPURISCVState {
>
>  #ifndef CONFIG_USER_ONLY
>      target_ulong priv;
> +    /* This contains QEMU specific information about the virt state. */
> +    target_ulong virt;
>      target_ulong resetvec;
>
>      target_ulong mhartid;
> @@ -269,6 +271,8 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>  int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
>  bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
>  bool riscv_cpu_fp_enabled(CPURISCVState *env);
> +bool riscv_cpu_virt_enabled(CPURISCVState *env);
> +void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
>  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
>  hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>  void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index eeaa03c0f8..2cdb0de4fe 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -430,6 +430,9 @@
>  #define PRV_H 2 /* Reserved */
>  #define PRV_M 3
>
> +/* Virtulisation Register Fields */
> +#define VIRT_ONOFF          1
> +
>  /* RV32 satp CSR field masks */
>  #define SATP32_MODE         0x80000000
>  #define SATP32_ASID         0x7fc00000
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index c201919c54..046f3549cc 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -82,6 +82,24 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
>      return false;
>  }
>
> +bool riscv_cpu_virt_enabled(CPURISCVState *env)
> +{
> +    if (!riscv_has_ext(env, RVH)) {
> +        return false;
> +    }
> +
> +    return get_field(env->virt, VIRT_ONOFF);
> +}
> +
> +void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
> +{
> +    if (!riscv_has_ext(env, RVH)) {
> +        return;
> +    }
> +
> +    env->virt = set_field(env->virt, VIRT_ONOFF, enable);
> +}
> +
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
>  {
>      CPURISCVState *env = &cpu->env;

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (42 preceding siblings ...)
  2020-01-07 18:28 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Palmer Dabbelt
@ 2020-01-08  0:06 ` Palmer Dabbelt
  2020-01-08  0:07 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Palmer Dabbelt
                   ` (15 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  0:06 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:04 PST (-0800), Alistair Francis wrote:
> Update the CSR permission checking to work correctly when we are in
> HS-mode.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 6a0a59edfd..eebfc1823d 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -802,12 +802,22 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
>
>      /* check privileges and return -1 if check fails */
>  #if !defined(CONFIG_USER_ONLY)
> -    int csr_priv = get_field(csrno, 0x300);
> +    int effective_priv = env->priv;
>      int read_only = get_field(csrno, 0xC00) == 3;
> -    if ((!env->debugger) && (env->priv < csr_priv)) {
> -        return -1;
> +
> +    if (riscv_has_ext(env, RVH) &&
> +        env->priv == PRV_S &&
> +        !riscv_cpu_virt_enabled(env)) {
> +        /*
> +         * We are in S mode without virtualisation, therefore we are in HS Mode.
> +         * Add 1 to the effective privledge level to allow us to access the
> +         * Hypervisor CSRs.
> +         */
> +        effective_priv++;
>      }
> -    if (write_mask && read_only) {
> +
> +    if ((write_mask && read_only) ||
> +        (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) {
>          return -1;
>      }
>  #endif

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (43 preceding siblings ...)
  2020-01-08  0:06 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Palmer Dabbelt
@ 2020-01-08  0:07 ` Palmer Dabbelt
  2020-01-08  0:07 ` [PATCH v1 14/36] target/riscv: Add Hypervisor virtual CSRs accesses Palmer Dabbelt
                   ` (14 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  0:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:11 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 134 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index eebfc1823d..b582d78529 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -98,6 +98,20 @@ static int smode(CPURISCVState *env, int csrno)
>      return -!riscv_has_ext(env, RVS);
>  }
>
> +static int hmode(CPURISCVState *env, int csrno)
> +{
> +    if (riscv_has_ext(env, RVS) &&
> +        riscv_has_ext(env, RVH)) {
> +        /* Hypervisor extension is supported */
> +        if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
> +            env->priv == PRV_M) {
> +            return 0;
> +        }
> +    }
> +
> +    return -1;
> +}
> +
>  static int pmp(CPURISCVState *env, int csrno)
>  {
>      return -!riscv_feature(env, RISCV_FEATURE_PMP);
> @@ -226,8 +240,9 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
>
>  /* Machine constants */
>
> -#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
> -#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
> +#define M_MODE_INTERRUPTS  (MIP_MSIP | MIP_MTIP | MIP_MEIP)
> +#define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
> +#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
>
>  static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
>  static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
> @@ -257,6 +272,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
>      SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
>      SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
>  static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
> +static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
>
>  #if defined(TARGET_RISCV32)
>  static const char valid_vm_1_09[16] = {
> @@ -757,6 +773,112 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
>      return 0;
>  }
>
> +/* Hypervisor Extensions */
> +static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->hstatus;
> +    return 0;
> +}
> +
> +static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->hstatus = val;
> +    return 0;
> +}
> +
> +static int read_hedeleg(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->hedeleg;
> +    return 0;
> +}
> +
> +static int write_hedeleg(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->hedeleg = val;
> +    return 0;
> +}
> +
> +static int read_hideleg(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->hideleg;
> +    return 0;
> +}
> +
> +static int write_hideleg(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->hideleg = val;
> +    return 0;
> +}
> +
> +static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> +                   target_ulong new_value, target_ulong write_mask)
> +{
> +    int ret = rmw_mip(env, 0, ret_value, new_value,
> +                      write_mask & hip_writable_mask);
> +
> +    return ret;
> +}
> +
> +static int read_hie(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mie & VS_MODE_INTERRUPTS;
> +    return 0;
> +}
> +
> +static int write_hie(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & VS_MODE_INTERRUPTS);
> +    return write_mie(env, CSR_MIE, newval);
> +}
> +
> +static int read_hcounteren(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->hcounteren;
> +    return 0;
> +}
> +
> +static int write_hcounteren(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->hcounteren = val;
> +    return 0;
> +}
> +
> +static int read_htval(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->htval;
> +    return 0;
> +}
> +
> +static int write_htval(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->htval = val;
> +    return 0;
> +}
> +
> +static int read_htinst(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->htinst;
> +    return 0;
> +}
> +
> +static int write_htinst(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->htinst = val;
> +    return 0;
> +}
> +
> +static int read_hgatp(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->hgatp;
> +    return 0;
> +}
> +
> +static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->hgatp = val;
> +    return 0;
> +}
> +
>  /* Physical Memory Protection */
>  static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> @@ -960,6 +1082,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>      /* Supervisor Protection and Translation */
>      [CSR_SATP] =                { smode, read_satp,        write_satp        },
>
> +    [CSR_HSTATUS] =             { hmode,   read_hstatus,     write_hstatus    },
> +    [CSR_HEDELEG] =             { hmode,   read_hedeleg,     write_hedeleg    },
> +    [CSR_HIDELEG] =             { hmode,   read_hideleg,     write_hideleg    },
> +    [CSR_HIP] =                 { hmode,   NULL,     NULL,     rmw_hip        },
> +    [CSR_HIE] =                 { hmode,   read_hie,         write_hie        },
> +    [CSR_HCOUNTEREN] =          { hmode,   read_hcounteren,  write_hcounteren },
> +    [CSR_HTVAL] =               { hmode,   read_htval,       write_htval      },
> +    [CSR_HTINST] =              { hmode,   read_htinst,      write_htinst     },
> +    [CSR_HGATP] =               { hmode,   read_hgatp,       write_hgatp      },
> +
>      /* Physical Memory Protection */
>      [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
>      [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 14/36] target/riscv: Add Hypervisor virtual CSRs accesses
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (44 preceding siblings ...)
  2020-01-08  0:07 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Palmer Dabbelt
@ 2020-01-08  0:07 ` Palmer Dabbelt
  2020-01-08  1:30 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Palmer Dabbelt
                   ` (13 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  0:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:17 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index aaca1a6a0f..74e911af08 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -985,6 +985,30 @@ static int write_vsatp(CPURISCVState *env, int csrno, target_ulong val)
>      return 0;
>  }
>
> +static int read_mtval2(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mtval2;
> +    return 0;
> +}
> +
> +static int write_mtval2(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->mtval2 = val;
> +    return 0;
> +}
> +
> +static int read_mtinst(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mtinst;
> +    return 0;
> +}
> +
> +static int write_mtinst(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->mtinst = val;
> +    return 0;
> +}
> +
>  /* Physical Memory Protection */
>  static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> @@ -1208,6 +1232,9 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>      [CSR_VSTVAL] =              { hmode,   read_vstval,      write_vstval     },
>      [CSR_VSATP] =               { hmode,   read_vsatp,       write_vsatp      },
>
> +    [CSR_MTVAL2] =              { hmode,   read_mtval2,      write_mtval2     },
> +    [CSR_MTINST] =              { hmode,   read_mtinst,      write_mtinst     },
> +
>      /* Physical Memory Protection */
>      [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
>      [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (45 preceding siblings ...)
  2020-01-08  0:07 ` [PATCH v1 14/36] target/riscv: Add Hypervisor virtual CSRs accesses Palmer Dabbelt
@ 2020-01-08  1:30 ` Palmer Dabbelt
  2020-01-21 11:02   ` Alistair Francis
  2020-01-30 14:48   ` Palmer Dabbelt
  2020-01-08  2:07 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Palmer Dabbelt
                   ` (12 subsequent siblings)
  59 siblings, 2 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  1:30 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> To handle the new Hypervisor CSR register aliasing let's use pointers.

For some reason I thought we were making this explicit?  In other words,
requiring that all callers provide which privilege mode they're using when
accessing these CSRs, as opposed to swapping around pointers.  I don't actually
care that much, but IIRC when we were talking with the ARM guys at Plumbers
they were pretty adament that would end up being a much cleaner implementation
as they'd tried this way and later changed over.

> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.c        | 11 +++++++++--
>  target/riscv/cpu.h        |  9 ++++++++-
>  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
>  target/riscv/csr.c        | 20 ++++++++++----------
>  target/riscv/op_helper.c  | 14 +++++++-------
>  5 files changed, 49 insertions(+), 35 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index a07c5689b3..e61cf46a73 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
>  #ifndef CONFIG_USER_ONLY
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
>      if (riscv_has_ext(env, RVH)) {
>          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
>          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
> @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
>      mcc->parent_reset(cs);
>  #ifndef CONFIG_USER_ONLY
>      env->priv = PRV_M;
> -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
>      env->mcause = 0;
>      env->pc = env->resetvec;
>  #endif
> @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>  static void riscv_cpu_init(Object *obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(obj);
> +#ifndef CONFIG_USER_ONLY
> +    CPURISCVState *env = &cpu->env;
> +#endif
>
>      cpu_set_cpustate_pointers(cpu);
> +
> +#ifndef CONFIG_USER_ONLY
> +    env->mstatus = &env->mstatus_novirt;
> +#endif
>  }
>
>  static const VMStateDescription vmstate_riscv_cpu = {
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 21ae5a8b19..9dc8303c62 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -122,7 +122,7 @@ struct CPURISCVState {
>      target_ulong resetvec;
>
>      target_ulong mhartid;
> -    target_ulong mstatus;
> +    target_ulong *mstatus;
>
>      target_ulong mip;
>      uint32_t miclaim;
> @@ -145,6 +145,13 @@ struct CPURISCVState {
>      target_ulong mcause;
>      target_ulong mtval;  /* since: priv-1.10.0 */
>
> +    /* The following registers are the "real" versions that the pointer
> +     * versions point to. These should never be used unless you know what you
> +     * are doing. To access these use the pointer versions instead. This is
> +     * required to handle the Hypervisor register swapping.
> +     */
> +    target_ulong mstatus_novirt;
> +
>      /* Hypervisor CSRs */
>      target_ulong hstatus;
>      target_ulong hedeleg;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index b00f66824a..9684da7f7d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  #ifndef CONFIG_USER_ONLY
>  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>  {
> -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
> +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
>      target_ulong pending = env->mip & env->mie;
>      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
>      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
> @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
>  /* Return true is floating point support is currently enabled */
>  bool riscv_cpu_fp_enabled(CPURISCVState *env)
>  {
> -    if (env->mstatus & MSTATUS_FS) {
> +    if (*env->mstatus & MSTATUS_FS) {
>          return true;
>      }
>
> @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      int mode = mmu_idx;
>
>      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> -            mode = get_field(env->mstatus, MSTATUS_MPP);
> +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>          }
>      }
>
> @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>
>      hwaddr base;
>      int levels, ptidxbits, ptesize, vm, sum;
> -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
>
>      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> -        sum = get_field(env->mstatus, MSTATUS_SUM);
> +        sum = get_field(*env->mstatus, MSTATUS_SUM);
>          vm = get_field(env->satp, SATP_MODE);
>          switch (vm) {
>          case VM_1_10_SV32:
> @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          }
>      } else {
>          base = (hwaddr)(env->sptbr) << PGSHIFT;
> -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> -        vm = get_field(env->mstatus, MSTATUS_VM);
> +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> +        vm = get_field(*env->mstatus, MSTATUS_VM);
>          switch (vm) {
>          case VM_1_09_SV32:
>            levels = 2; ptidxbits = 10; ptesize = 4; break;
> @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
>
>      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> -            mode = get_field(env->mstatus, MSTATUS_MPP);
> +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>          }
>      }
>
> @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      if (env->priv <= PRV_S &&
>              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
>          /* handle the trap in S-mode */
> -        target_ulong s = env->mstatus;
> +        target_ulong s = *env->mstatus;
>          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
>          s = set_field(s, MSTATUS_SPP, env->priv);
>          s = set_field(s, MSTATUS_SIE, 0);
> -        env->mstatus = s;
> +        *env->mstatus = s;
>          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
>          env->sepc = env->pc;
>          env->sbadaddr = tval;
> @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          riscv_cpu_set_mode(env, PRV_S);
>      } else {
>          /* handle the trap in M-mode */
> -        target_ulong s = env->mstatus;
> +        target_ulong s = *env->mstatus;
>          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
>          s = set_field(s, MSTATUS_MPP, env->priv);
>          s = set_field(s, MSTATUS_MIE, 0);
> -        env->mstatus = s;
> +        *env->mstatus = s;
>          env->mcause = cause | ~(((target_ulong)-1) >> async);
>          env->mepc = env->pc;
>          env->mbadaddr = tval;
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 74e911af08..a4b598d49a 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
>      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>          return -1;
>      }
> -    env->mstatus |= MSTATUS_FS;
> +    *env->mstatus |= MSTATUS_FS;
>  #endif
>      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
>      return 0;
> @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
>      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>          return -1;
>      }
> -    env->mstatus |= MSTATUS_FS;
> +    *env->mstatus |= MSTATUS_FS;
>  #endif
>      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
>      return 0;
> @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
>      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>          return -1;
>      }
> -    env->mstatus |= MSTATUS_FS;
> +    *env->mstatus |= MSTATUS_FS;
>  #endif
>      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
>      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
>  /* Machine Trap Setup */
>  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> -    *val = env->mstatus;
> +    *val = *env->mstatus;
>      return 0;
>  }
>
> @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
>
>  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>  {
> -    target_ulong mstatus = env->mstatus;
> +    target_ulong mstatus = *env->mstatus;
>      target_ulong mask = 0;
>      int dirty;
>
> @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
>              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
>      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> -    env->mstatus = mstatus;
> +    *env->mstatus = mstatus;
>
>      return 0;
>  }
> @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
>  {
>      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> -    *val = env->mstatus & mask;
> +    *val = *env->mstatus & mask;
>      return 0;
>  }
>
> @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
>  {
>      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
>      return write_mstatus(env, CSR_MSTATUS, newval);
>  }
>
> @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
>      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
>          *val = 0;
>      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>              return -1;
>          } else {
>              *val = env->satp;
> @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
>          validate_vm(env, get_field(val, SATP_MODE)) &&
>          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
>      {
> -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>              return -1;
>          } else {
>              if((val ^ env->satp) & SATP_ASID) {
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 331cc36232..d150551bc9 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>      }
>
>      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> -        get_field(env->mstatus, MSTATUS_TSR)) {
> +        get_field(*env->mstatus, MSTATUS_TSR)) {
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>
> -    target_ulong mstatus = env->mstatus;
> +    target_ulong mstatus = *env->mstatus;
>      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
>      mstatus = set_field(mstatus,
>          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
>      riscv_cpu_set_mode(env, prev_priv);
> -    env->mstatus = mstatus;
> +    *env->mstatus = mstatus;
>
>      return retpc;
>  }
> @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>
> -    target_ulong mstatus = env->mstatus;
> +    target_ulong mstatus = *env->mstatus;
>      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
>      mstatus = set_field(mstatus,
>          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
>      riscv_cpu_set_mode(env, prev_priv);
> -    env->mstatus = mstatus;
> +    *env->mstatus = mstatus;
>
>      return retpc;
>  }
> @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
>
>      if (env->priv == PRV_S &&
>          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> -        get_field(env->mstatus, MSTATUS_TW)) {
> +        get_field(*env->mstatus, MSTATUS_TW)) {
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          cs->halted = 1;
> @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
>      if (!(env->priv >= PRV_S) ||
>          (env->priv == PRV_S &&
>           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> -         get_field(env->mstatus, MSTATUS_TVM))) {
> +         get_field(*env->mstatus, MSTATUS_TVM))) {
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          tlb_flush(cs);


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 16/36] target/riscv: Add virtual register swapping function
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (46 preceding siblings ...)
  2020-01-08  1:30 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Palmer Dabbelt
@ 2020-01-08  2:07 ` Palmer Dabbelt
  2020-01-08  2:07 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Palmer Dabbelt
                   ` (11 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  2:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:22 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.h        | 10 +++++++
>  target/riscv/cpu_bits.h   |  7 +++++
>  target/riscv/cpu_helper.c | 63 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 80 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 9dc8303c62..eb089fbdb6 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -125,6 +125,7 @@ struct CPURISCVState {
>      target_ulong *mstatus;
>
>      target_ulong mip;
> +
>      uint32_t miclaim;
>
>      target_ulong mie;
> @@ -173,6 +174,14 @@ struct CPURISCVState {
>      target_ulong mtval2;
>      target_ulong mtinst;
>
> +    /* HS Backup CSRs */
> +    target_ulong stvec_hs;
> +    target_ulong sscratch_hs;
> +    target_ulong sepc_hs;
> +    target_ulong scause_hs;
> +    target_ulong stval_hs;
> +    target_ulong satp_hs;
> +
>      target_ulong scounteren;
>      target_ulong mcounteren;
>
> @@ -303,6 +312,7 @@ void riscv_cpu_list(void);
>  #define cpu_mmu_index riscv_cpu_mmu_index
>
>  #ifndef CONFIG_USER_ONLY
> +void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
>  uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
>  #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index ad6479796c..a24654d137 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -553,4 +553,11 @@
>  #define SIP_STIP                           MIP_STIP
>  #define SIP_SEIP                           MIP_SEIP
>
> +/* MIE masks */
> +#define MIE_SEIE                           (1 << IRQ_S_EXT)
> +#define MIE_UEIE                           (1 << IRQ_U_EXT)
> +#define MIE_STIE                           (1 << IRQ_S_TIMER)
> +#define MIE_UTIE                           (1 << IRQ_U_TIMER)
> +#define MIE_SSIE                           (1 << IRQ_S_SOFT)
> +#define MIE_USIE                           (1 << IRQ_U_SOFT)
>  #endif
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 9684da7f7d..63439c9370 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -82,6 +82,69 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
>      return false;
>  }
>
> +void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
> +{
> +    target_ulong mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
> +                                MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE;
> +    bool current_virt = riscv_cpu_virt_enabled(env);
> +
> +    g_assert(riscv_has_ext(env, RVH));
> +
> +#if defined(TARGET_RISCV64)
> +    mstatus_mask |= MSTATUS64_UXL;
> +#endif
> +
> +    if (current_virt) {
> +        /* Current V=1 and we are about to change to V=0 */
> +        env->mstatus = &env->mstatus_novirt;
> +        *env->mstatus &= mstatus_mask;
> +        *env->mstatus |= env->vsstatus & ~mstatus_mask;
> +        /* Ensure that vsstatus only holds the correct bits */
> +        env->vsstatus &= mstatus_mask;
> +
> +        env->vstvec = env->stvec;
> +        env->stvec = env->stvec_hs;
> +
> +        env->vsscratch = env->sscratch;
> +        env->sscratch = env->sscratch_hs;
> +
> +        env->vsepc = env->sepc;
> +        env->sepc = env->sepc_hs;
> +
> +        env->vscause = env->scause;
> +        env->scause = env->scause_hs;
> +
> +        env->vstval = env->sbadaddr;
> +        env->sbadaddr = env->stval_hs;
> +
> +        env->vsatp = env->satp;
> +        env->satp = env->satp_hs;
> +    } else {
> +        /* Current V=0 and we are about to change to V=1 */
> +        env->mstatus = &env->vsstatus;
> +        *env->mstatus &= mstatus_mask;
> +        *env->mstatus |= env->mstatus_novirt & ~mstatus_mask;
> +
> +        env->stvec_hs = env->stvec;
> +        env->stvec = env->vstvec;
> +
> +        env->sscratch_hs = env->sscratch;
> +        env->sscratch = env->vsscratch;
> +
> +        env->sepc_hs = env->sepc;
> +        env->sepc = env->vsepc;
> +
> +        env->scause_hs = env->scause;
> +        env->scause = env->vscause;
> +
> +        env->stval_hs = env->sbadaddr;
> +        env->sbadaddr = env->vstval;
> +
> +        env->satp_hs = env->satp;
> +        env->satp = env->vsatp;
> +    }
> +}
> +
>  bool riscv_cpu_virt_enabled(CPURISCVState *env)
>  {
>      if (!riscv_has_ext(env, RVH)) {

Modulo that question about the concept of pointer swapping on the previous
patch:

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (47 preceding siblings ...)
  2020-01-08  2:07 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Palmer Dabbelt
@ 2020-01-08  2:07 ` Palmer Dabbelt
  2020-01-21 11:11   ` Alistair Francis
  2020-01-08 20:25 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Palmer Dabbelt
                   ` (10 subsequent siblings)
  59 siblings, 1 reply; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08  2:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:24 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index a4b598d49a..fc38c45a7e 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -449,6 +449,9 @@ static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
>  static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
>  {
>      env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
> +    if (riscv_has_ext(env, RVH)) {
> +        env->mideleg |= VS_MODE_INTERRUPTS;
> +    }
>      return 0;
>  }

Do you have any idea why?  The spec is explicit that this is the case, but I'm
surprised.

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (48 preceding siblings ...)
  2020-01-08  2:07 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Palmer Dabbelt
@ 2020-01-08 20:25 ` Palmer Dabbelt
  2020-01-09  0:49 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Palmer Dabbelt
                   ` (9 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-08 20:25 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:27 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 24 ++++++++++++++++++++----
>  1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index fc38c45a7e..54edfb280e 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -244,8 +244,10 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
>  #define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
>  #define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
>
> -static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
> -static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
> +static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
> +                                           VS_MODE_INTERRUPTS;
> +static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
> +                                     VS_MODE_INTERRUPTS;
>  static const target_ulong delegable_excps =
>      (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) |
>      (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) |
> @@ -631,13 +633,27 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
>
>  static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> -    *val = env->mie & env->mideleg;
> +    if (riscv_cpu_virt_enabled(env)) {
> +        /* Tell the guest the VS bits, shifted to the S bit locations */
> +        *val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
> +    } else {
> +        *val = env->mie & env->mideleg;
> +    }
>      return 0;
>  }
>
>  static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
>  {
> -    target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg);
> +    target_ulong newval;
> +
> +    if (riscv_cpu_virt_enabled(env)) {
> +        /* Shift the guests S bits to VS */
> +        newval = (env->mie & ~VS_MODE_INTERRUPTS) |
> +                 ((val << 1) & VS_MODE_INTERRUPTS);
> +    } else {
> +        newval = (env->mie & ~S_MODE_INTERRUPTS) | (val & S_MODE_INTERRUPTS);
> +    }
> +
>      return write_mie(env, CSR_MIE, newval);
>  }

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 19/36] target/riscv: Extend the SIP CSR to support virtulisation
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (49 preceding siblings ...)
  2020-01-08 20:25 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Palmer Dabbelt
@ 2020-01-09  0:49 ` Palmer Dabbelt
  2020-01-09  0:49 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Palmer Dabbelt
                   ` (8 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  0:49 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:30 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/csr.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 54edfb280e..d028dfb60b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -744,8 +744,19 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
>  static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
>                     target_ulong new_value, target_ulong write_mask)
>  {
> -    int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
> +    int ret;
> +
> +    if (riscv_cpu_virt_enabled(env)) {
> +        /* Shift the new values to line up with the VS bits */
> +        ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
> +                      (write_mask & sip_writable_mask) << 1 & env->mideleg);
> +        ret &= vsip_writable_mask;
> +        ret >>= 1;
> +    } else {
> +        ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
>                        write_mask & env->mideleg & sip_writable_mask);
> +    }
> +
>      *ret_value &= env->mideleg;
>      return ret;
>  }

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 26/36] target/riscv: Remove the hret instruction
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (50 preceding siblings ...)
  2020-01-09  0:49 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Palmer Dabbelt
@ 2020-01-09  0:49 ` Palmer Dabbelt
  2020-01-09  0:49 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Palmer Dabbelt
                   ` (7 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  0:49 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:48 PST (-0800), Alistair Francis wrote:
> The hret instruction does not exist in the new spec versions, so remove
> it from QEMU.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/insn32.decode                     | 1 -
>  target/riscv/insn_trans/trans_privileged.inc.c | 5 -----
>  2 files changed, 6 deletions(-)
>
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index cfd9ca6d2b..b883672e63 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -75,7 +75,6 @@ ecall       000000000000     00000 000 00000 1110011
>  ebreak      000000000001     00000 000 00000 1110011
>  uret        0000000    00010 00000 000 00000 1110011
>  sret        0001000    00010 00000 000 00000 1110011
> -hret        0010000    00010 00000 000 00000 1110011
>  mret        0011000    00010 00000 000 00000 1110011
>  wfi         0001000    00101 00000 000 00000 1110011
>  hfence_gvma 0110001    ..... ..... 000 00000 1110011 @hfence_gvma
> diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c
> index b9b5a89b52..76c2fad71c 100644
> --- a/target/riscv/insn_trans/trans_privileged.inc.c
> +++ b/target/riscv/insn_trans/trans_privileged.inc.c
> @@ -58,11 +58,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
>  #endif
>  }
>
> -static bool trans_hret(DisasContext *ctx, arg_hret *a)
> -{
> -    return false;
> -}
> -
>  static bool trans_mret(DisasContext *ctx, arg_mret *a)
>  {
>  #ifndef CONFIG_USER_ONLY

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (51 preceding siblings ...)
  2020-01-09  0:49 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Palmer Dabbelt
@ 2020-01-09  0:49 ` Palmer Dabbelt
  2020-01-09  2:33   ` Richard Henderson
  2020-01-10 23:21   ` Palmer Dabbelt
  2020-01-09  0:58 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Palmer Dabbelt
                   ` (6 subsequent siblings)
  59 siblings, 2 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  0:49 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:32 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_helper.c | 33 ++++++++++++++++++++++++++++-----
>  1 file changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 63439c9370..85eed5d885 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -37,13 +37,36 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  #ifndef CONFIG_USER_ONLY
>  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>  {
> +    target_ulong irqs;
> +
>      target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
>      target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
> -    target_ulong pending = env->mip & env->mie;
> -    target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
> -    target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
> -    target_ulong irqs = (pending & ~env->mideleg & -mie) |
> -                        (pending &  env->mideleg & -sie);
> +    target_ulong hs_mstatus_sie = get_field(env->mstatus_novirt, MSTATUS_SIE);
> +
> +    target_ulong pending = env->mip & env->mie &
> +                               ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> +    target_ulong vspending = (env->mip & env->mie &
> +                              (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) >> 1;
> +
> +    target_ulong mie    = env->priv < PRV_M ||
> +                          (env->priv == PRV_M && mstatus_mie);
> +    target_ulong sie    = env->priv < PRV_S ||
> +                          (env->priv == PRV_S && mstatus_sie);
> +    target_ulong hs_sie = env->priv < PRV_S ||
> +                          (env->priv == PRV_S && hs_mstatus_sie);
> +
> +    if (riscv_cpu_virt_enabled(env)) {
> +        target_ulong pending_hs_irq = pending & -hs_sie;
> +
> +        if (pending_hs_irq) {
> +            riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
> +            return ctz64(pending_hs_irq);
> +        }
> +
> +        pending = vspending;
> +    }
> +
> +    irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);

Isn't "-unsigned" implementation defined?  I can't get GCC to throw a warning
and it was already there, so maybe I'm just wrong?

>
>      if (irqs) {
>          return ctz64(irqs); /* since non-zero */

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (52 preceding siblings ...)
  2020-01-09  0:49 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Palmer Dabbelt
@ 2020-01-09  0:58 ` Palmer Dabbelt
  2020-01-09  1:41 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Palmer Dabbelt
                   ` (5 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  0:58 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:56 PST (-0800), Alistair Francis wrote:
> mark_fs_dirty() is the only place in translate.c that uses the
> virt_enabled bool. Let's respect the contents of MSTATUS.MPRV and
> HSTATUS.SPRV when setting the bool as this is used for performing
> floating point operations when V=0.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/translate.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 1d879b34db..dd93e12b45 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -748,7 +748,21 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
>      ctx->priv_ver = env->priv_ver;
>  #if !defined(CONFIG_USER_ONLY)
> -    ctx->virt_enabled = riscv_cpu_virt_enabled(env);
> +    if (riscv_has_ext(env, RVH)) {
> +        ctx->virt_enabled = riscv_cpu_virt_enabled(env);
> +        if (env->priv_ver == PRV_M &&
> +            get_field(*env->mstatus, MSTATUS_MPRV) &&
> +            get_field(*env->mstatus, MSTATUS_MPV)) {
> +            ctx->virt_enabled = true;
> +        } else if (env->priv == PRV_S &&
> +                   !riscv_cpu_virt_enabled(env) &&
> +                   get_field(env->hstatus, HSTATUS_SPRV) &&
> +                   get_field(env->hstatus, HSTATUS_SPV)) {
> +            ctx->virt_enabled = true;
> +        }
> +    } else {
> +        ctx->virt_enabled = false;
> +    }
>  #else
>      ctx->virt_enabled = false;
>  #endif

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 30/36] target/riscv: Allow specifying MMU stage
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (53 preceding siblings ...)
  2020-01-09  0:58 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Palmer Dabbelt
@ 2020-01-09  1:41 ` Palmer Dabbelt
  2020-01-09  2:01 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Palmer Dabbelt
                   ` (4 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  1:41 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:11:59 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_helper.c | 39 ++++++++++++++++++++++++++++++---------
>  1 file changed, 30 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 2040fc0208..8b234790a7 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -279,10 +279,19 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
>   *
>   * Adapted from Spike's mmu_t::translate and mmu_t::walk
>   *
> + * @env: CPURISCVState
> + * @physical: This will be set to the calculated physical address
> + * @prot: The returned protection attributes
> + * @addr: The virtual address to be translated
> + * @access_type: The type of MMU access
> + * @mmu_idx: Indicates current privilege level
> + * @first_stage: Are we in first stage translation?
> + *               Second stage is used for hypervisor guest translation
>   */
>  static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>                                  int *prot, target_ulong addr,
> -                                int access_type, int mmu_idx)
> +                                int access_type, int mmu_idx,
> +                                bool first_stage)
>  {
>      /* NOTE: the env->pc value visible here will not be
>       * correct, but the value visible to the exception handler
> @@ -485,13 +494,23 @@ restart:
>  }
>
>  static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> -                                MMUAccessType access_type, bool pmp_violation)
> +                                MMUAccessType access_type, bool pmp_violation,
> +                                bool first_stage)
>  {
>      CPUState *cs = env_cpu(env);
> -    int page_fault_exceptions =
> -        (env->priv_ver >= PRIV_VERSION_1_10_0) &&
> -        get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
> -        !pmp_violation;
> +    int page_fault_exceptions;
> +    if (first_stage) {
> +        page_fault_exceptions =
> +            (env->priv_ver >= PRIV_VERSION_1_10_0) &&
> +            get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
> +            !pmp_violation;
> +        riscv_cpu_set_force_hs_excep(env, 0);
> +    } else {
> +        page_fault_exceptions =
> +            get_field(env->hgatp, HGATP_MODE) != VM_1_10_MBARE &&
> +            !pmp_violation;
> +        riscv_cpu_set_force_hs_excep(env, 1);
> +    }
>      switch (access_type) {
>      case MMU_INST_FETCH:
>          cs->exception_index = page_fault_exceptions ?
> @@ -518,7 +537,8 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
>      int prot;
>      int mmu_idx = cpu_mmu_index(&cpu->env, false);
>
> -    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx)) {
> +    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx,
> +                             true)) {
>          return -1;
>      }
>      return phys_addr;
> @@ -583,7 +603,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
>                    __func__, address, access_type, mmu_idx);
>
> -    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
> +    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx,
> +                               true);
>
>      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>          if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> @@ -610,7 +631,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      } else if (probe) {
>          return false;
>      } else {
> -        raise_mmu_exception(env, address, access_type, pmp_violation);
> +        raise_mmu_exception(env, address, access_type, pmp_violation, true);
>          riscv_raise_exception(env, cs->exception_index, retaddr);
>      }
>  #else

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 31/36] target/riscv: Implement second stage MMU
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (54 preceding siblings ...)
  2020-01-09  1:41 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Palmer Dabbelt
@ 2020-01-09  2:01 ` Palmer Dabbelt
  2020-01-09  2:29 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Palmer Dabbelt
                   ` (3 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  2:01 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:12:01 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.h        |   1 +
>  target/riscv/cpu_helper.c | 193 ++++++++++++++++++++++++++++++++++----
>  2 files changed, 175 insertions(+), 19 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index eb089fbdb6..b411a1f900 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -104,6 +104,7 @@ struct CPURISCVState {
>      target_ulong frm;
>
>      target_ulong badaddr;
> +    target_ulong guest_phys_fault_addr;
>
>      target_ulong priv_ver;
>      target_ulong misa;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 8b234790a7..8667e5ffce 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -287,11 +287,12 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
>   * @mmu_idx: Indicates current privilege level
>   * @first_stage: Are we in first stage translation?
>   *               Second stage is used for hypervisor guest translation
> + * @two_stage: Are we going to perform two stage translation
>   */
>  static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>                                  int *prot, target_ulong addr,
>                                  int access_type, int mmu_idx,
> -                                bool first_stage)
> +                                bool first_stage, bool two_stage)
>  {
>      /* NOTE: the env->pc value visible here will not be
>       * correct, but the value visible to the exception handler
> @@ -299,13 +300,40 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      MemTxResult res;
>      MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
>      int mode = mmu_idx;
> +    bool use_background = false;
>
> +    /*
> +     * Check if we should use the background registers for the two
> +     * stage translation. We don't need to check if we actually need
> +     * two stage translation as that happened before this function
> +     * was called. Background registers will be used if the guest has
> +     * forced a two stage translation to be on (in HS or M mode).
> +     */
>      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>          if (get_field(*env->mstatus, MSTATUS_MPRV)) {
>              mode = get_field(*env->mstatus, MSTATUS_MPP);
> +
> +            if (riscv_has_ext(env, RVH) &&
> +                get_field(*env->mstatus, MSTATUS_MPV)) {
> +                use_background = true;
> +            }
> +        }
> +    }
> +
> +    if (mode == PRV_S && access_type != MMU_INST_FETCH &&
> +        riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
> +        if (get_field(env->hstatus, HSTATUS_SPRV)) {
> +            mode = get_field(*env->mstatus, SSTATUS_SPP);
> +            use_background = true;
>          }
>      }
>
> +    if (first_stage == false) {
> +        /* We are in stage 2 translation, this is similar to stage 1. */
> +        /* Stage 2 is always taken as U-mode */
> +        mode = PRV_U;
> +    }
> +
>      if (mode == PRV_M || !riscv_feature(env, RISCV_FEATURE_MMU)) {
>          *physical = addr;
>          *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> @@ -315,13 +343,30 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      *prot = 0;
>
>      hwaddr base;
> -    int levels, ptidxbits, ptesize, vm, sum;
> -    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> +    int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
> +
> +    if (first_stage == true) {
> +        mxr = get_field(*env->mstatus, MSTATUS_MXR);
> +    } else {
> +        mxr = get_field(env->vsstatus, MSTATUS_MXR);
> +    }
>
>      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> -        base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> +        if (first_stage == true) {
> +            if (use_background) {
> +                base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
> +                vm = get_field(env->vsatp, SATP_MODE);
> +            } else {
> +                base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> +                vm = get_field(env->satp, SATP_MODE);
> +            }
> +            widened = 0;
> +        } else {
> +            base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
> +            vm = get_field(env->hgatp, HGATP_MODE);
> +            widened = 2;
> +        }
>          sum = get_field(*env->mstatus, MSTATUS_SUM);
> -        vm = get_field(env->satp, SATP_MODE);
>          switch (vm) {
>          case VM_1_10_SV32:
>            levels = 2; ptidxbits = 10; ptesize = 4; break;
> @@ -339,6 +384,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>            g_assert_not_reached();
>          }
>      } else {
> +        widened = 0;
>          base = (hwaddr)(env->sptbr) << PGSHIFT;
>          sum = !get_field(*env->mstatus, MSTATUS_PUM);
>          vm = get_field(*env->mstatus, MSTATUS_VM);
> @@ -359,9 +405,16 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      }
>
>      CPUState *cs = env_cpu(env);
> -    int va_bits = PGSHIFT + levels * ptidxbits;
> -    target_ulong mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
> -    target_ulong masked_msbs = (addr >> (va_bits - 1)) & mask;
> +    int va_bits = PGSHIFT + levels * ptidxbits + widened;
> +    target_ulong mask, masked_msbs;
> +
> +    if (TARGET_LONG_BITS > (va_bits - 1)) {
> +        mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
> +    } else {
> +        mask = 0;
> +    }
> +    masked_msbs = (addr >> (va_bits - 1)) & mask;
> +
>      if (masked_msbs != 0 && masked_msbs != mask) {
>          return TRANSLATE_FAIL;
>      }
> @@ -373,11 +426,29 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>  restart:
>  #endif
>      for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
> -        target_ulong idx = (addr >> (PGSHIFT + ptshift)) &
> +        target_ulong idx;
> +        if (i == 0) {
> +            idx = (addr >> (PGSHIFT + ptshift)) &
> +                           ((1 << (ptidxbits + widened)) - 1);
> +        } else {
> +            idx = (addr >> (PGSHIFT + ptshift)) &
>                             ((1 << ptidxbits) - 1);
> +        }
>
>          /* check that physical address of PTE is legal */
> -        hwaddr pte_addr = base + idx * ptesize;
> +        hwaddr pte_addr;
> +
> +        if (two_stage && first_stage) {
> +            hwaddr vbase;
> +
> +            /* Do the second stage translation on the base PTE address. */
> +            get_physical_address(env, &vbase, prot, base, access_type,
> +                                 mmu_idx, false, true);
> +
> +            pte_addr = vbase + idx * ptesize;
> +        } else {
> +            pte_addr = base + idx * ptesize;
> +        }
>
>          if (riscv_feature(env, RISCV_FEATURE_PMP) &&
>              !pmp_hart_has_privs(env, pte_addr, sizeof(target_ulong),
> @@ -474,7 +545,12 @@ restart:
>              /* for superpage mappings, make a fake leaf PTE for the TLB's
>                 benefit. */
>              target_ulong vpn = addr >> PGSHIFT;
> -            *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
> +            if (i == 0) {
> +                *physical = (ppn | (vpn & ((1L << (ptshift + widened)) - 1))) <<
> +                             PGSHIFT;
> +            } else {
> +                *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
> +            }
>
>              /* set permissions on the TLB entry */
>              if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
> @@ -533,14 +609,23 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
>  hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
>  {
>      RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
>      hwaddr phys_addr;
>      int prot;
>      int mmu_idx = cpu_mmu_index(&cpu->env, false);
>
> -    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx,
> -                             true)) {
> +    if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx,
> +                             true, riscv_cpu_virt_enabled(env))) {
>          return -1;
>      }
> +
> +    if (riscv_cpu_virt_enabled(env)) {
> +        if (get_physical_address(env, &phys_addr, &prot, phys_addr,
> +                                 0, mmu_idx, false, true)) {
> +            return -1;
> +        }
> +    }
> +
>      return phys_addr;
>  }
>
> @@ -594,17 +679,37 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      RISCVCPU *cpu = RISCV_CPU(cs);
>      CPURISCVState *env = &cpu->env;
>  #ifndef CONFIG_USER_ONLY
> +    vaddr im_address;
>      hwaddr pa = 0;
>      int prot;
>      bool pmp_violation = false;
> +    bool m_mode_two_stage = false;
> +    bool hs_mode_two_stage = false;
> +    bool first_stage_error = true;
>      int ret = TRANSLATE_FAIL;
>      int mode = mmu_idx;
>
> +    env->guest_phys_fault_addr = 0;
> +
>      qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
>                    __func__, address, access_type, mmu_idx);
>
> -    ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx,
> -                               true);
> +    /*
> +     * Determine if we are in M mode and MPRV is set or in HS mode and SPRV is
> +     * set and we want to access a virtulisation address.
> +     */
> +    if (riscv_has_ext(env, RVH)) {
> +        m_mode_two_stage = env->priv == PRV_M &&
> +                           access_type != MMU_INST_FETCH &&
> +                           get_field(*env->mstatus, MSTATUS_MPRV) &&
> +                           get_field(*env->mstatus, MSTATUS_MPV);
> +
> +        hs_mode_two_stage = env->priv == PRV_S &&
> +                            !riscv_cpu_virt_enabled(env) &&
> +                            access_type != MMU_INST_FETCH &&
> +                            get_field(env->hstatus, HSTATUS_SPRV) &&
> +                            get_field(env->hstatus, HSTATUS_SPV);
> +    }
>
>      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>          if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> @@ -612,9 +717,55 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>          }
>      }
>
> -    qemu_log_mask(CPU_LOG_MMU,
> -                  "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
> -                  " prot %d\n", __func__, address, ret, pa, prot);
> +    if (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) {
> +        /* Two stage lookup */
> +        ret = get_physical_address(env, &pa, &prot, address, access_type,
> +                                   mmu_idx, true, true);
> +
> +        qemu_log_mask(CPU_LOG_MMU,
> +                      "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
> +                      TARGET_FMT_plx " prot %d\n",
> +                      __func__, address, ret, pa, prot);
> +
> +        if (ret != TRANSLATE_FAIL) {
> +            /* Second stage lookup */
> +            im_address = pa;
> +
> +            ret = get_physical_address(env, &pa, &prot, im_address,
> +                                       access_type, mmu_idx, false, true);
> +
> +            qemu_log_mask(CPU_LOG_MMU,
> +                    "%s 2nd-stage address=%" VADDR_PRIx " ret %d physical "
> +                    TARGET_FMT_plx " prot %d\n",
> +                    __func__, im_address, ret, pa, prot);
> +
> +            if (riscv_feature(env, RISCV_FEATURE_PMP) &&
> +                (ret == TRANSLATE_SUCCESS) &&
> +                !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
> +                ret = TRANSLATE_PMP_FAIL;
> +            }
> +
> +            if (ret != TRANSLATE_SUCCESS) {
> +                /*
> +                 * Guest physical address translation failed, this is a HS
> +                 * level exception
> +                 */
> +                first_stage_error = false;
> +                env->guest_phys_fault_addr = (im_address |
> +                                              (address &
> +                                               (TARGET_PAGE_SIZE - 1))) >> 2;
> +            }
> +        }
> +    } else {
> +        /* Single stage lookup */
> +        ret = get_physical_address(env, &pa, &prot, address, access_type,
> +                                   mmu_idx, true, false);
> +
> +        qemu_log_mask(CPU_LOG_MMU,
> +                      "%s address=%" VADDR_PRIx " ret %d physical "
> +                      TARGET_FMT_plx " prot %d\n",
> +                      __func__, address, ret, pa, prot);
> +    }
>
>      if (riscv_feature(env, RISCV_FEATURE_PMP) &&
>          (ret == TRANSLATE_SUCCESS) &&
> @@ -624,6 +775,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      if (ret == TRANSLATE_PMP_FAIL) {
>          pmp_violation = true;
>      }
> +
>      if (ret == TRANSLATE_SUCCESS) {
>          tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
>                       prot, mmu_idx, TARGET_PAGE_SIZE);
> @@ -631,9 +783,12 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      } else if (probe) {
>          return false;
>      } else {
> -        raise_mmu_exception(env, address, access_type, pmp_violation, true);
> +        raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error);
>          riscv_raise_exception(env, cs->exception_index, retaddr);
>      }
> +
> +    return true;
> +
>  #else
>      switch (access_type) {
>      case MMU_INST_FETCH:

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (55 preceding siblings ...)
  2020-01-09  2:01 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Palmer Dabbelt
@ 2020-01-09  2:29 ` Palmer Dabbelt
  2020-01-09  2:29 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Palmer Dabbelt
                   ` (2 subsequent siblings)
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  2:29 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:12:04 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_helper.c | 24 ++++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 8667e5ffce..43c6629014 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -589,16 +589,28 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
>      }
>      switch (access_type) {
>      case MMU_INST_FETCH:
> -        cs->exception_index = page_fault_exceptions ?
> -            RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
> +        if (riscv_cpu_virt_enabled(env) && !first_stage) {
> +            cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
> +        } else {
> +            cs->exception_index = page_fault_exceptions ?
> +                RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
> +        }
>          break;
>      case MMU_DATA_LOAD:
> -        cs->exception_index = page_fault_exceptions ?
> -            RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
> +        if (riscv_cpu_virt_enabled(env) && !first_stage) {
> +            cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
> +        } else {
> +            cs->exception_index = page_fault_exceptions ?
> +                RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
> +        }
>          break;
>      case MMU_DATA_STORE:
> -        cs->exception_index = page_fault_exceptions ?
> -            RISCV_EXCP_STORE_PAGE_FAULT : RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
> +        if (riscv_cpu_virt_enabled(env) && !first_stage) {
> +            cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
> +        } else {
> +            cs->exception_index = page_fault_exceptions ?
> +                RISCV_EXCP_STORE_PAGE_FAULT : RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
> +        }
>          break;
>      default:
>          g_assert_not_reached();

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (56 preceding siblings ...)
  2020-01-09  2:29 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Palmer Dabbelt
@ 2020-01-09  2:29 ` Palmer Dabbelt
  2020-01-09  2:29 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Palmer Dabbelt
  2020-01-09  2:36 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Palmer Dabbelt
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  2:29 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:12:06 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_helper.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 43c6629014..aa033b8590 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -841,6 +841,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
>      target_ulong deleg = async ? env->mideleg : env->medeleg;
>      target_ulong tval = 0;
> +    target_ulong htval = 0;
> +    target_ulong mtval2 = 0;
>
>      if (!async) {
>          /* set tval to badaddr for traps with address information */
> @@ -900,6 +902,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>                  env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
>                                           riscv_cpu_virt_enabled(env));
>
> +                htval = env->guest_phys_fault_addr;
> +
>                  riscv_cpu_set_virt_enabled(env, 0);
>                  riscv_cpu_set_force_hs_excep(env, 0);
>              } else {
> @@ -910,6 +914,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>                                           get_field(*env->mstatus, SSTATUS_SPP));
>                  env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
>                                           riscv_cpu_virt_enabled(env));
> +
> +                htval = env->guest_phys_fault_addr;
>              }
>          }
>
> @@ -922,6 +928,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
>          env->sepc = env->pc;
>          env->sbadaddr = tval;
> +        env->htval = htval;
>          env->pc = (env->stvec >> 2 << 2) +
>              ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
>          riscv_cpu_set_mode(env, PRV_S);
> @@ -936,6 +943,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>              *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
>                                        riscv_cpu_force_hs_excep_enabled(env));
>
> +            mtval2 = env->guest_phys_fault_addr;
> +
>              /* Trapping to M mode, virt is disabled */
>              riscv_cpu_set_virt_enabled(env, 0);
>          }
> @@ -949,6 +958,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          env->mcause = cause | ~(((target_ulong)-1) >> async);
>          env->mepc = env->pc;
>          env->mbadaddr = tval;
> +        env->mtval2 = mtval2;
>          env->pc = (env->mtvec >> 2 << 2) +
>              ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
>          riscv_cpu_set_mode(env, PRV_M);

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (57 preceding siblings ...)
  2020-01-09  2:29 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Palmer Dabbelt
@ 2020-01-09  2:29 ` Palmer Dabbelt
  2020-01-09  2:36 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Palmer Dabbelt
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  2:29 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:12:09 PST (-0800), Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu.c        |  6 ++++++
>  target/riscv/cpu.h        |  7 +++++++
>  target/riscv/cpu_bits.h   |  3 +++
>  target/riscv/cpu_helper.c |  7 +++++++
>  target/riscv/csr.c        | 25 +++++++++++++++++++++++++
>  target/riscv/op_helper.c  |  4 ++++
>  6 files changed, 52 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e61cf46a73..ac8f53a49d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -237,6 +237,9 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
>  #ifndef CONFIG_USER_ONLY
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
>      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
> +#ifdef TARGET_RISCV32
> +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", *env->mstatush);
> +#endif
>      if (riscv_has_ext(env, RVH)) {
>          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
>          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
> @@ -473,6 +476,9 @@ static void riscv_cpu_init(Object *obj)
>
>  #ifndef CONFIG_USER_ONLY
>      env->mstatus = &env->mstatus_novirt;
> +# ifdef TARGET_RISCV32
> +    env->mstatush = &env->mstatush_novirt;
> +# endif
>  #endif
>  }
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index b411a1f900..84a07971dc 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -127,6 +127,10 @@ struct CPURISCVState {
>
>      target_ulong mip;
>
> +#ifdef TARGET_RISCV32
> +    target_ulong *mstatush;
> +#endif
> +
>      uint32_t miclaim;
>
>      target_ulong mie;
> @@ -153,6 +157,9 @@ struct CPURISCVState {
>       * required to handle the Hypervisor register swapping.
>       */
>      target_ulong mstatus_novirt;
> +#ifdef TARGET_RISCV32
> +    target_ulong mstatush_novirt;
> +#endif
>
>      /* Hypervisor CSRs */
>      target_ulong hstatus;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index a24654d137..049032f2ae 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -135,6 +135,9 @@
>  #define CSR_MTVEC           0x305
>  #define CSR_MCOUNTEREN      0x306
>
> +/* 32-bit only */
> +#define CSR_MSTATUSH        0x310
> +
>  /* Legacy Counter Setup (priv v1.9.1) */
>  /* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */
>  #define CSR_MUCOUNTEREN     0x320
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index aa033b8590..c2ad0bbce7 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -938,10 +938,17 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>              if (riscv_cpu_virt_enabled(env)) {
>                  riscv_cpu_swap_hypervisor_regs(env);
>              }
> +#ifdef TARGET_RISCV32
> +            *env->mstatush = set_field(*env->mstatush, MSTATUS_MPV,
> +                                       riscv_cpu_virt_enabled(env));
> +            *env->mstatush = set_field(*env->mstatush, MSTATUS_MTL,
> +                                       riscv_cpu_force_hs_excep_enabled(env));
> +#else
>              *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
>                                        riscv_cpu_virt_enabled(env));
>              *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
>                                        riscv_cpu_force_hs_excep_enabled(env));
> +#endif
>
>              mtval2 = env->guest_phys_fault_addr;
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index d028dfb60b..b28058f9d5 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -372,6 +372,27 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>      return 0;
>  }
>
> +#ifdef TARGET_RISCV32
> +static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = *env->mstatush;
> +    return 0;
> +}
> +
> +static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    if ((val ^ *env->mstatush) & (MSTATUS_MPV)) {
> +        tlb_flush(env_cpu(env));
> +    }
> +
> +    val &= MSTATUS_MPV | MSTATUS_MTL;
> +
> +    *env->mstatush = val;
> +
> +    return 0;
> +}
> +#endif
> +
>  static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
>  {
>      *val = env->misa;
> @@ -1215,6 +1236,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>      [CSR_MTVEC] =               { any,  read_mtvec,       write_mtvec       },
>      [CSR_MCOUNTEREN] =          { any,  read_mcounteren,  write_mcounteren  },
>
> +#if defined(TARGET_RISCV32)
> +    [CSR_MSTATUSH] =            { any,  read_mstatush,    write_mstatush    },
> +#endif
> +
>      /* Legacy Counter Setup (priv v1.9.1) */
>      [CSR_MUCOUNTEREN] =         { any,  read_mucounteren, write_mucounteren },
>      [CSR_MSCOUNTEREN] =         { any,  read_mscounteren, write_mscounteren },
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index e5128570e6..a0a631d722 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -153,7 +153,11 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          get_field(mstatus, MSTATUS_MPIE));
>      mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
>      mstatus = set_field(mstatus, MSTATUS_MPP, 0);
> +#ifdef TARGET_RISCV32
> +    *env->mstatush = set_field(*env->mstatush, MSTATUS_MPV, 0);
> +#else
>      mstatus = set_field(mstatus, MSTATUS_MPV, 0);
> +#endif
>      *env->mstatus = mstatus;
>      riscv_cpu_set_mode(env, prev_priv);

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting
  2020-01-09  0:49 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Palmer Dabbelt
@ 2020-01-09  2:33   ` Richard Henderson
  2020-01-10 23:21   ` Palmer Dabbelt
  1 sibling, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2020-01-09  2:33 UTC (permalink / raw)
  To: Palmer Dabbelt, Alistair Francis; +Cc: alistair23, qemu-riscv, qemu-devel

On 1/9/20 11:49 AM, Palmer Dabbelt wrote:
>> +    irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);
> 
> Isn't "-unsigned" implementation defined?  I can't get GCC to throw a warning
> and it was already there, so maybe I'm just wrong?

(1) You're confusing implementation defined with undefined, and unsigned
arithmetic is the former not the latter.

(2) There is no such thing as ones-compliment or sign-magnitude integer
hardware anymore, so for this case "implementation defined" is in fact universal.

(3) We build with -fwrapv, so we're explicitly asking for sane behaviour from
our signed types as well.


r~


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro
  2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
                   ` (58 preceding siblings ...)
  2020-01-09  2:29 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Palmer Dabbelt
@ 2020-01-09  2:36 ` Palmer Dabbelt
  59 siblings, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-09  2:36 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, qemu-riscv, Alistair Francis, alistair23

On Mon, 09 Dec 2019 10:12:12 PST (-0800), Alistair Francis wrote:
> Add a helper macro MSTATUS_MPV_ISSET() which will determine if the
> MSTATUS_MPV bit is set for both 32-bit and 64-bit RISC-V.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_bits.h   | 11 +++++++++++
>  target/riscv/cpu_helper.c |  4 ++--
>  target/riscv/op_helper.c  |  2 +-
>  target/riscv/translate.c  |  2 +-
>  4 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 049032f2ae..dd012a514e 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -363,8 +363,19 @@
>  #define MSTATUS_TVM         0x00100000 /* since: priv-1.10 */
>  #define MSTATUS_TW          0x20000000 /* since: priv-1.10 */
>  #define MSTATUS_TSR         0x40000000 /* since: priv-1.10 */
> +#if defined(TARGET_RISCV64)
>  #define MSTATUS_MTL         0x4000000000ULL
>  #define MSTATUS_MPV         0x8000000000ULL
> +#elif defined(TARGET_RISCV32)
> +#define MSTATUS_MTL         0x00000040
> +#define MSTATUS_MPV         0x00000080
> +#endif
> +
> +#ifdef TARGET_RISCV32
> +# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatush, MSTATUS_MPV)
> +#else
> +# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatus, MSTATUS_MPV)
> +#endif
>
>  #define MSTATUS64_UXL       0x0000000300000000ULL
>  #define MSTATUS64_SXL       0x0000000C00000000ULL
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index c2ad0bbce7..7166e6199e 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -314,7 +314,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>              mode = get_field(*env->mstatus, MSTATUS_MPP);
>
>              if (riscv_has_ext(env, RVH) &&
> -                get_field(*env->mstatus, MSTATUS_MPV)) {
> +                MSTATUS_MPV_ISSET(env)) {
>                  use_background = true;
>              }
>          }
> @@ -714,7 +714,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>          m_mode_two_stage = env->priv == PRV_M &&
>                             access_type != MMU_INST_FETCH &&
>                             get_field(*env->mstatus, MSTATUS_MPRV) &&
> -                           get_field(*env->mstatus, MSTATUS_MPV);
> +                           MSTATUS_MPV_ISSET(env);
>
>          hs_mode_two_stage = env->priv == PRV_S &&
>                              !riscv_cpu_virt_enabled(env) &&
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index a0a631d722..b0b9890a15 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -146,7 +146,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>
>      target_ulong mstatus = *env->mstatus;
>      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> -    target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
> +    target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
>      mstatus = set_field(mstatus,
>          env->priv_ver >= PRIV_VERSION_1_10_0 ?
>          MSTATUS_MIE : MSTATUS_UIE << prev_priv,
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index dd93e12b45..0a28f208a2 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -752,7 +752,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>          ctx->virt_enabled = riscv_cpu_virt_enabled(env);
>          if (env->priv_ver == PRV_M &&
>              get_field(*env->mstatus, MSTATUS_MPRV) &&
> -            get_field(*env->mstatus, MSTATUS_MPV)) {
> +            MSTATUS_MPV_ISSET(env)) {
>              ctx->virt_enabled = true;
>          } else if (env->priv == PRV_S &&
>                     !riscv_cpu_virt_enabled(env) &&

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting
  2020-01-09  0:49 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Palmer Dabbelt
  2020-01-09  2:33   ` Richard Henderson
@ 2020-01-10 23:21   ` Palmer Dabbelt
  1 sibling, 0 replies; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-10 23:21 UTC (permalink / raw)
  To: richard.henderson; +Cc: Alistair Francis, alistair23, qemu-riscv, qemu-devel

On Wed, 08 Jan 2020 18:33:40 PST (-0800), richard.henderson@linaro.org wrote:
> On 1/9/20 11:49 AM, Palmer Dabbelt wrote:
>>> +    irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);
>>
>> Isn't "-unsigned" implementation defined?  I can't get GCC to throw a warning
>> and it was already there, so maybe I'm just wrong?
>
> (1) You're confusing implementation defined with undefined, and unsigned
> arithmetic is the former not the latter.
>
> (2) There is no such thing as ones-compliment or sign-magnitude integer
> hardware anymore, so for this case "implementation defined" is in fact universal.
>
> (3) We build with -fwrapv, so we're explicitly asking for sane behaviour from
> our signed types as well.

Ah, thanks -- I didn't know we had -fwrapv.  In that case we're safe!

>
>
> r~


^ permalink raw reply	[flat|nested] 78+ messages in thread

* RE: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
  2019-12-09 18:11 ` [PATCH v1 23/36] target/riscv: Add hypvervisor trap support Alistair Francis
@ 2020-01-20  8:34   ` Jiangyifei
  2020-01-31 21:25     ` Alistair Francis
  0 siblings, 1 reply; 78+ messages in thread
From: Jiangyifei @ 2020-01-20  8:34 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel, qemu-riscv
  Cc: alistair23, zhaosiqi (A), palmer, limingwang (A), dengkai (A)

Hi Alistair, 

When I boot a riscv OS (the host) on the QEMU emulator and then boot a
guest riscv OS in the host. The guest riscv OS fails to boot. 

The riscv OS is a linux kernel in the riscv_kvm_v10 branch, the qemu emulator
is the riscv-hyp-ext-v0.5.next branch.

The QEMU command line:
    ./qemu-system-riscv64 -M virt -m 4096M -cpu rv64,x-h=true -nographic \
        -smp 8 \
        -name guest=riscv-test,debug-threads=on \
        -kernel ./fw_jump.elf \
        -device loader,file=./Image,addr=0x80200000 \
        -drive file=./hyp.img,format=raw,id=hd0 \
        -device virtio-blk-device,drive=hd0 \
        -append "root=/dev/vda rw console=ttyS0 earlycon=sbi"

The kvmtool command line:
    ./lkvm-static run -m 2048 -c2 --console serial -p "console=ttyS0 \
        earlycon=uart8250,mmio,0x3f8" -k ./Image -d guest.img

The error message is:
    [   46.136740] kvm [128]: VCPU exit error -14
    [   46.137967] kvm [128]: SEPC=0x3febbf234e SSTATUS=0x4020 HSTATUS=0x380
    [   46.140075] kvm [128]: SCAUSE=0x8 STVAL=0x0
    KVM_RUN failed: Bad address

According to the error message printed by kvm, the exception of Environment
call from VU-mode should to be delivered to VS-mode, instead of delivered
to kvm in HS-mode.

The problem is that the FORCE_HS_EXCEP flag is set when there is a pending
irq that should trap to V==0, but this bit is not cleared in  riscv_cpu_do_interrupt
when trapping to M-mode. So clearing FORCE_HS_EXCEP flag when trap to
M-mode. The patch is as follows:

Signed-off-by: Jiang Yifei <jiangyifei@huawei.com>
---
target/riscv/cpu_helper.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 7166e61..cb6a1d6 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -954,6 +954,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)

            /* Trapping to M mode, virt is disabled */
            riscv_cpu_set_virt_enabled(env, 0);
+            riscv_cpu_set_force_hs_excep(env, 0);
        }

        s = *env->mstatus;
--

Regards,
Yifei

> -----Original Message-----
> From: Qemu-riscv [mailto:qemu-riscv-
> bounces+jiangyifei=huawei.com@nongnu.org] On Behalf Of Alistair Francis
> Sent: Tuesday, December 10, 2019 2:12 AM
> To: qemu-devel@nongnu.org; qemu-riscv@nongnu.org
> Cc: alistair.francis@wdc.com; palmer@dabbelt.com; alistair23@gmail.com
> Subject: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
> 
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
> ---
>  target/riscv/cpu_helper.c | 65 +++++++++++++++++++++++++++++++++---
> ---
>  1 file changed, 55 insertions(+), 10 deletions(-)
> 
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index
> 1b747abf93..2c6d2bc3a3 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -641,6 +641,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> 
>      RISCVCPU *cpu = RISCV_CPU(cs);
>      CPURISCVState *env = &cpu->env;
> +    target_ulong s;
> 
>      /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
>       * so we mask off the MSB and separate into trap type and cause.
> @@ -650,13 +651,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      target_ulong deleg = async ? env->mideleg : env->medeleg;
>      target_ulong tval = 0;
> 
> -    static const int ecall_cause_map[] = {
> -        [PRV_U] = RISCV_EXCP_U_ECALL,
> -        [PRV_S] = RISCV_EXCP_S_ECALL,
> -        [PRV_H] = RISCV_EXCP_VS_ECALL,
> -        [PRV_M] = RISCV_EXCP_M_ECALL
> -    };
> -
>      if (!async) {
>          /* set tval to badaddr for traps with address information */
>          switch (cause) {
> @@ -680,7 +674,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          /* ecall is dispatched as one cause so translate based on mode */
>          if (cause == RISCV_EXCP_U_ECALL) {
>              assert(env->priv <= 3);
> -            cause = ecall_cause_map[env->priv];
> +
> +            if (env->priv == PRV_M) {
> +                cause = RISCV_EXCP_M_ECALL;
> +            } else if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
> +                cause = RISCV_EXCP_VS_ECALL;
> +            } else if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) {
> +                cause = RISCV_EXCP_S_ECALL;
> +            } else if (env->priv == PRV_U) {
> +                cause = RISCV_EXCP_U_ECALL;
> +            }
>          }
>      }
> 
> @@ -690,7 +693,36 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      if (env->priv <= PRV_S &&
>              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
>          /* handle the trap in S-mode */
> -        target_ulong s = *env->mstatus;
> +        if (riscv_has_ext(env, RVH)) {
> +            target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
> +
> +            if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
> +                !riscv_cpu_force_hs_excep_enabled(env)) {
> +                /* Trap to VS mode */
> +            } else if (riscv_cpu_virt_enabled(env)) {
> +                /* Trap into HS mode, from virt */
> +                riscv_cpu_swap_hypervisor_regs(env);
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
> +                                         get_field(env->hstatus, HSTATUS_SPV));
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
> +                                         get_field(*env->mstatus, SSTATUS_SPP));
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
> +                                         riscv_cpu_virt_enabled(env));
> +
> +                riscv_cpu_set_virt_enabled(env, 0);
> +                riscv_cpu_set_force_hs_excep(env, 0);
> +            } else {
> +                /* Trap into HS mode */
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
> +                                         get_field(env->hstatus, HSTATUS_SPV));
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
> +                                         get_field(*env->mstatus, SSTATUS_SPP));
> +                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
> +                                         riscv_cpu_virt_enabled(env));
> +            }
> +        }
> +
> +        s = *env->mstatus;
>          s = set_field(s, MSTATUS_SPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
>              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
>          s = set_field(s, MSTATUS_SPP, env->priv); @@ -704,7 +736,20 @@ void
> riscv_cpu_do_interrupt(CPUState *cs)
>          riscv_cpu_set_mode(env, PRV_S);
>      } else {
>          /* handle the trap in M-mode */
> -        target_ulong s = *env->mstatus;
> +        if (riscv_has_ext(env, RVH)) {
> +            if (riscv_cpu_virt_enabled(env)) {
> +                riscv_cpu_swap_hypervisor_regs(env);
> +            }
> +            *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
> +                                      riscv_cpu_virt_enabled(env));
> +            *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
> +
> + riscv_cpu_force_hs_excep_enabled(env));
> +
> +            /* Trapping to M mode, virt is disabled */
> +            riscv_cpu_set_virt_enabled(env, 0);
> +        }
> +
> +        s = *env->mstatus;
>          s = set_field(s, MSTATUS_MPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
>              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env-
> >priv));
>          s = set_field(s, MSTATUS_MPP, env->priv);
> --
> 2.24.0
> 



^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-08  1:30 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Palmer Dabbelt
@ 2020-01-21 11:02   ` Alistair Francis
  2020-01-21 12:56     ` Jonathan Behrens
  2020-01-30 14:48   ` Palmer Dabbelt
  1 sibling, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2020-01-21 11:02 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: open list:RISC-V, Alistair Francis, qemu-devel@nongnu.org Developers

On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>
> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> > To handle the new Hypervisor CSR register aliasing let's use pointers.
>
> For some reason I thought we were making this explicit?  In other words,
> requiring that all callers provide which privilege mode they're using when
> accessing these CSRs, as opposed to swapping around pointers.  I don't actually
> care that much, but IIRC when we were talking with the ARM guys at Plumbers
> they were pretty adament that would end up being a much cleaner implementation
> as they'd tried this way and later changed over.

I think their implementation is different so it doesn't apply the same here.

My main concern is that due to the modularity of RISC-V I don't expect
all future developers to keep track of the Hypervisor extensions. This
way we always have the correct state in the registers.

There is only one pointer variable left, so we could drop the pointer
swapping part, but for now it's still here.

Alistair

>
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > ---
> >  target/riscv/cpu.c        | 11 +++++++++--
> >  target/riscv/cpu.h        |  9 ++++++++-
> >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
> >  target/riscv/csr.c        | 20 ++++++++++----------
> >  target/riscv/op_helper.c  | 14 +++++++-------
> >  5 files changed, 49 insertions(+), 35 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index a07c5689b3..e61cf46a73 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
> >  #ifndef CONFIG_USER_ONLY
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
> >      if (riscv_has_ext(env, RVH)) {
> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> >      mcc->parent_reset(cs);
> >  #ifndef CONFIG_USER_ONLY
> >      env->priv = PRV_M;
> > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >      env->mcause = 0;
> >      env->pc = env->resetvec;
> >  #endif
> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
> >  static void riscv_cpu_init(Object *obj)
> >  {
> >      RISCVCPU *cpu = RISCV_CPU(obj);
> > +#ifndef CONFIG_USER_ONLY
> > +    CPURISCVState *env = &cpu->env;
> > +#endif
> >
> >      cpu_set_cpustate_pointers(cpu);
> > +
> > +#ifndef CONFIG_USER_ONLY
> > +    env->mstatus = &env->mstatus_novirt;
> > +#endif
> >  }
> >
> >  static const VMStateDescription vmstate_riscv_cpu = {
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 21ae5a8b19..9dc8303c62 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -122,7 +122,7 @@ struct CPURISCVState {
> >      target_ulong resetvec;
> >
> >      target_ulong mhartid;
> > -    target_ulong mstatus;
> > +    target_ulong *mstatus;
> >
> >      target_ulong mip;
> >      uint32_t miclaim;
> > @@ -145,6 +145,13 @@ struct CPURISCVState {
> >      target_ulong mcause;
> >      target_ulong mtval;  /* since: priv-1.10.0 */
> >
> > +    /* The following registers are the "real" versions that the pointer
> > +     * versions point to. These should never be used unless you know what you
> > +     * are doing. To access these use the pointer versions instead. This is
> > +     * required to handle the Hypervisor register swapping.
> > +     */
> > +    target_ulong mstatus_novirt;
> > +
> >      /* Hypervisor CSRs */
> >      target_ulong hstatus;
> >      target_ulong hedeleg;
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index b00f66824a..9684da7f7d 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
> >  #ifndef CONFIG_USER_ONLY
> >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> >  {
> > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
> > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
> >      target_ulong pending = env->mip & env->mie;
> >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
> >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
> > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
> >  /* Return true is floating point support is currently enabled */
> >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
> >  {
> > -    if (env->mstatus & MSTATUS_FS) {
> > +    if (*env->mstatus & MSTATUS_FS) {
> >          return true;
> >      }
> >
> > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >      int mode = mmu_idx;
> >
> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >          }
> >      }
> >
> > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >
> >      hwaddr base;
> >      int levels, ptidxbits, ptesize, vm, sum;
> > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> >
> >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> > -        sum = get_field(env->mstatus, MSTATUS_SUM);
> > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
> >          vm = get_field(env->satp, SATP_MODE);
> >          switch (vm) {
> >          case VM_1_10_SV32:
> > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >          }
> >      } else {
> >          base = (hwaddr)(env->sptbr) << PGSHIFT;
> > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> > -        vm = get_field(env->mstatus, MSTATUS_VM);
> > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> > +        vm = get_field(*env->mstatus, MSTATUS_VM);
> >          switch (vm) {
> >          case VM_1_09_SV32:
> >            levels = 2; ptidxbits = 10; ptesize = 4; break;
> > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> >      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
> >
> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >          }
> >      }
> >
> > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >      if (env->priv <= PRV_S &&
> >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> >          /* handle the trap in S-mode */
> > -        target_ulong s = env->mstatus;
> > +        target_ulong s = *env->mstatus;
> >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
> >          s = set_field(s, MSTATUS_SPP, env->priv);
> >          s = set_field(s, MSTATUS_SIE, 0);
> > -        env->mstatus = s;
> > +        *env->mstatus = s;
> >          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
> >          env->sepc = env->pc;
> >          env->sbadaddr = tval;
> > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >          riscv_cpu_set_mode(env, PRV_S);
> >      } else {
> >          /* handle the trap in M-mode */
> > -        target_ulong s = env->mstatus;
> > +        target_ulong s = *env->mstatus;
> >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
> >          s = set_field(s, MSTATUS_MPP, env->priv);
> >          s = set_field(s, MSTATUS_MIE, 0);
> > -        env->mstatus = s;
> > +        *env->mstatus = s;
> >          env->mcause = cause | ~(((target_ulong)-1) >> async);
> >          env->mepc = env->pc;
> >          env->mbadaddr = tval;
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index 74e911af08..a4b598d49a 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >          return -1;
> >      }
> > -    env->mstatus |= MSTATUS_FS;
> > +    *env->mstatus |= MSTATUS_FS;
> >  #endif
> >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> >      return 0;
> > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >          return -1;
> >      }
> > -    env->mstatus |= MSTATUS_FS;
> > +    *env->mstatus |= MSTATUS_FS;
> >  #endif
> >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
> >      return 0;
> > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >          return -1;
> >      }
> > -    env->mstatus |= MSTATUS_FS;
> > +    *env->mstatus |= MSTATUS_FS;
> >  #endif
> >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
> >  /* Machine Trap Setup */
> >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> > -    *val = env->mstatus;
> > +    *val = *env->mstatus;
> >      return 0;
> >  }
> >
> > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
> >
> >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > -    target_ulong mstatus = env->mstatus;
> > +    target_ulong mstatus = *env->mstatus;
> >      target_ulong mask = 0;
> >      int dirty;
> >
> > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
> >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
> >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> > -    env->mstatus = mstatus;
> > +    *env->mstatus = mstatus;
> >
> >      return 0;
> >  }
> > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > -    *val = env->mstatus & mask;
> > +    *val = *env->mstatus & mask;
> >      return 0;
> >  }
> >
> > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
> >      return write_mstatus(env, CSR_MSTATUS, newval);
> >  }
> >
> > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
> >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> >          *val = 0;
> >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> >              return -1;
> >          } else {
> >              *val = env->satp;
> > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
> >          validate_vm(env, get_field(val, SATP_MODE)) &&
> >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
> >      {
> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> >              return -1;
> >          } else {
> >              if((val ^ env->satp) & SATP_ASID) {
> > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> > index 331cc36232..d150551bc9 100644
> > --- a/target/riscv/op_helper.c
> > +++ b/target/riscv/op_helper.c
> > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >      }
> >
> >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > -        get_field(env->mstatus, MSTATUS_TSR)) {
> > +        get_field(*env->mstatus, MSTATUS_TSR)) {
> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >      }
> >
> > -    target_ulong mstatus = env->mstatus;
> > +    target_ulong mstatus = *env->mstatus;
> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
> >      mstatus = set_field(mstatus,
> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
> >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> >      riscv_cpu_set_mode(env, prev_priv);
> > -    env->mstatus = mstatus;
> > +    *env->mstatus = mstatus;
> >
> >      return retpc;
> >  }
> > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> >      }
> >
> > -    target_ulong mstatus = env->mstatus;
> > +    target_ulong mstatus = *env->mstatus;
> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> >      mstatus = set_field(mstatus,
> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
> >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> >      riscv_cpu_set_mode(env, prev_priv);
> > -    env->mstatus = mstatus;
> > +    *env->mstatus = mstatus;
> >
> >      return retpc;
> >  }
> > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
> >
> >      if (env->priv == PRV_S &&
> >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > -        get_field(env->mstatus, MSTATUS_TW)) {
> > +        get_field(*env->mstatus, MSTATUS_TW)) {
> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >      } else {
> >          cs->halted = 1;
> > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
> >      if (!(env->priv >= PRV_S) ||
> >          (env->priv == PRV_S &&
> >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > -         get_field(env->mstatus, MSTATUS_TVM))) {
> > +         get_field(*env->mstatus, MSTATUS_TVM))) {
> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >      } else {
> >          tlb_flush(cs);


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension
  2020-01-08  2:07 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Palmer Dabbelt
@ 2020-01-21 11:11   ` Alistair Francis
  2020-01-21 11:29     ` Anup Patel
  0 siblings, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2020-01-21 11:11 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: open list:RISC-V, Alistair Francis, qemu-devel@nongnu.org Developers

On Wed, Jan 8, 2020 at 12:07 PM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>
> On Mon, 09 Dec 2019 10:11:24 PST (-0800), Alistair Francis wrote:
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > ---
> >  target/riscv/csr.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index a4b598d49a..fc38c45a7e 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -449,6 +449,9 @@ static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
> >  static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> >      env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
> > +    if (riscv_has_ext(env, RVH)) {
> > +        env->mideleg |= VS_MODE_INTERRUPTS;
> > +    }
> >      return 0;
> >  }
>
> Do you have any idea why?  The spec is explicit that this is the case, but I'm
> surprised.

I'm not sure why, maybe to simplfy hardware design?

Alistair

>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension
  2020-01-21 11:11   ` Alistair Francis
@ 2020-01-21 11:29     ` Anup Patel
  0 siblings, 0 replies; 78+ messages in thread
From: Anup Patel @ 2020-01-21 11:29 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Alistair Francis, Palmer Dabbelt, open list:RISC-V,
	qemu-devel@nongnu.org Developers

On Tue, Jan 21, 2020 at 4:43 PM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Wed, Jan 8, 2020 at 12:07 PM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
> >
> > On Mon, 09 Dec 2019 10:11:24 PST (-0800), Alistair Francis wrote:
> > > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > > ---
> > >  target/riscv/csr.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > > index a4b598d49a..fc38c45a7e 100644
> > > --- a/target/riscv/csr.c
> > > +++ b/target/riscv/csr.c
> > > @@ -449,6 +449,9 @@ static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
> > >  static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
> > >  {
> > >      env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
> > > +    if (riscv_has_ext(env, RVH)) {
> > > +        env->mideleg |= VS_MODE_INTERRUPTS;
> > > +    }
> > >      return 0;
> > >  }
> >
> > Do you have any idea why?  The spec is explicit that this is the case, but I'm
> > surprised.
>
> I'm not sure why, maybe to simplfy hardware design?

As-per my understanding, the VS-mode interrupts can be
taken only when V=1 and these are injected by HS-mode
using HIP CSR.

If we allow VS-mode interrupts to be taken in M-mode then
it means HS-mode can now inject interrupts for M-mode using
HIP CSR. This cannot be allowed hence VS-mode interrupts
are force delegated to S-mode in MIDELEG.

Regards,
Anup


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-21 11:02   ` Alistair Francis
@ 2020-01-21 12:56     ` Jonathan Behrens
  2020-01-22  0:00       ` Alistair Francis
  0 siblings, 1 reply; 78+ messages in thread
From: Jonathan Behrens @ 2020-01-21 12:56 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Alistair Francis, Palmer Dabbelt, open list:RISC-V,
	qemu-devel@nongnu.org Developers

[-- Attachment #1: Type: text/plain, Size: 17804 bytes --]

When I looked through the relevant code a few months ago, I couldn't find
anywhere that could actually be agnostic to whether the real or virtual
registers were in effect (other than emulating the actual CSR modification
instructions). For almost all state, the VS behavior is filtered by HS-mode
code. For example, you can grab satp in either mode but to properly do
address translation you also have to factor in hgatp so you need to know
the virtualization state anyway. Similarly, floating point co-proccessor
state is tracked in two places with V=1 so that both the host and the guest
can independently track dirty bits, but of course only the one in the
"real" mstatus applies in non-virtualized mode.

The idea of using an array to track the two versions of registers seemed
really elegant to me. If you know you want the host version you access
element zero. If you know you want the guest version you access element
one. And if you want the version that the running code would see you index
by the virtualization mode. In any case, the choice indicates that you
thought though which was the right option to use in that instance.

Jonathan

On Tue, Jan 21, 2020 at 6:02 AM Alistair Francis <alistair23@gmail.com>
wrote:

> On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com>
> wrote:
> >
> > On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> > > To handle the new Hypervisor CSR register aliasing let's use pointers.
> >
> > For some reason I thought we were making this explicit?  In other words,
> > requiring that all callers provide which privilege mode they're using
> when
> > accessing these CSRs, as opposed to swapping around pointers.  I don't
> actually
> > care that much, but IIRC when we were talking with the ARM guys at
> Plumbers
> > they were pretty adament that would end up being a much cleaner
> implementation
> > as they'd tried this way and later changed over.
>
> I think their implementation is different so it doesn't apply the same
> here.
>
> My main concern is that due to the modularity of RISC-V I don't expect
> all future developers to keep track of the Hypervisor extensions. This
> way we always have the correct state in the registers.
>
> There is only one pointer variable left, so we could drop the pointer
> swapping part, but for now it's still here.
>
> Alistair
>
> >
> > > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > > ---
> > >  target/riscv/cpu.c        | 11 +++++++++--
> > >  target/riscv/cpu.h        |  9 ++++++++-
> > >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
> > >  target/riscv/csr.c        | 20 ++++++++++----------
> > >  target/riscv/op_helper.c  | 14 +++++++-------
> > >  5 files changed, 49 insertions(+), 35 deletions(-)
> > >
> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > > index a07c5689b3..e61cf46a73 100644
> > > --- a/target/riscv/cpu.c
> > > +++ b/target/riscv/cpu.c
> > > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs,
> FILE *f, int flags)
> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
> > >  #ifndef CONFIG_USER_ONLY
> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ",
> env->mhartid);
> > > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ",
> env->mstatus);
> > > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ",
> *env->mstatus);
> > >      if (riscv_has_ext(env, RVH)) {
> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ",
> env->hstatus);
> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
> env->vsstatus);
> > > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> > >      mcc->parent_reset(cs);
> > >  #ifndef CONFIG_USER_ONLY
> > >      env->priv = PRV_M;
> > > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > >      env->mcause = 0;
> > >      env->pc = env->resetvec;
> > >  #endif
> > > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev,
> Error **errp)
> > >  static void riscv_cpu_init(Object *obj)
> > >  {
> > >      RISCVCPU *cpu = RISCV_CPU(obj);
> > > +#ifndef CONFIG_USER_ONLY
> > > +    CPURISCVState *env = &cpu->env;
> > > +#endif
> > >
> > >      cpu_set_cpustate_pointers(cpu);
> > > +
> > > +#ifndef CONFIG_USER_ONLY
> > > +    env->mstatus = &env->mstatus_novirt;
> > > +#endif
> > >  }
> > >
> > >  static const VMStateDescription vmstate_riscv_cpu = {
> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > > index 21ae5a8b19..9dc8303c62 100644
> > > --- a/target/riscv/cpu.h
> > > +++ b/target/riscv/cpu.h
> > > @@ -122,7 +122,7 @@ struct CPURISCVState {
> > >      target_ulong resetvec;
> > >
> > >      target_ulong mhartid;
> > > -    target_ulong mstatus;
> > > +    target_ulong *mstatus;
> > >
> > >      target_ulong mip;
> > >      uint32_t miclaim;
> > > @@ -145,6 +145,13 @@ struct CPURISCVState {
> > >      target_ulong mcause;
> > >      target_ulong mtval;  /* since: priv-1.10.0 */
> > >
> > > +    /* The following registers are the "real" versions that the
> pointer
> > > +     * versions point to. These should never be used unless you know
> what you
> > > +     * are doing. To access these use the pointer versions instead.
> This is
> > > +     * required to handle the Hypervisor register swapping.
> > > +     */
> > > +    target_ulong mstatus_novirt;
> > > +
> > >      /* Hypervisor CSRs */
> > >      target_ulong hstatus;
> > >      target_ulong hedeleg;
> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > index b00f66824a..9684da7f7d 100644
> > > --- a/target/riscv/cpu_helper.c
> > > +++ b/target/riscv/cpu_helper.c
> > > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool
> ifetch)
> > >  #ifndef CONFIG_USER_ONLY
> > >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> > >  {
> > > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> > > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> > > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
> > > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
> > >      target_ulong pending = env->mip & env->mie;
> > >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M &&
> mstatus_mie);
> > >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S &&
> mstatus_sie);
> > > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int
> interrupt_request)
> > >  /* Return true is floating point support is currently enabled */
> > >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
> > >  {
> > > -    if (env->mstatus & MSTATUS_FS) {
> > > +    if (*env->mstatus & MSTATUS_FS) {
> > >          return true;
> > >      }
> > >
> > > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> > >      int mode = mmu_idx;
> > >
> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> > >          }
> > >      }
> > >
> > > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> > >
> > >      hwaddr base;
> > >      int levels, ptidxbits, ptesize, vm, sum;
> > > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> > > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> > >
> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> > >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> > > -        sum = get_field(env->mstatus, MSTATUS_SUM);
> > > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
> > >          vm = get_field(env->satp, SATP_MODE);
> > >          switch (vm) {
> > >          case VM_1_10_SV32:
> > > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> > >          }
> > >      } else {
> > >          base = (hwaddr)(env->sptbr) << PGSHIFT;
> > > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> > > -        vm = get_field(env->mstatus, MSTATUS_VM);
> > > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> > > +        vm = get_field(*env->mstatus, MSTATUS_VM);
> > >          switch (vm) {
> > >          case VM_1_09_SV32:
> > >            levels = 2; ptidxbits = 10; ptesize = 4; break;
> > > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr
> address, int size,
> > >      ret = get_physical_address(env, &pa, &prot, address, access_type,
> mmu_idx);
> > >
> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> > >          }
> > >      }
> > >
> > > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >      if (env->priv <= PRV_S &&
> > >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> > >          /* handle the trap in S-mode */
> > > -        target_ulong s = env->mstatus;
> > > +        target_ulong s = *env->mstatus;
> > >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
> > >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE <<
> env->priv));
> > >          s = set_field(s, MSTATUS_SPP, env->priv);
> > >          s = set_field(s, MSTATUS_SIE, 0);
> > > -        env->mstatus = s;
> > > +        *env->mstatus = s;
> > >          env->scause = cause | ((target_ulong)async <<
> (TARGET_LONG_BITS - 1));
> > >          env->sepc = env->pc;
> > >          env->sbadaddr = tval;
> > > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >          riscv_cpu_set_mode(env, PRV_S);
> > >      } else {
> > >          /* handle the trap in M-mode */
> > > -        target_ulong s = env->mstatus;
> > > +        target_ulong s = *env->mstatus;
> > >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
> > >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE <<
> env->priv));
> > >          s = set_field(s, MSTATUS_MPP, env->priv);
> > >          s = set_field(s, MSTATUS_MIE, 0);
> > > -        env->mstatus = s;
> > > +        *env->mstatus = s;
> > >          env->mcause = cause | ~(((target_ulong)-1) >> async);
> > >          env->mepc = env->pc;
> > >          env->mbadaddr = tval;
> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > > index 74e911af08..a4b598d49a 100644
> > > --- a/target/riscv/csr.c
> > > +++ b/target/riscv/csr.c
> > > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int
> csrno, target_ulong val)
> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >          return -1;
> > >      }
> > > -    env->mstatus |= MSTATUS_FS;
> > > +    *env->mstatus |= MSTATUS_FS;
> > >  #endif
> > >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> > >      return 0;
> > > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int
> csrno, target_ulong val)
> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >          return -1;
> > >      }
> > > -    env->mstatus |= MSTATUS_FS;
> > > +    *env->mstatus |= MSTATUS_FS;
> > >  #endif
> > >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
> > >      return 0;
> > > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int
> csrno, target_ulong val)
> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >          return -1;
> > >      }
> > > -    env->mstatus |= MSTATUS_FS;
> > > +    *env->mstatus |= MSTATUS_FS;
> > >  #endif
> > >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> > >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> > > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int
> csrno, target_ulong *val)
> > >  /* Machine Trap Setup */
> > >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong
> *val)
> > >  {
> > > -    *val = env->mstatus;
> > > +    *val = *env->mstatus;
> > >      return 0;
> > >  }
> > >
> > > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env,
> target_ulong vm)
> > >
> > >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong
> val)
> > >  {
> > > -    target_ulong mstatus = env->mstatus;
> > > +    target_ulong mstatus = *env->mstatus;
> > >      target_ulong mask = 0;
> > >      int dirty;
> > >
> > > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int
> csrno, target_ulong val)
> > >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
> > >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
> > >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> > > -    env->mstatus = mstatus;
> > > +    *env->mstatus = mstatus;
> > >
> > >      return 0;
> > >  }
> > > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int
> csrno, target_ulong *val)
> > >  {
> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > > -    *val = env->mstatus & mask;
> > > +    *val = *env->mstatus & mask;
> > >      return 0;
> > >  }
> > >
> > > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int
> csrno, target_ulong val)
> > >  {
> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> > > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
> > >      return write_mstatus(env, CSR_MSTATUS, newval);
> > >  }
> > >
> > > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int
> csrno, target_ulong *val)
> > >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> > >          *val = 0;
> > >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> > > -        if (env->priv == PRV_S && get_field(env->mstatus,
> MSTATUS_TVM)) {
> > > +        if (env->priv == PRV_S && get_field(*env->mstatus,
> MSTATUS_TVM)) {
> > >              return -1;
> > >          } else {
> > >              *val = env->satp;
> > > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int
> csrno, target_ulong val)
> > >          validate_vm(env, get_field(val, SATP_MODE)) &&
> > >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
> > >      {
> > > -        if (env->priv == PRV_S && get_field(env->mstatus,
> MSTATUS_TVM)) {
> > > +        if (env->priv == PRV_S && get_field(*env->mstatus,
> MSTATUS_TVM)) {
> > >              return -1;
> > >          } else {
> > >              if((val ^ env->satp) & SATP_ASID) {
> > > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> > > index 331cc36232..d150551bc9 100644
> > > --- a/target/riscv/op_helper.c
> > > +++ b/target/riscv/op_helper.c
> > > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> > >      }
> > >
> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > > -        get_field(env->mstatus, MSTATUS_TSR)) {
> > > +        get_field(*env->mstatus, MSTATUS_TSR)) {
> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >      }
> > >
> > > -    target_ulong mstatus = env->mstatus;
> > > +    target_ulong mstatus = *env->mstatus;
> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
> > >      mstatus = set_field(mstatus,
> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> > >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
> > >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> > >      riscv_cpu_set_mode(env, prev_priv);
> > > -    env->mstatus = mstatus;
> > > +    *env->mstatus = mstatus;
> > >
> > >      return retpc;
> > >  }
> > > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> > >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> > >      }
> > >
> > > -    target_ulong mstatus = env->mstatus;
> > > +    target_ulong mstatus = *env->mstatus;
> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> > >      mstatus = set_field(mstatus,
> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> > >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
> > >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> > >      riscv_cpu_set_mode(env, prev_priv);
> > > -    env->mstatus = mstatus;
> > > +    *env->mstatus = mstatus;
> > >
> > >      return retpc;
> > >  }
> > > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
> > >
> > >      if (env->priv == PRV_S &&
> > >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > > -        get_field(env->mstatus, MSTATUS_TW)) {
> > > +        get_field(*env->mstatus, MSTATUS_TW)) {
> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >      } else {
> > >          cs->halted = 1;
> > > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
> > >      if (!(env->priv >= PRV_S) ||
> > >          (env->priv == PRV_S &&
> > >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > > -         get_field(env->mstatus, MSTATUS_TVM))) {
> > > +         get_field(*env->mstatus, MSTATUS_TVM))) {
> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >      } else {
> > >          tlb_flush(cs);
>
>

[-- Attachment #2: Type: text/html, Size: 23132 bytes --]

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-21 12:56     ` Jonathan Behrens
@ 2020-01-22  0:00       ` Alistair Francis
  2020-01-22 22:13         ` Jonathan Behrens
  0 siblings, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2020-01-22  0:00 UTC (permalink / raw)
  To: Jonathan Behrens
  Cc: Alistair Francis, Palmer Dabbelt, open list:RISC-V,
	qemu-devel@nongnu.org Developers

On Tue, Jan 21, 2020 at 10:56 PM Jonathan Behrens <fintelia@gmail.com> wrote:
>
> When I looked through the relevant code a few months ago, I couldn't find anywhere that could actually be agnostic to whether the real or virtual registers were in effect (other than emulating the actual CSR modification instructions). For almost all state, the VS behavior is filtered by HS-mode code. For example, you can grab satp in either mode but to properly do address translation you also have to factor in hgatp so you need to know the virtualization state anyway. Similarly, floating point co-proccessor state is tracked in two places with V=1 so that both the host and the guest can independently track dirty bits, but of course only the one in the "real" mstatus applies in non-virtualized mode.

So the idea is that if you aren't interested in the Hypervisor
extension you can just access the CSRs as usual (inside QEMU's source
code). That is you don't need to know anything about the Hypervisor
extension to add support for other extensions or to work on the RISC-V
target in QEMU.

I was trying to avoid forcing everyone to understand the Hypervisor
extension to develop for RISC-V. For example we don't have to check
virtulasition status to dump the registers, we can just dump them and
know they are in the correct state (we do dump more is we have the
extension though). Image if someone adds a new way to dump registers,
I would like them not to care about if we are in V=1 or V=0 and they
can just dump them and know that the CSRs are correct.

>
> The idea of using an array to track the two versions of registers seemed really elegant to me. If you know you want the host version you access element zero. If you know you want the guest version you access element one. And if you want the version that the running code would see you index by the virtualization mode. In any case, the choice indicates that you thought though which was the right option to use in that instance.

mstatus really is the only one that has any complications. The others
have a vs* version, which could be converted to an array but it
doesn't really matter as we just swap them.

Alistair

>
> Jonathan
>
> On Tue, Jan 21, 2020 at 6:02 AM Alistair Francis <alistair23@gmail.com> wrote:
>>
>> On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>> >
>> > On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
>> > > To handle the new Hypervisor CSR register aliasing let's use pointers.
>> >
>> > For some reason I thought we were making this explicit?  In other words,
>> > requiring that all callers provide which privilege mode they're using when
>> > accessing these CSRs, as opposed to swapping around pointers.  I don't actually
>> > care that much, but IIRC when we were talking with the ARM guys at Plumbers
>> > they were pretty adament that would end up being a much cleaner implementation
>> > as they'd tried this way and later changed over.
>>
>> I think their implementation is different so it doesn't apply the same here.
>>
>> My main concern is that due to the modularity of RISC-V I don't expect
>> all future developers to keep track of the Hypervisor extensions. This
>> way we always have the correct state in the registers.
>>
>> There is only one pointer variable left, so we could drop the pointer
>> swapping part, but for now it's still here.
>>
>> Alistair
>>
>> >
>> > > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
>> > > ---
>> > >  target/riscv/cpu.c        | 11 +++++++++--
>> > >  target/riscv/cpu.h        |  9 ++++++++-
>> > >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
>> > >  target/riscv/csr.c        | 20 ++++++++++----------
>> > >  target/riscv/op_helper.c  | 14 +++++++-------
>> > >  5 files changed, 49 insertions(+), 35 deletions(-)
>> > >
>> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > > index a07c5689b3..e61cf46a73 100644
>> > > --- a/target/riscv/cpu.c
>> > > +++ b/target/riscv/cpu.c
>> > > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
>> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
>> > >  #ifndef CONFIG_USER_ONLY
>> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
>> > > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
>> > > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
>> > >      if (riscv_has_ext(env, RVH)) {
>> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
>> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
>> > > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
>> > >      mcc->parent_reset(cs);
>> > >  #ifndef CONFIG_USER_ONLY
>> > >      env->priv = PRV_M;
>> > > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
>> > > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
>> > >      env->mcause = 0;
>> > >      env->pc = env->resetvec;
>> > >  #endif
>> > > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>> > >  static void riscv_cpu_init(Object *obj)
>> > >  {
>> > >      RISCVCPU *cpu = RISCV_CPU(obj);
>> > > +#ifndef CONFIG_USER_ONLY
>> > > +    CPURISCVState *env = &cpu->env;
>> > > +#endif
>> > >
>> > >      cpu_set_cpustate_pointers(cpu);
>> > > +
>> > > +#ifndef CONFIG_USER_ONLY
>> > > +    env->mstatus = &env->mstatus_novirt;
>> > > +#endif
>> > >  }
>> > >
>> > >  static const VMStateDescription vmstate_riscv_cpu = {
>> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > > index 21ae5a8b19..9dc8303c62 100644
>> > > --- a/target/riscv/cpu.h
>> > > +++ b/target/riscv/cpu.h
>> > > @@ -122,7 +122,7 @@ struct CPURISCVState {
>> > >      target_ulong resetvec;
>> > >
>> > >      target_ulong mhartid;
>> > > -    target_ulong mstatus;
>> > > +    target_ulong *mstatus;
>> > >
>> > >      target_ulong mip;
>> > >      uint32_t miclaim;
>> > > @@ -145,6 +145,13 @@ struct CPURISCVState {
>> > >      target_ulong mcause;
>> > >      target_ulong mtval;  /* since: priv-1.10.0 */
>> > >
>> > > +    /* The following registers are the "real" versions that the pointer
>> > > +     * versions point to. These should never be used unless you know what you
>> > > +     * are doing. To access these use the pointer versions instead. This is
>> > > +     * required to handle the Hypervisor register swapping.
>> > > +     */
>> > > +    target_ulong mstatus_novirt;
>> > > +
>> > >      /* Hypervisor CSRs */
>> > >      target_ulong hstatus;
>> > >      target_ulong hedeleg;
>> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> > > index b00f66824a..9684da7f7d 100644
>> > > --- a/target/riscv/cpu_helper.c
>> > > +++ b/target/riscv/cpu_helper.c
>> > > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>> > >  #ifndef CONFIG_USER_ONLY
>> > >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>> > >  {
>> > > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
>> > > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
>> > > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
>> > > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
>> > >      target_ulong pending = env->mip & env->mie;
>> > >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
>> > >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
>> > > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
>> > >  /* Return true is floating point support is currently enabled */
>> > >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
>> > >  {
>> > > -    if (env->mstatus & MSTATUS_FS) {
>> > > +    if (*env->mstatus & MSTATUS_FS) {
>> > >          return true;
>> > >      }
>> > >
>> > > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> > >      int mode = mmu_idx;
>> > >
>> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
>> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
>> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
>> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>> > >          }
>> > >      }
>> > >
>> > > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> > >
>> > >      hwaddr base;
>> > >      int levels, ptidxbits, ptesize, vm, sum;
>> > > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
>> > > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
>> > >
>> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>> > >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
>> > > -        sum = get_field(env->mstatus, MSTATUS_SUM);
>> > > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
>> > >          vm = get_field(env->satp, SATP_MODE);
>> > >          switch (vm) {
>> > >          case VM_1_10_SV32:
>> > > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> > >          }
>> > >      } else {
>> > >          base = (hwaddr)(env->sptbr) << PGSHIFT;
>> > > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
>> > > -        vm = get_field(env->mstatus, MSTATUS_VM);
>> > > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
>> > > +        vm = get_field(*env->mstatus, MSTATUS_VM);
>> > >          switch (vm) {
>> > >          case VM_1_09_SV32:
>> > >            levels = 2; ptidxbits = 10; ptesize = 4; break;
>> > > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>> > >      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
>> > >
>> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
>> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
>> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
>> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>> > >          }
>> > >      }
>> > >
>> > > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>> > >      if (env->priv <= PRV_S &&
>> > >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
>> > >          /* handle the trap in S-mode */
>> > > -        target_ulong s = env->mstatus;
>> > > +        target_ulong s = *env->mstatus;
>> > >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
>> > >          s = set_field(s, MSTATUS_SPP, env->priv);
>> > >          s = set_field(s, MSTATUS_SIE, 0);
>> > > -        env->mstatus = s;
>> > > +        *env->mstatus = s;
>> > >          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
>> > >          env->sepc = env->pc;
>> > >          env->sbadaddr = tval;
>> > > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>> > >          riscv_cpu_set_mode(env, PRV_S);
>> > >      } else {
>> > >          /* handle the trap in M-mode */
>> > > -        target_ulong s = env->mstatus;
>> > > +        target_ulong s = *env->mstatus;
>> > >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
>> > >          s = set_field(s, MSTATUS_MPP, env->priv);
>> > >          s = set_field(s, MSTATUS_MIE, 0);
>> > > -        env->mstatus = s;
>> > > +        *env->mstatus = s;
>> > >          env->mcause = cause | ~(((target_ulong)-1) >> async);
>> > >          env->mepc = env->pc;
>> > >          env->mbadaddr = tval;
>> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> > > index 74e911af08..a4b598d49a 100644
>> > > --- a/target/riscv/csr.c
>> > > +++ b/target/riscv/csr.c
>> > > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
>> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> > >          return -1;
>> > >      }
>> > > -    env->mstatus |= MSTATUS_FS;
>> > > +    *env->mstatus |= MSTATUS_FS;
>> > >  #endif
>> > >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
>> > >      return 0;
>> > > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
>> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> > >          return -1;
>> > >      }
>> > > -    env->mstatus |= MSTATUS_FS;
>> > > +    *env->mstatus |= MSTATUS_FS;
>> > >  #endif
>> > >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
>> > >      return 0;
>> > > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
>> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> > >          return -1;
>> > >      }
>> > > -    env->mstatus |= MSTATUS_FS;
>> > > +    *env->mstatus |= MSTATUS_FS;
>> > >  #endif
>> > >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
>> > >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
>> > > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
>> > >  /* Machine Trap Setup */
>> > >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
>> > >  {
>> > > -    *val = env->mstatus;
>> > > +    *val = *env->mstatus;
>> > >      return 0;
>> > >  }
>> > >
>> > > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
>> > >
>> > >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>> > >  {
>> > > -    target_ulong mstatus = env->mstatus;
>> > > +    target_ulong mstatus = *env->mstatus;
>> > >      target_ulong mask = 0;
>> > >      int dirty;
>> > >
>> > > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>> > >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
>> > >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
>> > >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
>> > > -    env->mstatus = mstatus;
>> > > +    *env->mstatus = mstatus;
>> > >
>> > >      return 0;
>> > >  }
>> > > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
>> > >  {
>> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
>> > > -    *val = env->mstatus & mask;
>> > > +    *val = *env->mstatus & mask;
>> > >      return 0;
>> > >  }
>> > >
>> > > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
>> > >  {
>> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
>> > > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
>> > > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
>> > >      return write_mstatus(env, CSR_MSTATUS, newval);
>> > >  }
>> > >
>> > > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
>> > >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
>> > >          *val = 0;
>> > >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>> > > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
>> > > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>> > >              return -1;
>> > >          } else {
>> > >              *val = env->satp;
>> > > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
>> > >          validate_vm(env, get_field(val, SATP_MODE)) &&
>> > >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
>> > >      {
>> > > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
>> > > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>> > >              return -1;
>> > >          } else {
>> > >              if((val ^ env->satp) & SATP_ASID) {
>> > > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
>> > > index 331cc36232..d150551bc9 100644
>> > > --- a/target/riscv/op_helper.c
>> > > +++ b/target/riscv/op_helper.c
>> > > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> > >      }
>> > >
>> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > > -        get_field(env->mstatus, MSTATUS_TSR)) {
>> > > +        get_field(*env->mstatus, MSTATUS_TSR)) {
>> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> > >      }
>> > >
>> > > -    target_ulong mstatus = env->mstatus;
>> > > +    target_ulong mstatus = *env->mstatus;
>> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
>> > >      mstatus = set_field(mstatus,
>> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> > >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
>> > >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
>> > >      riscv_cpu_set_mode(env, prev_priv);
>> > > -    env->mstatus = mstatus;
>> > > +    *env->mstatus = mstatus;
>> > >
>> > >      return retpc;
>> > >  }
>> > > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> > >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>> > >      }
>> > >
>> > > -    target_ulong mstatus = env->mstatus;
>> > > +    target_ulong mstatus = *env->mstatus;
>> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
>> > >      mstatus = set_field(mstatus,
>> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> > >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
>> > >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
>> > >      riscv_cpu_set_mode(env, prev_priv);
>> > > -    env->mstatus = mstatus;
>> > > +    *env->mstatus = mstatus;
>> > >
>> > >      return retpc;
>> > >  }
>> > > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
>> > >
>> > >      if (env->priv == PRV_S &&
>> > >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > > -        get_field(env->mstatus, MSTATUS_TW)) {
>> > > +        get_field(*env->mstatus, MSTATUS_TW)) {
>> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> > >      } else {
>> > >          cs->halted = 1;
>> > > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
>> > >      if (!(env->priv >= PRV_S) ||
>> > >          (env->priv == PRV_S &&
>> > >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > > -         get_field(env->mstatus, MSTATUS_TVM))) {
>> > > +         get_field(*env->mstatus, MSTATUS_TVM))) {
>> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> > >      } else {
>> > >          tlb_flush(cs);
>>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-22  0:00       ` Alistair Francis
@ 2020-01-22 22:13         ` Jonathan Behrens
  0 siblings, 0 replies; 78+ messages in thread
From: Jonathan Behrens @ 2020-01-22 22:13 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Alistair Francis, Palmer Dabbelt, open list:RISC-V,
	qemu-devel@nongnu.org Developers

[-- Attachment #1: Type: text/plain, Size: 22266 bytes --]

>
> I was trying to avoid forcing everyone to understand the Hypervisor
> extension to develop for RISC-V.


I agree a full understanding of the hypervisor extension shouldn't be
required. But if code is going to be dealing with supervisor mode
registers, then whether the machine is in HS or VS mode is going to matter
in a lot of cases. The cases where it doesn't matter are particularly
troubling: it wouldn't be obvious from reading the code whether the author
forgot about the possibility of register swapping or if the code actually
works then too. Plus, for custom forks we can always add a one line comment
above the register declarations saying you can just s*xxx*[NOVIRT] to
access the normal supervisor registers unless you want to make sure your
code works with the H-extension.

For example we don't have to check
> virtualization status to dump the registers, we can just dump them and
> know they are in the correct state (we do dump more is we have the
> extension though). Image if someone adds a new way to dump registers,
> I would like them not to care about if we are in V=1 or V=0 and they
> can just dump them and know that the CSRs are correct.
>

This is almost a best case for being orthogonal to other features because
you don't have to understand anything about how the registers impact
machine execution in order to dump them.

But even here it is somewhat debatable whether a naive implementation would
dump the "correct" versions of these registers. One view is that what you
really want would be the values that M-mode code would see since it has the
most objective view of the system. Another is that they are the values that
would be returned if the the current operating mode tried to access them,
or undefined if that access would trap. Maybe you even want to query the
value for a specific mode independent of the current privilege level. If
the behavior you want happens to match up to the chosen design, then yes a
naive implementation that is oblivious the hypervisor extension will work
without having to understand anything. However, I'd attribute that more to
luck than elegance of a particular option.

Jonathan

On Tue, Jan 21, 2020 at 7:01 PM Alistair Francis <alistair23@gmail.com>
wrote:

> On Tue, Jan 21, 2020 at 10:56 PM Jonathan Behrens <fintelia@gmail.com>
> wrote:
> >
> > When I looked through the relevant code a few months ago, I couldn't
> find anywhere that could actually be agnostic to whether the real or
> virtual registers were in effect (other than emulating the actual CSR
> modification instructions). For almost all state, the VS behavior is
> filtered by HS-mode code. For example, you can grab satp in either mode but
> to properly do address translation you also have to factor in hgatp so you
> need to know the virtualization state anyway. Similarly, floating point
> co-proccessor state is tracked in two places with V=1 so that both the host
> and the guest can independently track dirty bits, but of course only the
> one in the "real" mstatus applies in non-virtualized mode.
>
> So the idea is that if you aren't interested in the Hypervisor
> extension you can just access the CSRs as usual (inside QEMU's source
> code). That is you don't need to know anything about the Hypervisor
> extension to add support for other extensions or to work on the RISC-V
> target in QEMU.
>
> I was trying to avoid forcing everyone to understand the Hypervisor
> extension to develop for RISC-V. For example we don't have to check
> virtulasition status to dump the registers, we can just dump them and
> know they are in the correct state (we do dump more is we have the
> extension though). Image if someone adds a new way to dump registers,
> I would like them not to care about if we are in V=1 or V=0 and they
> can just dump them and know that the CSRs are correct.
>
> >
> > The idea of using an array to track the two versions of registers seemed
> really elegant to me. If you know you want the host version you access
> element zero. If you know you want the guest version you access element
> one. And if you want the version that the running code would see you index
> by the virtualization mode. In any case, the choice indicates that you
> thought though which was the right option to use in that instance.
>
> mstatus really is the only one that has any complications. The others
> have a vs* version, which could be converted to an array but it
> doesn't really matter as we just swap them.
>
> Alistair
>
> >
> > Jonathan
> >
> > On Tue, Jan 21, 2020 at 6:02 AM Alistair Francis <alistair23@gmail.com>
> wrote:
> >>
> >> On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <
> palmerdabbelt@google.com> wrote:
> >> >
> >> > On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> >> > > To handle the new Hypervisor CSR register aliasing let's use
> pointers.
> >> >
> >> > For some reason I thought we were making this explicit?  In other
> words,
> >> > requiring that all callers provide which privilege mode they're using
> when
> >> > accessing these CSRs, as opposed to swapping around pointers.  I
> don't actually
> >> > care that much, but IIRC when we were talking with the ARM guys at
> Plumbers
> >> > they were pretty adament that would end up being a much cleaner
> implementation
> >> > as they'd tried this way and later changed over.
> >>
> >> I think their implementation is different so it doesn't apply the same
> here.
> >>
> >> My main concern is that due to the modularity of RISC-V I don't expect
> >> all future developers to keep track of the Hypervisor extensions. This
> >> way we always have the correct state in the registers.
> >>
> >> There is only one pointer variable left, so we could drop the pointer
> >> swapping part, but for now it's still here.
> >>
> >> Alistair
> >>
> >> >
> >> > > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> >> > > ---
> >> > >  target/riscv/cpu.c        | 11 +++++++++--
> >> > >  target/riscv/cpu.h        |  9 ++++++++-
> >> > >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
> >> > >  target/riscv/csr.c        | 20 ++++++++++----------
> >> > >  target/riscv/op_helper.c  | 14 +++++++-------
> >> > >  5 files changed, 49 insertions(+), 35 deletions(-)
> >> > >
> >> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> > > index a07c5689b3..e61cf46a73 100644
> >> > > --- a/target/riscv/cpu.c
> >> > > +++ b/target/riscv/cpu.c
> >> > > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs,
> FILE *f, int flags)
> >> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ",
> env->pc);
> >> > >  #ifndef CONFIG_USER_ONLY
> >> > >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ",
> env->mhartid);
> >> > > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ",
> env->mstatus);
> >> > > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ",
> *env->mstatus);
> >> > >      if (riscv_has_ext(env, RVH)) {
> >> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ",
> env->hstatus);
> >> > >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
> env->vsstatus);
> >> > > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> >> > >      mcc->parent_reset(cs);
> >> > >  #ifndef CONFIG_USER_ONLY
> >> > >      env->priv = PRV_M;
> >> > > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> > > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> > >      env->mcause = 0;
> >> > >      env->pc = env->resetvec;
> >> > >  #endif
> >> > > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState
> *dev, Error **errp)
> >> > >  static void riscv_cpu_init(Object *obj)
> >> > >  {
> >> > >      RISCVCPU *cpu = RISCV_CPU(obj);
> >> > > +#ifndef CONFIG_USER_ONLY
> >> > > +    CPURISCVState *env = &cpu->env;
> >> > > +#endif
> >> > >
> >> > >      cpu_set_cpustate_pointers(cpu);
> >> > > +
> >> > > +#ifndef CONFIG_USER_ONLY
> >> > > +    env->mstatus = &env->mstatus_novirt;
> >> > > +#endif
> >> > >  }
> >> > >
> >> > >  static const VMStateDescription vmstate_riscv_cpu = {
> >> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> > > index 21ae5a8b19..9dc8303c62 100644
> >> > > --- a/target/riscv/cpu.h
> >> > > +++ b/target/riscv/cpu.h
> >> > > @@ -122,7 +122,7 @@ struct CPURISCVState {
> >> > >      target_ulong resetvec;
> >> > >
> >> > >      target_ulong mhartid;
> >> > > -    target_ulong mstatus;
> >> > > +    target_ulong *mstatus;
> >> > >
> >> > >      target_ulong mip;
> >> > >      uint32_t miclaim;
> >> > > @@ -145,6 +145,13 @@ struct CPURISCVState {
> >> > >      target_ulong mcause;
> >> > >      target_ulong mtval;  /* since: priv-1.10.0 */
> >> > >
> >> > > +    /* The following registers are the "real" versions that the
> pointer
> >> > > +     * versions point to. These should never be used unless you
> know what you
> >> > > +     * are doing. To access these use the pointer versions
> instead. This is
> >> > > +     * required to handle the Hypervisor register swapping.
> >> > > +     */
> >> > > +    target_ulong mstatus_novirt;
> >> > > +
> >> > >      /* Hypervisor CSRs */
> >> > >      target_ulong hstatus;
> >> > >      target_ulong hedeleg;
> >> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> >> > > index b00f66824a..9684da7f7d 100644
> >> > > --- a/target/riscv/cpu_helper.c
> >> > > +++ b/target/riscv/cpu_helper.c
> >> > > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool
> ifetch)
> >> > >  #ifndef CONFIG_USER_ONLY
> >> > >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> >> > >  {
> >> > > -    target_ulong mstatus_mie = get_field(env->mstatus,
> MSTATUS_MIE);
> >> > > -    target_ulong mstatus_sie = get_field(env->mstatus,
> MSTATUS_SIE);
> >> > > +    target_ulong mstatus_mie = get_field(*env->mstatus,
> MSTATUS_MIE);
> >> > > +    target_ulong mstatus_sie = get_field(*env->mstatus,
> MSTATUS_SIE);
> >> > >      target_ulong pending = env->mip & env->mie;
> >> > >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M &&
> mstatus_mie);
> >> > >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S &&
> mstatus_sie);
> >> > > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int
> interrupt_request)
> >> > >  /* Return true is floating point support is currently enabled */
> >> > >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
> >> > >  {
> >> > > -    if (env->mstatus & MSTATUS_FS) {
> >> > > +    if (*env->mstatus & MSTATUS_FS) {
> >> > >          return true;
> >> > >      }
> >> > >
> >> > > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> >> > >      int mode = mmu_idx;
> >> > >
> >> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> >> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> >> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> >> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> >> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >> > >          }
> >> > >      }
> >> > >
> >> > > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> >> > >
> >> > >      hwaddr base;
> >> > >      int levels, ptidxbits, ptesize, vm, sum;
> >> > > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> >> > > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> >> > >
> >> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> >> > >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> >> > > -        sum = get_field(env->mstatus, MSTATUS_SUM);
> >> > > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
> >> > >          vm = get_field(env->satp, SATP_MODE);
> >> > >          switch (vm) {
> >> > >          case VM_1_10_SV32:
> >> > > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState
> *env, hwaddr *physical,
> >> > >          }
> >> > >      } else {
> >> > >          base = (hwaddr)(env->sptbr) << PGSHIFT;
> >> > > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> >> > > -        vm = get_field(env->mstatus, MSTATUS_VM);
> >> > > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> >> > > +        vm = get_field(*env->mstatus, MSTATUS_VM);
> >> > >          switch (vm) {
> >> > >          case VM_1_09_SV32:
> >> > >            levels = 2; ptidxbits = 10; ptesize = 4; break;
> >> > > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr
> address, int size,
> >> > >      ret = get_physical_address(env, &pa, &prot, address,
> access_type, mmu_idx);
> >> > >
> >> > >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> >> > > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> >> > > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> >> > > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> >> > > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >> > >          }
> >> > >      }
> >> > >
> >> > > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >> > >      if (env->priv <= PRV_S &&
> >> > >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> >> > >          /* handle the trap in S-mode */
> >> > > -        target_ulong s = env->mstatus;
> >> > > +        target_ulong s = *env->mstatus;
> >> > >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
> >> > >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE
> << env->priv));
> >> > >          s = set_field(s, MSTATUS_SPP, env->priv);
> >> > >          s = set_field(s, MSTATUS_SIE, 0);
> >> > > -        env->mstatus = s;
> >> > > +        *env->mstatus = s;
> >> > >          env->scause = cause | ((target_ulong)async <<
> (TARGET_LONG_BITS - 1));
> >> > >          env->sepc = env->pc;
> >> > >          env->sbadaddr = tval;
> >> > > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >> > >          riscv_cpu_set_mode(env, PRV_S);
> >> > >      } else {
> >> > >          /* handle the trap in M-mode */
> >> > > -        target_ulong s = env->mstatus;
> >> > > +        target_ulong s = *env->mstatus;
> >> > >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >=
> PRIV_VERSION_1_10_0 ?
> >> > >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE
> << env->priv));
> >> > >          s = set_field(s, MSTATUS_MPP, env->priv);
> >> > >          s = set_field(s, MSTATUS_MIE, 0);
> >> > > -        env->mstatus = s;
> >> > > +        *env->mstatus = s;
> >> > >          env->mcause = cause | ~(((target_ulong)-1) >> async);
> >> > >          env->mepc = env->pc;
> >> > >          env->mbadaddr = tval;
> >> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> > > index 74e911af08..a4b598d49a 100644
> >> > > --- a/target/riscv/csr.c
> >> > > +++ b/target/riscv/csr.c
> >> > > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int
> csrno, target_ulong val)
> >> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> > >          return -1;
> >> > >      }
> >> > > -    env->mstatus |= MSTATUS_FS;
> >> > > +    *env->mstatus |= MSTATUS_FS;
> >> > >  #endif
> >> > >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> >> > >      return 0;
> >> > > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int
> csrno, target_ulong val)
> >> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> > >          return -1;
> >> > >      }
> >> > > -    env->mstatus |= MSTATUS_FS;
> >> > > +    *env->mstatus |= MSTATUS_FS;
> >> > >  #endif
> >> > >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
> >> > >      return 0;
> >> > > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int
> csrno, target_ulong val)
> >> > >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> > >          return -1;
> >> > >      }
> >> > > -    env->mstatus |= MSTATUS_FS;
> >> > > +    *env->mstatus |= MSTATUS_FS;
> >> > >  #endif
> >> > >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> >> > >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> >> > > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int
> csrno, target_ulong *val)
> >> > >  /* Machine Trap Setup */
> >> > >  static int read_mstatus(CPURISCVState *env, int csrno,
> target_ulong *val)
> >> > >  {
> >> > > -    *val = env->mstatus;
> >> > > +    *val = *env->mstatus;
> >> > >      return 0;
> >> > >  }
> >> > >
> >> > > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env,
> target_ulong vm)
> >> > >
> >> > >  static int write_mstatus(CPURISCVState *env, int csrno,
> target_ulong val)
> >> > >  {
> >> > > -    target_ulong mstatus = env->mstatus;
> >> > > +    target_ulong mstatus = *env->mstatus;
> >> > >      target_ulong mask = 0;
> >> > >      int dirty;
> >> > >
> >> > > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env,
> int csrno, target_ulong val)
> >> > >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
> >> > >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
> >> > >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> >> > > -    env->mstatus = mstatus;
> >> > > +    *env->mstatus = mstatus;
> >> > >
> >> > >      return 0;
> >> > >  }
> >> > > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int
> csrno, target_ulong *val)
> >> > >  {
> >> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> >> > > -    *val = env->mstatus & mask;
> >> > > +    *val = *env->mstatus & mask;
> >> > >      return 0;
> >> > >  }
> >> > >
> >> > > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env,
> int csrno, target_ulong val)
> >> > >  {
> >> > >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >> > >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> >> > > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> >> > > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
> >> > >      return write_mstatus(env, CSR_MSTATUS, newval);
> >> > >  }
> >> > >
> >> > > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int
> csrno, target_ulong *val)
> >> > >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> >> > >          *val = 0;
> >> > >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> >> > > -        if (env->priv == PRV_S && get_field(env->mstatus,
> MSTATUS_TVM)) {
> >> > > +        if (env->priv == PRV_S && get_field(*env->mstatus,
> MSTATUS_TVM)) {
> >> > >              return -1;
> >> > >          } else {
> >> > >              *val = env->satp;
> >> > > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int
> csrno, target_ulong val)
> >> > >          validate_vm(env, get_field(val, SATP_MODE)) &&
> >> > >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
> >> > >      {
> >> > > -        if (env->priv == PRV_S && get_field(env->mstatus,
> MSTATUS_TVM)) {
> >> > > +        if (env->priv == PRV_S && get_field(*env->mstatus,
> MSTATUS_TVM)) {
> >> > >              return -1;
> >> > >          } else {
> >> > >              if((val ^ env->satp) & SATP_ASID) {
> >> > > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> >> > > index 331cc36232..d150551bc9 100644
> >> > > --- a/target/riscv/op_helper.c
> >> > > +++ b/target/riscv/op_helper.c
> >> > > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> >> > >      }
> >> > >
> >> > >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > > -        get_field(env->mstatus, MSTATUS_TSR)) {
> >> > > +        get_field(*env->mstatus, MSTATUS_TSR)) {
> >> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST,
> GETPC());
> >> > >      }
> >> > >
> >> > > -    target_ulong mstatus = env->mstatus;
> >> > > +    target_ulong mstatus = *env->mstatus;
> >> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
> >> > >      mstatus = set_field(mstatus,
> >> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> > > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> >> > >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
> >> > >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> >> > >      riscv_cpu_set_mode(env, prev_priv);
> >> > > -    env->mstatus = mstatus;
> >> > > +    *env->mstatus = mstatus;
> >> > >
> >> > >      return retpc;
> >> > >  }
> >> > > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> >> > >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS,
> GETPC());
> >> > >      }
> >> > >
> >> > > -    target_ulong mstatus = env->mstatus;
> >> > > +    target_ulong mstatus = *env->mstatus;
> >> > >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> >> > >      mstatus = set_field(mstatus,
> >> > >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> > > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env,
> target_ulong cpu_pc_deb)
> >> > >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
> >> > >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> >> > >      riscv_cpu_set_mode(env, prev_priv);
> >> > > -    env->mstatus = mstatus;
> >> > > +    *env->mstatus = mstatus;
> >> > >
> >> > >      return retpc;
> >> > >  }
> >> > > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
> >> > >
> >> > >      if (env->priv == PRV_S &&
> >> > >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > > -        get_field(env->mstatus, MSTATUS_TW)) {
> >> > > +        get_field(*env->mstatus, MSTATUS_TW)) {
> >> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST,
> GETPC());
> >> > >      } else {
> >> > >          cs->halted = 1;
> >> > > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
> >> > >      if (!(env->priv >= PRV_S) ||
> >> > >          (env->priv == PRV_S &&
> >> > >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > > -         get_field(env->mstatus, MSTATUS_TVM))) {
> >> > > +         get_field(*env->mstatus, MSTATUS_TVM))) {
> >> > >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST,
> GETPC());
> >> > >      } else {
> >> > >          tlb_flush(cs);
> >>
>

[-- Attachment #2: Type: text/html, Size: 30350 bytes --]

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-08  1:30 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Palmer Dabbelt
  2020-01-21 11:02   ` Alistair Francis
@ 2020-01-30 14:48   ` Palmer Dabbelt
  2020-01-31 17:31     ` Alistair Francis
  1 sibling, 1 reply; 78+ messages in thread
From: Palmer Dabbelt @ 2020-01-30 14:48 UTC (permalink / raw)
  To: alistair23; +Cc: qemu-riscv, Alistair Francis, qemu-devel

On Tue, 21 Jan 2020 11:02:01 GMT (+0000), alistair23@gmail.com wrote:
> On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>>
>> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
>> > To handle the new Hypervisor CSR register aliasing let's use pointers.
>>
>> For some reason I thought we were making this explicit?  In other words,
>> requiring that all callers provide which privilege mode they're using when
>> accessing these CSRs, as opposed to swapping around pointers.  I don't actually
>> care that much, but IIRC when we were talking with the ARM guys at Plumbers
>> they were pretty adament that would end up being a much cleaner implementation
>> as they'd tried this way and later changed over.
>
> I think their implementation is different so it doesn't apply the same here.
>
> My main concern is that due to the modularity of RISC-V I don't expect
> all future developers to keep track of the Hypervisor extensions. This
> way we always have the correct state in the registers.
>
> There is only one pointer variable left, so we could drop the pointer
> swapping part, but for now it's still here.

OK, so in the interest of moving things forwards let's just

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

so we can merge this -- it's too big of a patch set to wait around on something
so small for.  I think that was the last one missing a review, right?

>
> Alistair
>
>>
>> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
>> > ---
>> >  target/riscv/cpu.c        | 11 +++++++++--
>> >  target/riscv/cpu.h        |  9 ++++++++-
>> >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
>> >  target/riscv/csr.c        | 20 ++++++++++----------
>> >  target/riscv/op_helper.c  | 14 +++++++-------
>> >  5 files changed, 49 insertions(+), 35 deletions(-)
>> >
>> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > index a07c5689b3..e61cf46a73 100644
>> > --- a/target/riscv/cpu.c
>> > +++ b/target/riscv/cpu.c
>> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
>> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
>> >  #ifndef CONFIG_USER_ONLY
>> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
>> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
>> > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
>> >      if (riscv_has_ext(env, RVH)) {
>> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
>> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
>> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
>> >      mcc->parent_reset(cs);
>> >  #ifndef CONFIG_USER_ONLY
>> >      env->priv = PRV_M;
>> > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
>> > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
>> >      env->mcause = 0;
>> >      env->pc = env->resetvec;
>> >  #endif
>> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>> >  static void riscv_cpu_init(Object *obj)
>> >  {
>> >      RISCVCPU *cpu = RISCV_CPU(obj);
>> > +#ifndef CONFIG_USER_ONLY
>> > +    CPURISCVState *env = &cpu->env;
>> > +#endif
>> >
>> >      cpu_set_cpustate_pointers(cpu);
>> > +
>> > +#ifndef CONFIG_USER_ONLY
>> > +    env->mstatus = &env->mstatus_novirt;
>> > +#endif
>> >  }
>> >
>> >  static const VMStateDescription vmstate_riscv_cpu = {
>> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > index 21ae5a8b19..9dc8303c62 100644
>> > --- a/target/riscv/cpu.h
>> > +++ b/target/riscv/cpu.h
>> > @@ -122,7 +122,7 @@ struct CPURISCVState {
>> >      target_ulong resetvec;
>> >
>> >      target_ulong mhartid;
>> > -    target_ulong mstatus;
>> > +    target_ulong *mstatus;
>> >
>> >      target_ulong mip;
>> >      uint32_t miclaim;
>> > @@ -145,6 +145,13 @@ struct CPURISCVState {
>> >      target_ulong mcause;
>> >      target_ulong mtval;  /* since: priv-1.10.0 */
>> >
>> > +    /* The following registers are the "real" versions that the pointer
>> > +     * versions point to. These should never be used unless you know what you
>> > +     * are doing. To access these use the pointer versions instead. This is
>> > +     * required to handle the Hypervisor register swapping.
>> > +     */
>> > +    target_ulong mstatus_novirt;
>> > +
>> >      /* Hypervisor CSRs */
>> >      target_ulong hstatus;
>> >      target_ulong hedeleg;
>> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> > index b00f66824a..9684da7f7d 100644
>> > --- a/target/riscv/cpu_helper.c
>> > +++ b/target/riscv/cpu_helper.c
>> > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>> >  #ifndef CONFIG_USER_ONLY
>> >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>> >  {
>> > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
>> > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
>> > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
>> > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
>> >      target_ulong pending = env->mip & env->mie;
>> >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
>> >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
>> > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
>> >  /* Return true is floating point support is currently enabled */
>> >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
>> >  {
>> > -    if (env->mstatus & MSTATUS_FS) {
>> > +    if (*env->mstatus & MSTATUS_FS) {
>> >          return true;
>> >      }
>> >
>> > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> >      int mode = mmu_idx;
>> >
>> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
>> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
>> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
>> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>> >          }
>> >      }
>> >
>> > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> >
>> >      hwaddr base;
>> >      int levels, ptidxbits, ptesize, vm, sum;
>> > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
>> > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
>> >
>> >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>> >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
>> > -        sum = get_field(env->mstatus, MSTATUS_SUM);
>> > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
>> >          vm = get_field(env->satp, SATP_MODE);
>> >          switch (vm) {
>> >          case VM_1_10_SV32:
>> > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>> >          }
>> >      } else {
>> >          base = (hwaddr)(env->sptbr) << PGSHIFT;
>> > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
>> > -        vm = get_field(env->mstatus, MSTATUS_VM);
>> > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
>> > +        vm = get_field(*env->mstatus, MSTATUS_VM);
>> >          switch (vm) {
>> >          case VM_1_09_SV32:
>> >            levels = 2; ptidxbits = 10; ptesize = 4; break;
>> > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>> >      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
>> >
>> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
>> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
>> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
>> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
>> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
>> >          }
>> >      }
>> >
>> > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>> >      if (env->priv <= PRV_S &&
>> >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
>> >          /* handle the trap in S-mode */
>> > -        target_ulong s = env->mstatus;
>> > +        target_ulong s = *env->mstatus;
>> >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
>> >          s = set_field(s, MSTATUS_SPP, env->priv);
>> >          s = set_field(s, MSTATUS_SIE, 0);
>> > -        env->mstatus = s;
>> > +        *env->mstatus = s;
>> >          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
>> >          env->sepc = env->pc;
>> >          env->sbadaddr = tval;
>> > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>> >          riscv_cpu_set_mode(env, PRV_S);
>> >      } else {
>> >          /* handle the trap in M-mode */
>> > -        target_ulong s = env->mstatus;
>> > +        target_ulong s = *env->mstatus;
>> >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
>> >          s = set_field(s, MSTATUS_MPP, env->priv);
>> >          s = set_field(s, MSTATUS_MIE, 0);
>> > -        env->mstatus = s;
>> > +        *env->mstatus = s;
>> >          env->mcause = cause | ~(((target_ulong)-1) >> async);
>> >          env->mepc = env->pc;
>> >          env->mbadaddr = tval;
>> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> > index 74e911af08..a4b598d49a 100644
>> > --- a/target/riscv/csr.c
>> > +++ b/target/riscv/csr.c
>> > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
>> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> >          return -1;
>> >      }
>> > -    env->mstatus |= MSTATUS_FS;
>> > +    *env->mstatus |= MSTATUS_FS;
>> >  #endif
>> >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
>> >      return 0;
>> > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
>> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> >          return -1;
>> >      }
>> > -    env->mstatus |= MSTATUS_FS;
>> > +    *env->mstatus |= MSTATUS_FS;
>> >  #endif
>> >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
>> >      return 0;
>> > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
>> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
>> >          return -1;
>> >      }
>> > -    env->mstatus |= MSTATUS_FS;
>> > +    *env->mstatus |= MSTATUS_FS;
>> >  #endif
>> >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
>> >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
>> > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
>> >  /* Machine Trap Setup */
>> >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
>> >  {
>> > -    *val = env->mstatus;
>> > +    *val = *env->mstatus;
>> >      return 0;
>> >  }
>> >
>> > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
>> >
>> >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>> >  {
>> > -    target_ulong mstatus = env->mstatus;
>> > +    target_ulong mstatus = *env->mstatus;
>> >      target_ulong mask = 0;
>> >      int dirty;
>> >
>> > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>> >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
>> >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
>> >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
>> > -    env->mstatus = mstatus;
>> > +    *env->mstatus = mstatus;
>> >
>> >      return 0;
>> >  }
>> > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
>> >  {
>> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
>> > -    *val = env->mstatus & mask;
>> > +    *val = *env->mstatus & mask;
>> >      return 0;
>> >  }
>> >
>> > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
>> >  {
>> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
>> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
>> > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
>> > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
>> >      return write_mstatus(env, CSR_MSTATUS, newval);
>> >  }
>> >
>> > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
>> >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
>> >          *val = 0;
>> >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
>> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>> >              return -1;
>> >          } else {
>> >              *val = env->satp;
>> > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
>> >          validate_vm(env, get_field(val, SATP_MODE)) &&
>> >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
>> >      {
>> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
>> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
>> >              return -1;
>> >          } else {
>> >              if((val ^ env->satp) & SATP_ASID) {
>> > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
>> > index 331cc36232..d150551bc9 100644
>> > --- a/target/riscv/op_helper.c
>> > +++ b/target/riscv/op_helper.c
>> > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> >      }
>> >
>> >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > -        get_field(env->mstatus, MSTATUS_TSR)) {
>> > +        get_field(*env->mstatus, MSTATUS_TSR)) {
>> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> >      }
>> >
>> > -    target_ulong mstatus = env->mstatus;
>> > +    target_ulong mstatus = *env->mstatus;
>> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
>> >      mstatus = set_field(mstatus,
>> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
>> >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
>> >      riscv_cpu_set_mode(env, prev_priv);
>> > -    env->mstatus = mstatus;
>> > +    *env->mstatus = mstatus;
>> >
>> >      return retpc;
>> >  }
>> > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>> >      }
>> >
>> > -    target_ulong mstatus = env->mstatus;
>> > +    target_ulong mstatus = *env->mstatus;
>> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
>> >      mstatus = set_field(mstatus,
>> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
>> > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>> >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
>> >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
>> >      riscv_cpu_set_mode(env, prev_priv);
>> > -    env->mstatus = mstatus;
>> > +    *env->mstatus = mstatus;
>> >
>> >      return retpc;
>> >  }
>> > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
>> >
>> >      if (env->priv == PRV_S &&
>> >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > -        get_field(env->mstatus, MSTATUS_TW)) {
>> > +        get_field(*env->mstatus, MSTATUS_TW)) {
>> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> >      } else {
>> >          cs->halted = 1;
>> > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
>> >      if (!(env->priv >= PRV_S) ||
>> >          (env->priv == PRV_S &&
>> >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
>> > -         get_field(env->mstatus, MSTATUS_TVM))) {
>> > +         get_field(*env->mstatus, MSTATUS_TVM))) {
>> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>> >      } else {
>> >          tlb_flush(cs);


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-30 14:48   ` Palmer Dabbelt
@ 2020-01-31 17:31     ` Alistair Francis
  2020-02-01  0:09       ` Alistair Francis
  0 siblings, 1 reply; 78+ messages in thread
From: Alistair Francis @ 2020-01-31 17:31 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: Alistair Francis, open list:RISC-V, qemu-devel@nongnu.org Developers

On Thu, Jan 30, 2020 at 6:48 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>
> On Tue, 21 Jan 2020 11:02:01 GMT (+0000), alistair23@gmail.com wrote:
> > On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
> >>
> >> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> >> > To handle the new Hypervisor CSR register aliasing let's use pointers.
> >>
> >> For some reason I thought we were making this explicit?  In other words,
> >> requiring that all callers provide which privilege mode they're using when
> >> accessing these CSRs, as opposed to swapping around pointers.  I don't actually
> >> care that much, but IIRC when we were talking with the ARM guys at Plumbers
> >> they were pretty adament that would end up being a much cleaner implementation
> >> as they'd tried this way and later changed over.
> >
> > I think their implementation is different so it doesn't apply the same here.
> >
> > My main concern is that due to the modularity of RISC-V I don't expect
> > all future developers to keep track of the Hypervisor extensions. This
> > way we always have the correct state in the registers.
> >
> > There is only one pointer variable left, so we could drop the pointer
> > swapping part, but for now it's still here.
>
> OK, so in the interest of moving things forwards let's just
>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

Thanks

>
> so we can merge this -- it's too big of a patch set to wait around on something
> so small for.  I think that was the last one missing a review, right?

I have made one small change and dismissed your review from a patch,
it also looks like one patch hasn't been reviewed either.

I'll send a v2 later today that has been rebased on master.

Alistair

>
> >
> > Alistair
> >
> >>
> >> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> >> > ---
> >> >  target/riscv/cpu.c        | 11 +++++++++--
> >> >  target/riscv/cpu.h        |  9 ++++++++-
> >> >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
> >> >  target/riscv/csr.c        | 20 ++++++++++----------
> >> >  target/riscv/op_helper.c  | 14 +++++++-------
> >> >  5 files changed, 49 insertions(+), 35 deletions(-)
> >> >
> >> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> > index a07c5689b3..e61cf46a73 100644
> >> > --- a/target/riscv/cpu.c
> >> > +++ b/target/riscv/cpu.c
> >> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> >> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
> >> >  #ifndef CONFIG_USER_ONLY
> >> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> >> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> >> > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
> >> >      if (riscv_has_ext(env, RVH)) {
> >> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
> >> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
> >> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> >> >      mcc->parent_reset(cs);
> >> >  #ifndef CONFIG_USER_ONLY
> >> >      env->priv = PRV_M;
> >> > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> >      env->mcause = 0;
> >> >      env->pc = env->resetvec;
> >> >  #endif
> >> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
> >> >  static void riscv_cpu_init(Object *obj)
> >> >  {
> >> >      RISCVCPU *cpu = RISCV_CPU(obj);
> >> > +#ifndef CONFIG_USER_ONLY
> >> > +    CPURISCVState *env = &cpu->env;
> >> > +#endif
> >> >
> >> >      cpu_set_cpustate_pointers(cpu);
> >> > +
> >> > +#ifndef CONFIG_USER_ONLY
> >> > +    env->mstatus = &env->mstatus_novirt;
> >> > +#endif
> >> >  }
> >> >
> >> >  static const VMStateDescription vmstate_riscv_cpu = {
> >> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> > index 21ae5a8b19..9dc8303c62 100644
> >> > --- a/target/riscv/cpu.h
> >> > +++ b/target/riscv/cpu.h
> >> > @@ -122,7 +122,7 @@ struct CPURISCVState {
> >> >      target_ulong resetvec;
> >> >
> >> >      target_ulong mhartid;
> >> > -    target_ulong mstatus;
> >> > +    target_ulong *mstatus;
> >> >
> >> >      target_ulong mip;
> >> >      uint32_t miclaim;
> >> > @@ -145,6 +145,13 @@ struct CPURISCVState {
> >> >      target_ulong mcause;
> >> >      target_ulong mtval;  /* since: priv-1.10.0 */
> >> >
> >> > +    /* The following registers are the "real" versions that the pointer
> >> > +     * versions point to. These should never be used unless you know what you
> >> > +     * are doing. To access these use the pointer versions instead. This is
> >> > +     * required to handle the Hypervisor register swapping.
> >> > +     */
> >> > +    target_ulong mstatus_novirt;
> >> > +
> >> >      /* Hypervisor CSRs */
> >> >      target_ulong hstatus;
> >> >      target_ulong hedeleg;
> >> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> >> > index b00f66824a..9684da7f7d 100644
> >> > --- a/target/riscv/cpu_helper.c
> >> > +++ b/target/riscv/cpu_helper.c
> >> > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
> >> >  #ifndef CONFIG_USER_ONLY
> >> >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> >> >  {
> >> > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> >> > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> >> > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
> >> > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
> >> >      target_ulong pending = env->mip & env->mie;
> >> >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
> >> >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
> >> > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
> >> >  /* Return true is floating point support is currently enabled */
> >> >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
> >> >  {
> >> > -    if (env->mstatus & MSTATUS_FS) {
> >> > +    if (*env->mstatus & MSTATUS_FS) {
> >> >          return true;
> >> >      }
> >> >
> >> > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >> >      int mode = mmu_idx;
> >> >
> >> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> >> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> >> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> >> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> >> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >> >          }
> >> >      }
> >> >
> >> > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >> >
> >> >      hwaddr base;
> >> >      int levels, ptidxbits, ptesize, vm, sum;
> >> > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> >> > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> >> >
> >> >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> >> >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> >> > -        sum = get_field(env->mstatus, MSTATUS_SUM);
> >> > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
> >> >          vm = get_field(env->satp, SATP_MODE);
> >> >          switch (vm) {
> >> >          case VM_1_10_SV32:
> >> > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> >> >          }
> >> >      } else {
> >> >          base = (hwaddr)(env->sptbr) << PGSHIFT;
> >> > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> >> > -        vm = get_field(env->mstatus, MSTATUS_VM);
> >> > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> >> > +        vm = get_field(*env->mstatus, MSTATUS_VM);
> >> >          switch (vm) {
> >> >          case VM_1_09_SV32:
> >> >            levels = 2; ptidxbits = 10; ptesize = 4; break;
> >> > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> >> >      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
> >> >
> >> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> >> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> >> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> >> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> >> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> >> >          }
> >> >      }
> >> >
> >> > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >> >      if (env->priv <= PRV_S &&
> >> >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> >> >          /* handle the trap in S-mode */
> >> > -        target_ulong s = env->mstatus;
> >> > +        target_ulong s = *env->mstatus;
> >> >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
> >> >          s = set_field(s, MSTATUS_SPP, env->priv);
> >> >          s = set_field(s, MSTATUS_SIE, 0);
> >> > -        env->mstatus = s;
> >> > +        *env->mstatus = s;
> >> >          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
> >> >          env->sepc = env->pc;
> >> >          env->sbadaddr = tval;
> >> > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >> >          riscv_cpu_set_mode(env, PRV_S);
> >> >      } else {
> >> >          /* handle the trap in M-mode */
> >> > -        target_ulong s = env->mstatus;
> >> > +        target_ulong s = *env->mstatus;
> >> >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
> >> >          s = set_field(s, MSTATUS_MPP, env->priv);
> >> >          s = set_field(s, MSTATUS_MIE, 0);
> >> > -        env->mstatus = s;
> >> > +        *env->mstatus = s;
> >> >          env->mcause = cause | ~(((target_ulong)-1) >> async);
> >> >          env->mepc = env->pc;
> >> >          env->mbadaddr = tval;
> >> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> > index 74e911af08..a4b598d49a 100644
> >> > --- a/target/riscv/csr.c
> >> > +++ b/target/riscv/csr.c
> >> > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
> >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> >          return -1;
> >> >      }
> >> > -    env->mstatus |= MSTATUS_FS;
> >> > +    *env->mstatus |= MSTATUS_FS;
> >> >  #endif
> >> >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> >> >      return 0;
> >> > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
> >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> >          return -1;
> >> >      }
> >> > -    env->mstatus |= MSTATUS_FS;
> >> > +    *env->mstatus |= MSTATUS_FS;
> >> >  #endif
> >> >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
> >> >      return 0;
> >> > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
> >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> >> >          return -1;
> >> >      }
> >> > -    env->mstatus |= MSTATUS_FS;
> >> > +    *env->mstatus |= MSTATUS_FS;
> >> >  #endif
> >> >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> >> >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> >> > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
> >> >  /* Machine Trap Setup */
> >> >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >> >  {
> >> > -    *val = env->mstatus;
> >> > +    *val = *env->mstatus;
> >> >      return 0;
> >> >  }
> >> >
> >> > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
> >> >
> >> >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> >> >  {
> >> > -    target_ulong mstatus = env->mstatus;
> >> > +    target_ulong mstatus = *env->mstatus;
> >> >      target_ulong mask = 0;
> >> >      int dirty;
> >> >
> >> > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> >> >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
> >> >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
> >> >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> >> > -    env->mstatus = mstatus;
> >> > +    *env->mstatus = mstatus;
> >> >
> >> >      return 0;
> >> >  }
> >> > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >> >  {
> >> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> >> > -    *val = env->mstatus & mask;
> >> > +    *val = *env->mstatus & mask;
> >> >      return 0;
> >> >  }
> >> >
> >> > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
> >> >  {
> >> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> >> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> >> > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> >> > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
> >> >      return write_mstatus(env, CSR_MSTATUS, newval);
> >> >  }
> >> >
> >> > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
> >> >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> >> >          *val = 0;
> >> >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> >> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> >> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> >> >              return -1;
> >> >          } else {
> >> >              *val = env->satp;
> >> > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
> >> >          validate_vm(env, get_field(val, SATP_MODE)) &&
> >> >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
> >> >      {
> >> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> >> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> >> >              return -1;
> >> >          } else {
> >> >              if((val ^ env->satp) & SATP_ASID) {
> >> > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> >> > index 331cc36232..d150551bc9 100644
> >> > --- a/target/riscv/op_helper.c
> >> > +++ b/target/riscv/op_helper.c
> >> > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >> >      }
> >> >
> >> >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > -        get_field(env->mstatus, MSTATUS_TSR)) {
> >> > +        get_field(*env->mstatus, MSTATUS_TSR)) {
> >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >> >      }
> >> >
> >> > -    target_ulong mstatus = env->mstatus;
> >> > +    target_ulong mstatus = *env->mstatus;
> >> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
> >> >      mstatus = set_field(mstatus,
> >> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >> >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
> >> >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> >> >      riscv_cpu_set_mode(env, prev_priv);
> >> > -    env->mstatus = mstatus;
> >> > +    *env->mstatus = mstatus;
> >> >
> >> >      return retpc;
> >> >  }
> >> > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >> >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> >> >      }
> >> >
> >> > -    target_ulong mstatus = env->mstatus;
> >> > +    target_ulong mstatus = *env->mstatus;
> >> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> >> >      mstatus = set_field(mstatus,
> >> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> >> > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> >> >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
> >> >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> >> >      riscv_cpu_set_mode(env, prev_priv);
> >> > -    env->mstatus = mstatus;
> >> > +    *env->mstatus = mstatus;
> >> >
> >> >      return retpc;
> >> >  }
> >> > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
> >> >
> >> >      if (env->priv == PRV_S &&
> >> >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > -        get_field(env->mstatus, MSTATUS_TW)) {
> >> > +        get_field(*env->mstatus, MSTATUS_TW)) {
> >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >> >      } else {
> >> >          cs->halted = 1;
> >> > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
> >> >      if (!(env->priv >= PRV_S) ||
> >> >          (env->priv == PRV_S &&
> >> >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> >> > -         get_field(env->mstatus, MSTATUS_TVM))) {
> >> > +         get_field(*env->mstatus, MSTATUS_TVM))) {
> >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> >> >      } else {
> >> >          tlb_flush(cs);


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
  2020-01-20  8:34   ` Jiangyifei
@ 2020-01-31 21:25     ` Alistair Francis
  0 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2020-01-31 21:25 UTC (permalink / raw)
  To: Jiangyifei
  Cc: qemu-riscv, limingwang (A),
	qemu-devel, palmer, Alistair Francis, zhaosiqi (A), dengkai (A)

On Mon, Jan 20, 2020 at 12:34 AM Jiangyifei <jiangyifei@huawei.com> wrote:
>
> Hi Alistair,
>
> When I boot a riscv OS (the host) on the QEMU emulator and then boot a
> guest riscv OS in the host. The guest riscv OS fails to boot.
>
> The riscv OS is a linux kernel in the riscv_kvm_v10 branch, the qemu emulator
> is the riscv-hyp-ext-v0.5.next branch.
>
> The QEMU command line:
>     ./qemu-system-riscv64 -M virt -m 4096M -cpu rv64,x-h=true -nographic \
>         -smp 8 \
>         -name guest=riscv-test,debug-threads=on \
>         -kernel ./fw_jump.elf \
>         -device loader,file=./Image,addr=0x80200000 \
>         -drive file=./hyp.img,format=raw,id=hd0 \
>         -device virtio-blk-device,drive=hd0 \
>         -append "root=/dev/vda rw console=ttyS0 earlycon=sbi"
>
> The kvmtool command line:
>     ./lkvm-static run -m 2048 -c2 --console serial -p "console=ttyS0 \
>         earlycon=uart8250,mmio,0x3f8" -k ./Image -d guest.img
>
> The error message is:
>     [   46.136740] kvm [128]: VCPU exit error -14
>     [   46.137967] kvm [128]: SEPC=0x3febbf234e SSTATUS=0x4020 HSTATUS=0x380
>     [   46.140075] kvm [128]: SCAUSE=0x8 STVAL=0x0
>     KVM_RUN failed: Bad address
>
> According to the error message printed by kvm, the exception of Environment
> call from VU-mode should to be delivered to VS-mode, instead of delivered
> to kvm in HS-mode.
>
> The problem is that the FORCE_HS_EXCEP flag is set when there is a pending
> irq that should trap to V==0, but this bit is not cleared in  riscv_cpu_do_interrupt
> when trapping to M-mode. So clearing FORCE_HS_EXCEP flag when trap to
> M-mode. The patch is as follows:
>
> Signed-off-by: Jiang Yifei <jiangyifei@huawei.com>
> ---
> target/riscv/cpu_helper.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 7166e61..cb6a1d6 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -954,6 +954,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>
>             /* Trapping to M mode, virt is disabled */
>             riscv_cpu_set_virt_enabled(env, 0);
> +            riscv_cpu_set_force_hs_excep(env, 0);
>         }
>
>         s = *env->mstatus;

Thanks, I think you are correct and I have included this change in my patch.

Alistair

> --
>
> Regards,
> Yifei
>
> > -----Original Message-----
> > From: Qemu-riscv [mailto:qemu-riscv-
> > bounces+jiangyifei=huawei.com@nongnu.org] On Behalf Of Alistair Francis
> > Sent: Tuesday, December 10, 2019 2:12 AM
> > To: qemu-devel@nongnu.org; qemu-riscv@nongnu.org
> > Cc: alistair.francis@wdc.com; palmer@dabbelt.com; alistair23@gmail.com
> > Subject: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
> >
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
> > ---
> >  target/riscv/cpu_helper.c | 65 +++++++++++++++++++++++++++++++++---
> > ---
> >  1 file changed, 55 insertions(+), 10 deletions(-)
> >
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index
> > 1b747abf93..2c6d2bc3a3 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -641,6 +641,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >
> >      RISCVCPU *cpu = RISCV_CPU(cs);
> >      CPURISCVState *env = &cpu->env;
> > +    target_ulong s;
> >
> >      /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
> >       * so we mask off the MSB and separate into trap type and cause.
> > @@ -650,13 +651,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >      target_ulong deleg = async ? env->mideleg : env->medeleg;
> >      target_ulong tval = 0;
> >
> > -    static const int ecall_cause_map[] = {
> > -        [PRV_U] = RISCV_EXCP_U_ECALL,
> > -        [PRV_S] = RISCV_EXCP_S_ECALL,
> > -        [PRV_H] = RISCV_EXCP_VS_ECALL,
> > -        [PRV_M] = RISCV_EXCP_M_ECALL
> > -    };
> > -
> >      if (!async) {
> >          /* set tval to badaddr for traps with address information */
> >          switch (cause) {
> > @@ -680,7 +674,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >          /* ecall is dispatched as one cause so translate based on mode */
> >          if (cause == RISCV_EXCP_U_ECALL) {
> >              assert(env->priv <= 3);
> > -            cause = ecall_cause_map[env->priv];
> > +
> > +            if (env->priv == PRV_M) {
> > +                cause = RISCV_EXCP_M_ECALL;
> > +            } else if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
> > +                cause = RISCV_EXCP_VS_ECALL;
> > +            } else if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) {
> > +                cause = RISCV_EXCP_S_ECALL;
> > +            } else if (env->priv == PRV_U) {
> > +                cause = RISCV_EXCP_U_ECALL;
> > +            }
> >          }
> >      }
> >
> > @@ -690,7 +693,36 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >      if (env->priv <= PRV_S &&
> >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> >          /* handle the trap in S-mode */
> > -        target_ulong s = *env->mstatus;
> > +        if (riscv_has_ext(env, RVH)) {
> > +            target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
> > +
> > +            if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
> > +                !riscv_cpu_force_hs_excep_enabled(env)) {
> > +                /* Trap to VS mode */
> > +            } else if (riscv_cpu_virt_enabled(env)) {
> > +                /* Trap into HS mode, from virt */
> > +                riscv_cpu_swap_hypervisor_regs(env);
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
> > +                                         get_field(env->hstatus, HSTATUS_SPV));
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
> > +                                         get_field(*env->mstatus, SSTATUS_SPP));
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
> > +                                         riscv_cpu_virt_enabled(env));
> > +
> > +                riscv_cpu_set_virt_enabled(env, 0);
> > +                riscv_cpu_set_force_hs_excep(env, 0);
> > +            } else {
> > +                /* Trap into HS mode */
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
> > +                                         get_field(env->hstatus, HSTATUS_SPV));
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
> > +                                         get_field(*env->mstatus, SSTATUS_SPP));
> > +                env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
> > +                                         riscv_cpu_virt_enabled(env));
> > +            }
> > +        }
> > +
> > +        s = *env->mstatus;
> >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >=
> > PRIV_VERSION_1_10_0 ?
> >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
> >          s = set_field(s, MSTATUS_SPP, env->priv); @@ -704,7 +736,20 @@ void
> > riscv_cpu_do_interrupt(CPUState *cs)
> >          riscv_cpu_set_mode(env, PRV_S);
> >      } else {
> >          /* handle the trap in M-mode */
> > -        target_ulong s = *env->mstatus;
> > +        if (riscv_has_ext(env, RVH)) {
> > +            if (riscv_cpu_virt_enabled(env)) {
> > +                riscv_cpu_swap_hypervisor_regs(env);
> > +            }
> > +            *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
> > +                                      riscv_cpu_virt_enabled(env));
> > +            *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
> > +
> > + riscv_cpu_force_hs_excep_enabled(env));
> > +
> > +            /* Trapping to M mode, virt is disabled */
> > +            riscv_cpu_set_virt_enabled(env, 0);
> > +        }
> > +
> > +        s = *env->mstatus;
> >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >=
> > PRIV_VERSION_1_10_0 ?
> >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env-
> > >priv));
> >          s = set_field(s, MSTATUS_MPP, env->priv);
> > --
> > 2.24.0
> >
>


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers
  2020-01-31 17:31     ` Alistair Francis
@ 2020-02-01  0:09       ` Alistair Francis
  0 siblings, 0 replies; 78+ messages in thread
From: Alistair Francis @ 2020-02-01  0:09 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: Alistair Francis, open list:RISC-V, qemu-devel@nongnu.org Developers

On Fri, Jan 31, 2020 at 9:31 AM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Thu, Jan 30, 2020 at 6:48 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
> >
> > On Tue, 21 Jan 2020 11:02:01 GMT (+0000), alistair23@gmail.com wrote:
> > > On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
> > >>
> > >> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> > >> > To handle the new Hypervisor CSR register aliasing let's use pointers.
> > >>
> > >> For some reason I thought we were making this explicit?  In other words,
> > >> requiring that all callers provide which privilege mode they're using when
> > >> accessing these CSRs, as opposed to swapping around pointers.  I don't actually
> > >> care that much, but IIRC when we were talking with the ARM guys at Plumbers
> > >> they were pretty adament that would end up being a much cleaner implementation
> > >> as they'd tried this way and later changed over.
> > >
> > > I think their implementation is different so it doesn't apply the same here.
> > >
> > > My main concern is that due to the modularity of RISC-V I don't expect
> > > all future developers to keep track of the Hypervisor extensions. This
> > > way we always have the correct state in the registers.
> > >
> > > There is only one pointer variable left, so we could drop the pointer
> > > swapping part, but for now it's still here.
> >
> > OK, so in the interest of moving things forwards let's just
> >
> > Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
>
> Thanks
>
> >
> > so we can merge this -- it's too big of a patch set to wait around on something
> > so small for.  I think that was the last one missing a review, right?
>
> I have made one small change and dismissed your review from a patch,
> it also looks like one patch hasn't been reviewed either.
>
> I'll send a v2 later today that has been rebased on master.

After rebasing everything stopped working. While attempting to fix the
problem I remeoved this patch and managed to get it working again. So
now in v2 there are no CSR pointers, just value swapping for
everything.

I fixed a few bugs that I noticed related to FP, I have cleared your
review Palmer from a few patches. I'll send the v2 for review soon.
It's pretty similar to the v1 so should be easy to review.

Alistair

>
> Alistair
>
> >
> > >
> > > Alistair
> > >
> > >>
> > >> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > >> > ---
> > >> >  target/riscv/cpu.c        | 11 +++++++++--
> > >> >  target/riscv/cpu.h        |  9 ++++++++-
> > >> >  target/riscv/cpu_helper.c | 30 +++++++++++++++---------------
> > >> >  target/riscv/csr.c        | 20 ++++++++++----------
> > >> >  target/riscv/op_helper.c  | 14 +++++++-------
> > >> >  5 files changed, 49 insertions(+), 35 deletions(-)
> > >> >
> > >> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > >> > index a07c5689b3..e61cf46a73 100644
> > >> > --- a/target/riscv/cpu.c
> > >> > +++ b/target/riscv/cpu.c
> > >> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> > >> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
> > >> >  #ifndef CONFIG_USER_ONLY
> > >> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> > >> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
> > >> > +    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
> > >> >      if (riscv_has_ext(env, RVH)) {
> > >> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
> > >> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
> > >> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> > >> >      mcc->parent_reset(cs);
> > >> >  #ifndef CONFIG_USER_ONLY
> > >> >      env->priv = PRV_M;
> > >> > -    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > >> > +    *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > >> >      env->mcause = 0;
> > >> >      env->pc = env->resetvec;
> > >> >  #endif
> > >> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
> > >> >  static void riscv_cpu_init(Object *obj)
> > >> >  {
> > >> >      RISCVCPU *cpu = RISCV_CPU(obj);
> > >> > +#ifndef CONFIG_USER_ONLY
> > >> > +    CPURISCVState *env = &cpu->env;
> > >> > +#endif
> > >> >
> > >> >      cpu_set_cpustate_pointers(cpu);
> > >> > +
> > >> > +#ifndef CONFIG_USER_ONLY
> > >> > +    env->mstatus = &env->mstatus_novirt;
> > >> > +#endif
> > >> >  }
> > >> >
> > >> >  static const VMStateDescription vmstate_riscv_cpu = {
> > >> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > >> > index 21ae5a8b19..9dc8303c62 100644
> > >> > --- a/target/riscv/cpu.h
> > >> > +++ b/target/riscv/cpu.h
> > >> > @@ -122,7 +122,7 @@ struct CPURISCVState {
> > >> >      target_ulong resetvec;
> > >> >
> > >> >      target_ulong mhartid;
> > >> > -    target_ulong mstatus;
> > >> > +    target_ulong *mstatus;
> > >> >
> > >> >      target_ulong mip;
> > >> >      uint32_t miclaim;
> > >> > @@ -145,6 +145,13 @@ struct CPURISCVState {
> > >> >      target_ulong mcause;
> > >> >      target_ulong mtval;  /* since: priv-1.10.0 */
> > >> >
> > >> > +    /* The following registers are the "real" versions that the pointer
> > >> > +     * versions point to. These should never be used unless you know what you
> > >> > +     * are doing. To access these use the pointer versions instead. This is
> > >> > +     * required to handle the Hypervisor register swapping.
> > >> > +     */
> > >> > +    target_ulong mstatus_novirt;
> > >> > +
> > >> >      /* Hypervisor CSRs */
> > >> >      target_ulong hstatus;
> > >> >      target_ulong hedeleg;
> > >> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > >> > index b00f66824a..9684da7f7d 100644
> > >> > --- a/target/riscv/cpu_helper.c
> > >> > +++ b/target/riscv/cpu_helper.c
> > >> > @@ -37,8 +37,8 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
> > >> >  #ifndef CONFIG_USER_ONLY
> > >> >  static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> > >> >  {
> > >> > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> > >> > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> > >> > +    target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
> > >> > +    target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
> > >> >      target_ulong pending = env->mip & env->mie;
> > >> >      target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
> > >> >      target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
> > >> > @@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
> > >> >  /* Return true is floating point support is currently enabled */
> > >> >  bool riscv_cpu_fp_enabled(CPURISCVState *env)
> > >> >  {
> > >> > -    if (env->mstatus & MSTATUS_FS) {
> > >> > +    if (*env->mstatus & MSTATUS_FS) {
> > >> >          return true;
> > >> >      }
> > >> >
> > >> > @@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> > >> >      int mode = mmu_idx;
> > >> >
> > >> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > >> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > >> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > >> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > >> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> > >> >          }
> > >> >      }
> > >> >
> > >> > @@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> > >> >
> > >> >      hwaddr base;
> > >> >      int levels, ptidxbits, ptesize, vm, sum;
> > >> > -    int mxr = get_field(env->mstatus, MSTATUS_MXR);
> > >> > +    int mxr = get_field(*env->mstatus, MSTATUS_MXR);
> > >> >
> > >> >      if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> > >> >          base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
> > >> > -        sum = get_field(env->mstatus, MSTATUS_SUM);
> > >> > +        sum = get_field(*env->mstatus, MSTATUS_SUM);
> > >> >          vm = get_field(env->satp, SATP_MODE);
> > >> >          switch (vm) {
> > >> >          case VM_1_10_SV32:
> > >> > @@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> > >> >          }
> > >> >      } else {
> > >> >          base = (hwaddr)(env->sptbr) << PGSHIFT;
> > >> > -        sum = !get_field(env->mstatus, MSTATUS_PUM);
> > >> > -        vm = get_field(env->mstatus, MSTATUS_VM);
> > >> > +        sum = !get_field(*env->mstatus, MSTATUS_PUM);
> > >> > +        vm = get_field(*env->mstatus, MSTATUS_VM);
> > >> >          switch (vm) {
> > >> >          case VM_1_09_SV32:
> > >> >            levels = 2; ptidxbits = 10; ptesize = 4; break;
> > >> > @@ -492,8 +492,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> > >> >      ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
> > >> >
> > >> >      if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> > >> > -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> > >> > -            mode = get_field(env->mstatus, MSTATUS_MPP);
> > >> > +        if (get_field(*env->mstatus, MSTATUS_MPRV)) {
> > >> > +            mode = get_field(*env->mstatus, MSTATUS_MPP);
> > >> >          }
> > >> >      }
> > >> >
> > >> > @@ -599,12 +599,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >> >      if (env->priv <= PRV_S &&
> > >> >              cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> > >> >          /* handle the trap in S-mode */
> > >> > -        target_ulong s = env->mstatus;
> > >> > +        target_ulong s = *env->mstatus;
> > >> >          s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > >> >              get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
> > >> >          s = set_field(s, MSTATUS_SPP, env->priv);
> > >> >          s = set_field(s, MSTATUS_SIE, 0);
> > >> > -        env->mstatus = s;
> > >> > +        *env->mstatus = s;
> > >> >          env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
> > >> >          env->sepc = env->pc;
> > >> >          env->sbadaddr = tval;
> > >> > @@ -613,12 +613,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >> >          riscv_cpu_set_mode(env, PRV_S);
> > >> >      } else {
> > >> >          /* handle the trap in M-mode */
> > >> > -        target_ulong s = env->mstatus;
> > >> > +        target_ulong s = *env->mstatus;
> > >> >          s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > >> >              get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
> > >> >          s = set_field(s, MSTATUS_MPP, env->priv);
> > >> >          s = set_field(s, MSTATUS_MIE, 0);
> > >> > -        env->mstatus = s;
> > >> > +        *env->mstatus = s;
> > >> >          env->mcause = cause | ~(((target_ulong)-1) >> async);
> > >> >          env->mepc = env->pc;
> > >> >          env->mbadaddr = tval;
> > >> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > >> > index 74e911af08..a4b598d49a 100644
> > >> > --- a/target/riscv/csr.c
> > >> > +++ b/target/riscv/csr.c
> > >> > @@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
> > >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >> >          return -1;
> > >> >      }
> > >> > -    env->mstatus |= MSTATUS_FS;
> > >> > +    *env->mstatus |= MSTATUS_FS;
> > >> >  #endif
> > >> >      riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> > >> >      return 0;
> > >> > @@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
> > >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >> >          return -1;
> > >> >      }
> > >> > -    env->mstatus |= MSTATUS_FS;
> > >> > +    *env->mstatus |= MSTATUS_FS;
> > >> >  #endif
> > >> >      env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
> > >> >      return 0;
> > >> > @@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
> > >> >      if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
> > >> >          return -1;
> > >> >      }
> > >> > -    env->mstatus |= MSTATUS_FS;
> > >> > +    *env->mstatus |= MSTATUS_FS;
> > >> >  #endif
> > >> >      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> > >> >      riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> > >> > @@ -313,7 +313,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
> > >> >  /* Machine Trap Setup */
> > >> >  static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
> > >> >  {
> > >> > -    *val = env->mstatus;
> > >> > +    *val = *env->mstatus;
> > >> >      return 0;
> > >> >  }
> > >> >
> > >> > @@ -325,7 +325,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
> > >> >
> > >> >  static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> > >> >  {
> > >> > -    target_ulong mstatus = env->mstatus;
> > >> > +    target_ulong mstatus = *env->mstatus;
> > >> >      target_ulong mask = 0;
> > >> >      int dirty;
> > >> >
> > >> > @@ -365,7 +365,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
> > >> >               ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
> > >> >              ((mstatus & MSTATUS_XS) == MSTATUS_XS);
> > >> >      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> > >> > -    env->mstatus = mstatus;
> > >> > +    *env->mstatus = mstatus;
> > >> >
> > >> >      return 0;
> > >> >  }
> > >> > @@ -614,7 +614,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
> > >> >  {
> > >> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> > >> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > >> > -    *val = env->mstatus & mask;
> > >> > +    *val = *env->mstatus & mask;
> > >> >      return 0;
> > >> >  }
> > >> >
> > >> > @@ -622,7 +622,7 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
> > >> >  {
> > >> >      target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
> > >> >                           sstatus_v1_10_mask : sstatus_v1_9_mask);
> > >> > -    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
> > >> > +    target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
> > >> >      return write_mstatus(env, CSR_MSTATUS, newval);
> > >> >  }
> > >> >
> > >> > @@ -737,7 +737,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
> > >> >      if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> > >> >          *val = 0;
> > >> >      } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
> > >> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> > >> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> > >> >              return -1;
> > >> >          } else {
> > >> >              *val = env->satp;
> > >> > @@ -762,7 +762,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
> > >> >          validate_vm(env, get_field(val, SATP_MODE)) &&
> > >> >          ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
> > >> >      {
> > >> > -        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> > >> > +        if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
> > >> >              return -1;
> > >> >          } else {
> > >> >              if((val ^ env->satp) & SATP_ASID) {
> > >> > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> > >> > index 331cc36232..d150551bc9 100644
> > >> > --- a/target/riscv/op_helper.c
> > >> > +++ b/target/riscv/op_helper.c
> > >> > @@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> > >> >      }
> > >> >
> > >> >      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > >> > -        get_field(env->mstatus, MSTATUS_TSR)) {
> > >> > +        get_field(*env->mstatus, MSTATUS_TSR)) {
> > >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >> >      }
> > >> >
> > >> > -    target_ulong mstatus = env->mstatus;
> > >> > +    target_ulong mstatus = *env->mstatus;
> > >> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
> > >> >      mstatus = set_field(mstatus,
> > >> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > >> > @@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
> > >> >      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
> > >> >      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> > >> >      riscv_cpu_set_mode(env, prev_priv);
> > >> > -    env->mstatus = mstatus;
> > >> > +    *env->mstatus = mstatus;
> > >> >
> > >> >      return retpc;
> > >> >  }
> > >> > @@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> > >> >          riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> > >> >      }
> > >> >
> > >> > -    target_ulong mstatus = env->mstatus;
> > >> > +    target_ulong mstatus = *env->mstatus;
> > >> >      target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> > >> >      mstatus = set_field(mstatus,
> > >> >          env->priv_ver >= PRIV_VERSION_1_10_0 ?
> > >> > @@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
> > >> >      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
> > >> >      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> > >> >      riscv_cpu_set_mode(env, prev_priv);
> > >> > -    env->mstatus = mstatus;
> > >> > +    *env->mstatus = mstatus;
> > >> >
> > >> >      return retpc;
> > >> >  }
> > >> > @@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
> > >> >
> > >> >      if (env->priv == PRV_S &&
> > >> >          env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > >> > -        get_field(env->mstatus, MSTATUS_TW)) {
> > >> > +        get_field(*env->mstatus, MSTATUS_TW)) {
> > >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >> >      } else {
> > >> >          cs->halted = 1;
> > >> > @@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
> > >> >      if (!(env->priv >= PRV_S) ||
> > >> >          (env->priv == PRV_S &&
> > >> >           env->priv_ver >= PRIV_VERSION_1_10_0 &&
> > >> > -         get_field(env->mstatus, MSTATUS_TVM))) {
> > >> > +         get_field(*env->mstatus, MSTATUS_TVM))) {
> > >> >          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> > >> >      } else {
> > >> >          tlb_flush(cs);


^ permalink raw reply	[flat|nested] 78+ messages in thread

end of thread, other threads:[~2020-02-01  0:17 UTC | newest]

Thread overview: 78+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-09 18:10 [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Alistair Francis
2019-12-09 18:10 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Alistair Francis
2019-12-09 18:10 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Alistair Francis
2019-12-09 18:10 ` [PATCH v1 03/36] target/riscv: Add the Hypervisor extension Alistair Francis
2019-12-09 18:10 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Alistair Francis
2019-12-09 18:10 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Alistair Francis
2019-12-09 18:10 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Alistair Francis
2019-12-09 18:10 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Alistair Francis
2019-12-09 18:11 ` [PATCH v1 08/36] target/riscv: Add the force HS exception mode Alistair Francis
2019-12-09 18:11 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Alistair Francis
2019-12-09 18:11 ` [PATCH v1 10/36] target/riscv: Print priv and virt in disas log Alistair Francis
2019-12-09 18:11 ` [PATCH v1 11/36] target/riscv: Dump Hypervisor registers if enabled Alistair Francis
2019-12-09 18:11 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Alistair Francis
2019-12-09 18:11 ` [PATCH v1 13/36] target/riscv: Add Hypervisor virtual CSRs accesses Alistair Francis
2019-12-09 18:11 ` [PATCH v1 14/36] " Alistair Francis
2019-12-09 18:11 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Alistair Francis
2019-12-09 18:11 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Alistair Francis
2019-12-09 18:11 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Alistair Francis
2019-12-09 18:11 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Alistair Francis
2019-12-09 18:11 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Alistair Francis
2019-12-09 18:11 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Alistair Francis
2019-12-09 18:11 ` [PATCH v1 21/36] target/ricsv: Flush the TLB on virtulisation mode changes Alistair Francis
2019-12-09 18:11 ` [PATCH v1 22/36] target/riscv: Generate illegal instruction on WFI when V=1 Alistair Francis
2019-12-09 18:11 ` [PATCH v1 23/36] target/riscv: Add hypvervisor trap support Alistair Francis
2020-01-20  8:34   ` Jiangyifei
2020-01-31 21:25     ` Alistair Francis
2019-12-09 18:11 ` [PATCH v1 24/36] target/riscv: Add Hypervisor trap return support Alistair Francis
2019-12-09 18:11 ` [PATCH v1 25/36] target/riscv: Add hfence instructions Alistair Francis
2019-12-09 18:11 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Alistair Francis
2019-12-09 18:11 ` [PATCH v1 27/36] target/riscv: Disable guest FP support based on virtual status Alistair Francis
2019-12-09 18:11 ` [PATCH v1 28/36] target/riscv: Mark both sstatus and vsstatus as dirty Alistair Francis
2019-12-09 18:11 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Alistair Francis
2019-12-09 18:11 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Alistair Francis
2019-12-09 18:12 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Alistair Francis
2019-12-09 18:12 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Alistair Francis
2019-12-09 18:12 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Alistair Francis
2019-12-09 18:12 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Alistair Francis
2019-12-09 18:12 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Alistair Francis
2019-12-09 18:12 ` [PATCH v1 36/36] target/riscv: Allow enabling the Hypervisor extension Alistair Francis
2019-12-09 22:55 ` [PATCH v1 00/36] Add RISC-V Hypervisor Extension v0.5 Aleksandar Markovic
2019-12-10  0:03   ` Alistair Francis
2019-12-10 19:05     ` Aleksandar Markovic
2020-01-02 18:18 ` [PATCH v1 01/36] target/riscv: Convert MIP CSR to target_ulong Palmer Dabbelt
2020-01-03  2:08   ` Alistair Francis
2020-01-06 17:51 ` [PATCH v1 02/36] target/riscv: Don't set write permissions on dirty PTEs Palmer Dabbelt
2020-01-07  1:33   ` Alistair Francis
2020-01-07 18:28 ` [PATCH v1 04/36] target/riscv: Add the Hypervisor CSRs to CPUState Palmer Dabbelt
2020-01-07 18:28 ` [PATCH v1 05/36] target/riscv: Add support for the new execption numbers Palmer Dabbelt
2020-01-07 18:28 ` [PATCH v1 06/36] target/riscv: Rename the H irqs to VS irqs Palmer Dabbelt
2020-01-07 18:28 ` [PATCH v1 07/36] target/riscv: Add the virtulisation mode Palmer Dabbelt
2020-01-08  0:06 ` [PATCH v1 09/36] target/riscv: Fix CSR perm checking for HS mode Palmer Dabbelt
2020-01-08  0:07 ` [PATCH v1 12/36] target/riscv: Add Hypervisor CSR access functions Palmer Dabbelt
2020-01-08  0:07 ` [PATCH v1 14/36] target/riscv: Add Hypervisor virtual CSRs accesses Palmer Dabbelt
2020-01-08  1:30 ` [PATCH v1 15/36] target/riscv: Convert mstatus to pointers Palmer Dabbelt
2020-01-21 11:02   ` Alistair Francis
2020-01-21 12:56     ` Jonathan Behrens
2020-01-22  0:00       ` Alistair Francis
2020-01-22 22:13         ` Jonathan Behrens
2020-01-30 14:48   ` Palmer Dabbelt
2020-01-31 17:31     ` Alistair Francis
2020-02-01  0:09       ` Alistair Francis
2020-01-08  2:07 ` [PATCH v1 16/36] target/riscv: Add virtual register swapping function Palmer Dabbelt
2020-01-08  2:07 ` [PATCH v1 17/36] target/riscv: Set VS bits in mideleg for Hyp extension Palmer Dabbelt
2020-01-21 11:11   ` Alistair Francis
2020-01-21 11:29     ` Anup Patel
2020-01-08 20:25 ` [PATCH v1 18/36] target/riscv: Extend the MIE CSR to support virtulisation Palmer Dabbelt
2020-01-09  0:49 ` [PATCH v1 19/36] target/riscv: Extend the SIP " Palmer Dabbelt
2020-01-09  0:49 ` [PATCH v1 26/36] target/riscv: Remove the hret instruction Palmer Dabbelt
2020-01-09  0:49 ` [PATCH v1 20/36] target/riscv: Add support for virtual interrupt setting Palmer Dabbelt
2020-01-09  2:33   ` Richard Henderson
2020-01-10 23:21   ` Palmer Dabbelt
2020-01-09  0:58 ` [PATCH v1 29/36] target/riscv: Respect MPRV and SPRV for floating point ops Palmer Dabbelt
2020-01-09  1:41 ` [PATCH v1 30/36] target/riscv: Allow specifying MMU stage Palmer Dabbelt
2020-01-09  2:01 ` [PATCH v1 31/36] target/riscv: Implement second stage MMU Palmer Dabbelt
2020-01-09  2:29 ` [PATCH v1 32/36] target/riscv: Raise the new execptions when 2nd stage translation fails Palmer Dabbelt
2020-01-09  2:29 ` [PATCH v1 33/36] target/riscv: Set htval and mtval2 on execptions Palmer Dabbelt
2020-01-09  2:29 ` [PATCH v1 34/36] target/riscv: Add support for the 32-bit MSTATUSH CSR Palmer Dabbelt
2020-01-09  2:36 ` [PATCH v1 35/36] target/riscv: Add the MSTATUS_MPV_ISSET helper macro Palmer Dabbelt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).