All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates
@ 2018-05-23  0:14 Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
                   ` (29 more replies)
  0 siblings, 30 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Alistair Francis, Bastian Koppelmann,
	Palmer Dabbelt, Sagar Karandikar

This is a series of bug fixes, specification conformance
fixes and CPU feature modularily updates to allow more
precise modelling of the SiFive U Series CPUs (multi-core
application processors with MMU, Supervisor and User modes)
and SiFive E Series CPUs (embedded microcontroller cores
without MMU or Supervisor mode). This series adds several
updates to CPU features such as writable 'misa', minimal
hypervisor support for mstatus.TSR/TW/TVM, a new modular
interface for truly atomic CSRs, bug fixes and several
new features such as separate firmware and kernel payload.

These changes are available in the RISC-V GitHub repo:

- https://github.com/riscv/riscv-qemu/tree/qemu-2.13-for-upstream

Summary of changes

* Support separate firmware and kernel payload
  * Can use -bios bbl -kernel vmlinux on 'virt' machine
* Add infrastructure to support runtime 'misa' writes
* Implemented TSR, TW and TVM for privileged ISA v1.10
* Update floating-point to correctly mark mstatus.FS dirty.
* Made PMP (Physical Memory Protection) an optional CPU feature.
* Disabled access to s* CSRs on cores without misa.S set.
* Added CSR feature predicates to improve CPU emulation support
  and to allow for easier CPU model differentiation.
  * SiFive U series application processors (MMU, S-mode, U-mode)
  * SiFive E series embedded microcontrollers (no MMU, U-mode)
* Add non-trapping interface to CSRs so that gdbstub.c can
  accesses CSRs without longjmp being called.
* Implements an interface for atomic CSR accesses and convert
  accesses to 'mip' and 'sip' to the atomic interface:
  * The previous implementation using separate methods for
    csr_read_helper and csr_write_helper was incompatible
    with atomic CSR accesses. The previous implementation
    used monolithic switch statements and was not modular.
  * Add public API so that CPUs can implement custom CSRs.
* Replaces locks with atomic lock-free updates for interrupt
  * Reduce idle Linux SMP CPU usage by up to 35%.
  * Increases CPU performance under load by up to 15%.
* Improved specification conformance of the page table walker
  * Change access checks from ternary operator to if statements.
  * Checks for misaligned PPNs.
  * Disallow M-mode or S-mode from fetching from User pages.
  * Adds reserved PTE flag check: W or W|X.
  * Set READ flag for PTE X flag if mstatus.mxr is in effect.
  * Improves page walker comments and code readability .

Testing Coverage

* Linux Fedora SMP mstatus.FS scheduler test: pass
* Linux Fedora SMP MTTCG tests (~22 hr GCC bootstrap): pass
* spike_v1.9.1 bbl/linux-4.6.2 board test: pass
* spike_v1.10 bbl/linux-4.14 board test: pass
* virt bbl/linux-4.16-rc2 board test: pass
* sifive_e board test (HiFive1 binaries): pass
* sifive_u board test (HiFive Unleashed): pass
* riscv-tests: pass
* checkpatch: pass

Kito Cheng (1):
  RISC-V: linux-user support for RVE ABI

Michael Clark (27):
  RISC-V: Update address bits to support sv39 and sv48
  RISC-V: Improve page table walker spec compliance
  RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  RISC-V: Simplify riscv_cpu_local_irqs_pending
  RISC-V: Allow setting and clearing multiple irqs
  RISC-V: Move non-ops from op_helper to cpu_helper
  RISC-V: Update CSR and interrupt definitions
  RISC-V: Implement modular CSR helper interface
  RISC-V: Implement atomic mip/sip CSR updates
  RISC-V: Implement existential predicates for CSRs
  RISC-V: Implement mstatus.TSR/TW/TVM
  RISC-V: Add public API for the CSR dispatch table
  RISC-V: Add hartid and \n to interrupt logging
  RISC-V: Use riscv prefix consistently on cpu helpers
  RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
  RISC-V: Add missing free for plic_hart_config
  RISC-V: Allow interrupt controllers to claim interrupts
  RISC-V: Add misa to DisasContext
  RISC-V: Add misa.MAFD checks to translate
  RISC-V: Add misa runtime write support
  RISC-V: Fix CLINT timecmp low 32-bit writes
  RISC-V: Fix PLIC pending bitfield reads
  RISC-V: Enable second UART on sifive_e and sifive_u
  RISC-V: Remove unnecessary disassembler constraints
  elf: Add RISC-V PSABI ELF header defines
  RISC-V: Don't add NULL bootargs to device-tree
  RISC-V: Support separate firmware and kernel payload

Richard Henderson (2):
  RISC-V: Split out mstatus_fs from tb_flags
  RISC-V: Mark mstatus.fs dirty

 disas/riscv.c                           | 138 -----
 hw/riscv/Makefile.objs                  |   1 +
 hw/riscv/boot.c                         | 172 ++++++
 hw/riscv/sifive_clint.c                 |  16 +-
 hw/riscv/sifive_e.c                     |   4 +-
 hw/riscv/sifive_plic.c                  |  72 +--
 hw/riscv/sifive_u.c                     |   8 +-
 hw/riscv/spike.c                        |   6 +-
 hw/riscv/virt.c                         |  73 +--
 include/elf.h                           |   8 +
 include/hw/riscv/boot.h                 |  30 ++
 include/hw/riscv/sifive_plic.h          |   1 -
 linux-user/riscv/cpu_loop.c             |  14 +-
 linux-user/riscv/signal.c               |   4 +-
 target/riscv/Makefile.objs              |   2 +-
 target/riscv/cpu.c                      |   8 +-
 target/riscv/cpu.h                      |  98 +++-
 target/riscv/cpu_bits.h                 | 701 +++++++++++++-----------
 target/riscv/{helper.c => cpu_helper.c} | 177 ++++--
 target/riscv/cpu_user.h                 |   3 +-
 target/riscv/csr.c                      | 921 ++++++++++++++++++++++++++++++++
 target/riscv/fpu_helper.c               |   6 +-
 target/riscv/gdbstub.c                  |  10 +-
 target/riscv/op_helper.c                | 680 ++---------------------
 target/riscv/translate.c                | 286 ++++++++--
 25 files changed, 2103 insertions(+), 1336 deletions(-)
 create mode 100644 hw/riscv/boot.c
 create mode 100644 include/hw/riscv/boot.h
 rename target/riscv/{helper.c => cpu_helper.c} (74%)
 create mode 100644 target/riscv/csr.c

-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-25 15:07   ` Richard Henderson
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance Michael Clark
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
---
 target/riscv/cpu.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 34abc383e3d4..e0608e6d5f08 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -24,12 +24,12 @@
 #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */
 #if defined(TARGET_RISCV64)
 #define TARGET_LONG_BITS 64
-#define TARGET_PHYS_ADDR_SPACE_BITS 50
-#define TARGET_VIRT_ADDR_SPACE_BITS 39
+#define TARGET_PHYS_ADDR_SPACE_BITS 56 /* 44-bit PPN */
+#define TARGET_VIRT_ADDR_SPACE_BITS 48 /* sv48 */
 #elif defined(TARGET_RISCV32)
 #define TARGET_LONG_BITS 32
-#define TARGET_PHYS_ADDR_SPACE_BITS 34
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#define TARGET_PHYS_ADDR_SPACE_BITS 34 /* 22-bit PPN */
+#define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */
 #endif
 
 #define TCG_GUEST_DEFAULT_MO 0
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23 22:31   ` Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

- Inline PTE_TABLE check for better readability
- Change access checks from ternary operator to if
- Improve readibility of User page U mode and SUM test
- Disallow non U mode from fetching from User pages
- Add reserved PTE flag check: W or W|X
- Add misaligned PPN check
- Set READ protection for PTE X flag and mstatus.mxr
- Use memory_region_is_ram in pte update

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_bits.h |  2 --
 target/riscv/helper.c   | 64 ++++++++++++++++++++++++++++++++++---------------
 2 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 64aa097181fa..12b4757088f4 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -407,5 +407,3 @@
 #define PTE_SOFT  0x300 /* Reserved for Software */
 
 #define PTE_PPN_SHIFT 10
-
-#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
diff --git a/target/riscv/helper.c b/target/riscv/helper.c
index 95889f23b94d..3b57e1360549 100644
--- a/target/riscv/helper.c
+++ b/target/riscv/helper.c
@@ -185,16 +185,39 @@ restart:
 #endif
         target_ulong ppn = pte >> PTE_PPN_SHIFT;
 
-        if (PTE_TABLE(pte)) { /* next level of page table */
+        if (!(pte & PTE_V)) {
+            /* Invalid PTE */
+            return TRANSLATE_FAIL;
+        } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
+            /* Inner PTE, continue walking */
             base = ppn << PGSHIFT;
-        } else if ((pte & PTE_U) ? (mode == PRV_S) && !sum : !(mode == PRV_S)) {
-            break;
-        } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
-            break;
-        } else if (access_type == MMU_INST_FETCH ? !(pte & PTE_X) :
-                  access_type == MMU_DATA_LOAD ?  !(pte & PTE_R) &&
-                  !(mxr && (pte & PTE_X)) : !((pte & PTE_R) && (pte & PTE_W))) {
-            break;
+        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
+            /* Reserved leaf PTE flags: PTE_W */
+            return TRANSLATE_FAIL;
+        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
+            /* Reserved leaf PTE flags: PTE_W + PTE_X */
+            return TRANSLATE_FAIL;
+        } else if ((pte & PTE_U) && ((mode != PRV_U) &&
+                   (!sum || access_type == MMU_INST_FETCH))) {
+            /* User PTE flags when not U mode and mstatus.SUM is not set,
+               or the access type is an instruction fetch */
+            return TRANSLATE_FAIL;
+        } else if (!(pte & PTE_U) && (mode != PRV_S)) {
+            /* Supervisor PTE flags when not S mode */
+            return TRANSLATE_FAIL;
+        } else if (ppn & ((1ULL << ptshift) - 1)) {
+            /* Misasligned PPN */
+            return TRANSLATE_FAIL;
+        } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
+                   ((pte & PTE_X) && mxr))) {
+            /* Read access check failed */
+            return TRANSLATE_FAIL;
+        } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
+            /* Write access check failed */
+            return TRANSLATE_FAIL;
+        } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
+            /* Fetch access check failed */
+            return TRANSLATE_FAIL;
         } else {
             /* if necessary, set accessed and dirty bits. */
             target_ulong updated_pte = pte | PTE_A |
@@ -202,16 +225,19 @@ restart:
 
             /* Page table updates need to be atomic with MTTCG enabled */
             if (updated_pte != pte) {
-                /* if accessed or dirty bits need updating, and the PTE is
-                 * in RAM, then we do so atomically with a compare and swap.
-                 * if the PTE is in IO space, then it can't be updated.
-                 * if the PTE changed, then we must re-walk the page table
-                   as the PTE is no longer valid */
+                /*
+                 * - if accessed or dirty bits need updating, and the PTE is
+                 *   in RAM, then we do so atomically with a compare and swap.
+                 * - if the PTE is in IO space or ROM, then it can't be updated
+                 *   and we return TRANSLATE_FAIL.
+                 * - if the PTE changed by the time we went to update it, then
+                 *   it is no longer valid and we must re-walk the page table.
+                 */
                 MemoryRegion *mr;
                 hwaddr l = sizeof(target_ulong), addr1;
                 mr = address_space_translate(cs->as, pte_addr,
                     &addr1, &l, false);
-                if (memory_access_is_direct(mr, true)) {
+                if (memory_region_is_ram(mr)) {
                     target_ulong *pte_pa =
                         qemu_map_ram_ptr(mr->ram_block, addr1);
 #if TCG_OVERSIZED_GUEST
@@ -239,15 +265,15 @@ restart:
             target_ulong vpn = addr >> PGSHIFT;
             *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
 
-            if ((pte & PTE_R)) {
+            /* set permissions on the TLB entry */
+            if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
                 *prot |= PAGE_READ;
             }
             if ((pte & PTE_X)) {
                 *prot |= PAGE_EXEC;
             }
-           /* only add write permission on stores or if the page
-              is already dirty, so that we don't miss further
-              page table walks to update the dirty bit */
+            /* 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))) {
                 *prot |= PAGE_WRITE;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-29 23:32   ` Alistair Francis
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

The PLIC previously used a mutex to protect against concurrent
access to the claimed and pending bitfields. Instead of using
a mutex, we update the bitfields using atomic_cmpxchg.

Rename sifive_plic_num_irqs_pending to sifive_plic_irqs_pending
and add an early out if any interrupts are pending as the
count of pending interrupts is not used.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 hw/riscv/sifive_plic.c         | 49 +++++++++++++++++++-----------------------
 include/hw/riscv/sifive_plic.h |  1 -
 2 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 874de2ebaf77..1af23c76e603 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -81,36 +81,32 @@ static void sifive_plic_print_state(SiFivePLICState *plic)
     }
 }
 
-static
-void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
+static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
 {
-    qemu_mutex_lock(&plic->lock);
-    uint32_t word = irq >> 5;
-    if (pending) {
-        plic->pending[word] |= (1 << (irq & 31));
-    } else {
-        plic->pending[word] &= ~(1 << (irq & 31));
-    }
-    qemu_mutex_unlock(&plic->lock);
+    uint32_t old, new, cmp = atomic_read(a);
+
+    do {
+        old = cmp;
+        new = (old & ~mask) | (value & mask);
+        cmp = atomic_cmpxchg(a, old, new);
+    } while (old != cmp);
+
+    return old;
 }
 
-static
-void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
+static void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool level)
 {
-    qemu_mutex_lock(&plic->lock);
-    uint32_t word = irq >> 5;
-    if (claimed) {
-        plic->claimed[word] |= (1 << (irq & 31));
-    } else {
-        plic->claimed[word] &= ~(1 << (irq & 31));
-    }
-    qemu_mutex_unlock(&plic->lock);
+    atomic_set_masked(&plic->pending[irq >> 5], 1 << (irq & 31), -!!level);
 }
 
-static
-int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level)
 {
-    int i, j, count = 0;
+    atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level);
+}
+
+static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+{
+    int i, j;
     for (i = 0; i < plic->bitfield_words; i++) {
         uint32_t pending_enabled_not_claimed =
             (plic->pending[i] & ~plic->claimed[i]) &
@@ -123,11 +119,11 @@ int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
             uint32_t prio = plic->source_priority[irq];
             int enabled = pending_enabled_not_claimed & (1 << j);
             if (enabled && prio > plic->target_priority[addrid]) {
-                count++;
+                return 1;
             }
         }
     }
-    return count;
+    return 0;
 }
 
 static void sifive_plic_update(SiFivePLICState *plic)
@@ -143,7 +139,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
         if (!env) {
             continue;
         }
-        int level = sifive_plic_num_irqs_pending(plic, addrid) > 0;
+        int level = sifive_plic_irqs_pending(plic, addrid);
         switch (mode) {
         case PLICMode_M:
             riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
@@ -440,7 +436,6 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
     memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
                           TYPE_SIFIVE_PLIC, plic->aperture_size);
     parse_hart_config(plic);
-    qemu_mutex_init(&plic->lock);
     plic->bitfield_words = (plic->num_sources + 31) >> 5;
     plic->source_priority = g_new0(uint32_t, plic->num_sources);
     plic->target_priority = g_new(uint32_t, plic->num_addrs);
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 11a5a98df1f9..ff09a288261e 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -55,7 +55,6 @@ typedef struct SiFivePLICState {
     uint32_t *pending;
     uint32_t *claimed;
     uint32_t *enable;
-    QemuMutex lock;
     qemu_irq *irqs;
 
     /* config */
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (2 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-25 15:15   ` Richard Henderson
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs Michael Clark
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

This commit is intended to improve readability.
There is no change to the logic.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/helper.c | 34 ++++++++++++----------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/target/riscv/helper.c b/target/riscv/helper.c
index 3b57e1360549..47d116e9c13f 100644
--- a/target/riscv/helper.c
+++ b/target/riscv/helper.c
@@ -35,28 +35,18 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 }
 
 #ifndef CONFIG_USER_ONLY
-/*
- * Return RISC-V IRQ number if an interrupt should be taken, else -1.
- * Used in cpu-exec.c
- *
- * Adapted from Spike's processor_t::take_interrupt()
- */
-static int riscv_cpu_hw_interrupts_pending(CPURISCVState *env)
+static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
-    target_ulong pending_interrupts = atomic_read(&env->mip) & env->mie;
-
-    target_ulong mie = get_field(env->mstatus, MSTATUS_MIE);
-    target_ulong m_enabled = env->priv < PRV_M || (env->priv == PRV_M && mie);
-    target_ulong enabled_interrupts = pending_interrupts &
-                                      ~env->mideleg & -m_enabled;
-
-    target_ulong sie = get_field(env->mstatus, MSTATUS_SIE);
-    target_ulong s_enabled = env->priv < PRV_S || (env->priv == PRV_S && sie);
-    enabled_interrupts |= pending_interrupts & env->mideleg &
-                          -s_enabled;
-
-    if (enabled_interrupts) {
-        return ctz64(enabled_interrupts); /* since non-zero */
+    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
+    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
+    target_ulong pending = atomic_read(&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);
+
+    if (irqs) {
+        return ctz64(irqs); /* since non-zero */
     } else {
         return EXCP_NONE; /* indicates no pending interrupt */
     }
@@ -69,7 +59,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
     if (interrupt_request & CPU_INTERRUPT_HARD) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         CPURISCVState *env = &cpu->env;
-        int interruptno = riscv_cpu_hw_interrupts_pending(env);
+        int interruptno = riscv_cpu_local_irq_pending(env);
         if (interruptno >= 0) {
             cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
             riscv_cpu_do_interrupt(cs);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (3 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23 23:55   ` Alistair Francis
  2018-05-25 15:19   ` Richard Henderson
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
                   ` (24 subsequent siblings)
  29 siblings, 2 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Change the API of riscv_set_local_interrupt to take a
write mask and value to allow setting and clearing of
multiple local interrupts atomically in a single call.
Rename the new function to riscv_cpu_update_mip.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_clint.c  |  8 ++++----
 hw/riscv/sifive_plic.c   |  4 ++--
 target/riscv/cpu.h       | 22 +++++++++++++---------
 target/riscv/op_helper.c | 24 +++++++++++++++---------
 4 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 7cc606e06546..0d2fd52487e6 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/riscv/sifive_clint.c
@@ -47,12 +47,12 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
     if (cpu->env.timecmp <= rtc_r) {
         /* if we're setting an MTIMECMP value in the "past",
            immediately raise the timer interrupt */
-        riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
+        riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
         return;
     }
 
     /* otherwise, set up the future timer interrupt */
-    riscv_set_local_interrupt(cpu, MIP_MTIP, 0);
+    riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
     diff = cpu->env.timecmp - rtc_r;
     /* back to ns (note args switched in muldiv64) */
     next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
@@ -67,7 +67,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
 static void sifive_clint_timer_cb(void *opaque)
 {
     RISCVCPU *cpu = opaque;
-    riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
+    riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
 }
 
 /* CPU wants to read rtc or timecmp register */
@@ -132,7 +132,7 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
         if (!env) {
             error_report("clint: invalid timecmp hartid: %zu", hartid);
         } else if ((addr & 0x3) == 0) {
-            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MSIP, value != 0);
+            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MSIP, BOOL_TO_MASK(value));
         } else {
             error_report("clint: invalid sip write: %08x", (uint32_t)addr);
         }
diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 1af23c76e603..b267ff88902d 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -142,10 +142,10 @@ static void sifive_plic_update(SiFivePLICState *plic)
         int level = sifive_plic_irqs_pending(plic, addrid);
         switch (mode) {
         case PLICMode_M:
-            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
+            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
             break;
         case PLICMode_S:
-            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_SEIP, level);
+            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level));
             break;
         default:
             break;
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e0608e6d5f08..c5d485769cde 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -126,13 +126,18 @@ struct CPURISCVState {
 
     target_ulong mhartid;
     target_ulong mstatus;
+
     /*
      * CAUTION! Unlike the rest of this struct, mip is accessed asynchonously
-     * by I/O threads and other vCPUs, so hold the iothread mutex before
-     * operating on it.  CPU_INTERRUPT_HARD should be in effect iff this is
-     * non-zero.  Use riscv_cpu_set_local_interrupt.
+     * by I/O threads. It should be read with atomic_read. It should be updated
+     * using riscv_cpu_update_mip with the iothread mutex held. The iothread
+     * mutex must be held because mip must be consistent with the CPU inturrept
+     * state. riscv_cpu_update_mip calls cpu_interrupt or cpu_reset_interrupt
+     * wuth the invariant that CPU_INTERRUPT_HARD is set iff mip is non-zero.
+     * mip is 32-bits to allow atomic_read on 32-bit hosts.
      */
-    uint32_t mip;        /* allow atomic_read for >= 32-bit hosts */
+    uint32_t mip;
+
     target_ulong mie;
     target_ulong mideleg;
 
@@ -247,7 +252,6 @@ void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
                                     uintptr_t retaddr);
 int riscv_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
                               int rw, int mmu_idx);
-
 char *riscv_isa_string(RISCVCPU *cpu);
 void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
@@ -256,6 +260,10 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #define cpu_list riscv_cpu_list
 #define cpu_mmu_index riscv_cpu_mmu_index
 
+#ifndef CONFIG_USER_ONLY
+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 */
+#endif
 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
 
 void riscv_translate_init(void);
@@ -286,10 +294,6 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         target_ulong csrno);
 target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno);
 
-#ifndef CONFIG_USER_ONLY
-void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value);
-#endif
-
 #include "exec/cpu-all.h"
 
 #endif /* RISCV_CPU_H */
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 3abf52453cfc..5a02795bf931 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -171,10 +171,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
          */
         qemu_mutex_lock_iothread();
         RISCVCPU *cpu = riscv_env_get_cpu(env);
-        riscv_set_local_interrupt(cpu, MIP_SSIP,
-                                  (val_to_write & MIP_SSIP) != 0);
-        riscv_set_local_interrupt(cpu, MIP_STIP,
-                                  (val_to_write & MIP_STIP) != 0);
+        riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
+                                  (val_to_write & (MIP_SSIP | MIP_STIP)));
         /*
          * csrs, csrc on mip.SEIP is not decomposable into separate read and
          * write steps, so a different implementation is needed
@@ -655,16 +653,24 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
 #ifndef CONFIG_USER_ONLY
 
 /* iothread_mutex must be held */
-void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value)
+uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
 {
-    target_ulong old_mip = cpu->env.mip;
-    cpu->env.mip = (old_mip & ~mask) | (value ? mask : 0);
+    CPURISCVState *env = &cpu->env;
+    uint32_t old, new, cmp = atomic_read(&env->mip);
 
-    if (cpu->env.mip && !old_mip) {
+    do {
+        old = cmp;
+        new = (old & ~mask) | (value & mask);
+        cmp = atomic_cmpxchg(&env->mip, old, new);
+    } while (old != cmp);
+
+    if (new && !old) {
         cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    } else if (!cpu->env.mip && old_mip) {
+    } else if (!new && old) {
         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
     }
+
+    return old;
 }
 
 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (4 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23 12:23   ` Philippe Mathieu-Daudé
  2018-05-25 15:20   ` Richard Henderson
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 07/30] RISC-V: Update CSR and interrupt definitions Michael Clark
                   ` (23 subsequent siblings)
  29 siblings, 2 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

This patch makes op_helper.c contain only instruction
operation helpers used by translate.c and moves any
unrelated cpu helpers into cpu_helper.c. No logic is
changed by this patch.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/Makefile.objs              |  2 +-
 target/riscv/{helper.c => cpu_helper.c} | 35 ++++++++++++++++++++++++++++++++-
 target/riscv/op_helper.c                | 34 --------------------------------
 3 files changed, 35 insertions(+), 36 deletions(-)
 rename target/riscv/{helper.c => cpu_helper.c} (95%)

diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index abd0a7cde333..fcc5d34c1f2e 100644
--- a/target/riscv/Makefile.objs
+++ b/target/riscv/Makefile.objs
@@ -1 +1 @@
-obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o gdbstub.o pmp.o
+obj-y += translate.o op_helper.o cpu_helper.o cpu.o fpu_helper.o gdbstub.o pmp.o
diff --git a/target/riscv/helper.c b/target/riscv/cpu_helper.c
similarity index 95%
rename from target/riscv/helper.c
rename to target/riscv/cpu_helper.c
index 47d116e9c13f..6c886e99055a 100644
--- a/target/riscv/helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1,5 +1,5 @@
 /*
- * RISC-V emulation helpers for qemu.
+ * RISC-V CPU helpers for qemu.
  *
  * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
  * Copyright (c) 2017-2018 SiFive, Inc.
@@ -72,6 +72,39 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 
 #if !defined(CONFIG_USER_ONLY)
 
+/* iothread_mutex must be held */
+uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
+{
+    CPURISCVState *env = &cpu->env;
+    uint32_t old, new, cmp = atomic_read(&env->mip);
+
+    do {
+        old = cmp;
+        new = (old & ~mask) | (value & mask);
+        cmp = atomic_cmpxchg(&env->mip, old, new);
+    } while (old != cmp);
+
+    if (new && !old) {
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+    } else if (!new && old) {
+        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+    }
+
+    return old;
+}
+
+void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
+{
+    if (newpriv > PRV_M) {
+        g_assert_not_reached();
+    }
+    if (newpriv == PRV_H) {
+        newpriv = PRV_U;
+    }
+    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
+    env->priv = newpriv;
+}
+
 /* get_physical_address - get the physical address for this virtual address
  *
  * Do a page table walk to obtain the physical address corresponding to a
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 5a02795bf931..2b9dd9da6486 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -652,39 +652,6 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
 
 #ifndef CONFIG_USER_ONLY
 
-/* iothread_mutex must be held */
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
-{
-    CPURISCVState *env = &cpu->env;
-    uint32_t old, new, cmp = atomic_read(&env->mip);
-
-    do {
-        old = cmp;
-        new = (old & ~mask) | (value & mask);
-        cmp = atomic_cmpxchg(&env->mip, old, new);
-    } while (old != cmp);
-
-    if (new && !old) {
-        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    } else if (!new && old) {
-        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    }
-
-    return old;
-}
-
-void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
-{
-    if (newpriv > PRV_M) {
-        g_assert_not_reached();
-    }
-    if (newpriv == PRV_H) {
-        newpriv = PRV_U;
-    }
-    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
-    env->priv = newpriv;
-}
-
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
 {
     if (!(env->priv >= PRV_S)) {
@@ -735,7 +702,6 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
     return retpc;
 }
 
-
 void helper_wfi(CPURISCVState *env)
 {
     CPUState *cs = CPU(riscv_env_get_cpu(env));
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 07/30] RISC-V: Update CSR and interrupt definitions
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (5 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 08/30] RISC-V: Implement modular CSR helper interface Michael Clark
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

* Add user-mode CSR defininitions.
* Reorder CSR definitions to match the specification.
* Change H mode interrupt comment to 'reserved'.
* Remove unused X_COP interrupt.
* Add user-mode and core-level interrupts.
* Remove erroneous until comemnts on machine mode interrupts.
* Move together paging mode and page table bit definitions.
* Move together interrupt and exception cause definitions.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu_bits.h  | 692 +++++++++++++++++++++++++----------------------
 target/riscv/op_helper.c |   4 +-
 2 files changed, 376 insertions(+), 320 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 12b4757088f4..878de6233846 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -6,242 +6,283 @@
                  (((target_ulong)(val) * ((mask) & ~((mask) << 1))) & \
                  (target_ulong)(mask)))
 
-#define PGSHIFT 12
-
-#define FSR_RD_SHIFT 5
-#define FSR_RD   (0x7 << FSR_RD_SHIFT)
-
-#define FPEXC_NX 0x01
-#define FPEXC_UF 0x02
-#define FPEXC_OF 0x04
-#define FPEXC_DZ 0x08
-#define FPEXC_NV 0x10
-
-#define FSR_AEXC_SHIFT 0
-#define FSR_NVA  (FPEXC_NV << FSR_AEXC_SHIFT)
-#define FSR_OFA  (FPEXC_OF << FSR_AEXC_SHIFT)
-#define FSR_UFA  (FPEXC_UF << FSR_AEXC_SHIFT)
-#define FSR_DZA  (FPEXC_DZ << FSR_AEXC_SHIFT)
-#define FSR_NXA  (FPEXC_NX << FSR_AEXC_SHIFT)
-#define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
-
-/* CSR numbers */
-#define CSR_FFLAGS 0x1
-#define CSR_FRM 0x2
-#define CSR_FCSR 0x3
-#define CSR_CYCLE 0xc00
-#define CSR_TIME 0xc01
-#define CSR_INSTRET 0xc02
-#define CSR_HPMCOUNTER3 0xc03
-#define CSR_HPMCOUNTER4 0xc04
-#define CSR_HPMCOUNTER5 0xc05
-#define CSR_HPMCOUNTER6 0xc06
-#define CSR_HPMCOUNTER7 0xc07
-#define CSR_HPMCOUNTER8 0xc08
-#define CSR_HPMCOUNTER9 0xc09
-#define CSR_HPMCOUNTER10 0xc0a
-#define CSR_HPMCOUNTER11 0xc0b
-#define CSR_HPMCOUNTER12 0xc0c
-#define CSR_HPMCOUNTER13 0xc0d
-#define CSR_HPMCOUNTER14 0xc0e
-#define CSR_HPMCOUNTER15 0xc0f
-#define CSR_HPMCOUNTER16 0xc10
-#define CSR_HPMCOUNTER17 0xc11
-#define CSR_HPMCOUNTER18 0xc12
-#define CSR_HPMCOUNTER19 0xc13
-#define CSR_HPMCOUNTER20 0xc14
-#define CSR_HPMCOUNTER21 0xc15
-#define CSR_HPMCOUNTER22 0xc16
-#define CSR_HPMCOUNTER23 0xc17
-#define CSR_HPMCOUNTER24 0xc18
-#define CSR_HPMCOUNTER25 0xc19
-#define CSR_HPMCOUNTER26 0xc1a
-#define CSR_HPMCOUNTER27 0xc1b
-#define CSR_HPMCOUNTER28 0xc1c
-#define CSR_HPMCOUNTER29 0xc1d
-#define CSR_HPMCOUNTER30 0xc1e
-#define CSR_HPMCOUNTER31 0xc1f
-#define CSR_SSTATUS 0x100
-#define CSR_SIE 0x104
-#define CSR_STVEC 0x105
-#define CSR_SCOUNTEREN 0x106
-#define CSR_SSCRATCH 0x140
-#define CSR_SEPC 0x141
-#define CSR_SCAUSE 0x142
-#define CSR_SBADADDR 0x143
-#define CSR_SIP 0x144
-#define CSR_SPTBR 0x180
-#define CSR_SATP 0x180
-#define CSR_MSTATUS 0x300
-#define CSR_MISA 0x301
-#define CSR_MEDELEG 0x302
-#define CSR_MIDELEG 0x303
-#define CSR_MIE 0x304
-#define CSR_MTVEC 0x305
-#define CSR_MCOUNTEREN 0x306
-#define CSR_MSCRATCH 0x340
-#define CSR_MEPC 0x341
-#define CSR_MCAUSE 0x342
-#define CSR_MBADADDR 0x343
-#define CSR_MIP 0x344
-#define CSR_PMPCFG0 0x3a0
-#define CSR_PMPCFG1 0x3a1
-#define CSR_PMPCFG2 0x3a2
-#define CSR_PMPCFG3 0x3a3
-#define CSR_PMPADDR0 0x3b0
-#define CSR_PMPADDR1 0x3b1
-#define CSR_PMPADDR2 0x3b2
-#define CSR_PMPADDR3 0x3b3
-#define CSR_PMPADDR4 0x3b4
-#define CSR_PMPADDR5 0x3b5
-#define CSR_PMPADDR6 0x3b6
-#define CSR_PMPADDR7 0x3b7
-#define CSR_PMPADDR8 0x3b8
-#define CSR_PMPADDR9 0x3b9
-#define CSR_PMPADDR10 0x3ba
-#define CSR_PMPADDR11 0x3bb
-#define CSR_PMPADDR12 0x3bc
-#define CSR_PMPADDR13 0x3bd
-#define CSR_PMPADDR14 0x3be
-#define CSR_PMPADDR15 0x3bf
-#define CSR_TSELECT 0x7a0
-#define CSR_TDATA1 0x7a1
-#define CSR_TDATA2 0x7a2
-#define CSR_TDATA3 0x7a3
-#define CSR_DCSR 0x7b0
-#define CSR_DPC 0x7b1
-#define CSR_DSCRATCH 0x7b2
-#define CSR_MCYCLE 0xb00
-#define CSR_MINSTRET 0xb02
-#define CSR_MHPMCOUNTER3 0xb03
-#define CSR_MHPMCOUNTER4 0xb04
-#define CSR_MHPMCOUNTER5 0xb05
-#define CSR_MHPMCOUNTER6 0xb06
-#define CSR_MHPMCOUNTER7 0xb07
-#define CSR_MHPMCOUNTER8 0xb08
-#define CSR_MHPMCOUNTER9 0xb09
-#define CSR_MHPMCOUNTER10 0xb0a
-#define CSR_MHPMCOUNTER11 0xb0b
-#define CSR_MHPMCOUNTER12 0xb0c
-#define CSR_MHPMCOUNTER13 0xb0d
-#define CSR_MHPMCOUNTER14 0xb0e
-#define CSR_MHPMCOUNTER15 0xb0f
-#define CSR_MHPMCOUNTER16 0xb10
-#define CSR_MHPMCOUNTER17 0xb11
-#define CSR_MHPMCOUNTER18 0xb12
-#define CSR_MHPMCOUNTER19 0xb13
-#define CSR_MHPMCOUNTER20 0xb14
-#define CSR_MHPMCOUNTER21 0xb15
-#define CSR_MHPMCOUNTER22 0xb16
-#define CSR_MHPMCOUNTER23 0xb17
-#define CSR_MHPMCOUNTER24 0xb18
-#define CSR_MHPMCOUNTER25 0xb19
-#define CSR_MHPMCOUNTER26 0xb1a
-#define CSR_MHPMCOUNTER27 0xb1b
-#define CSR_MHPMCOUNTER28 0xb1c
-#define CSR_MHPMCOUNTER29 0xb1d
-#define CSR_MHPMCOUNTER30 0xb1e
-#define CSR_MHPMCOUNTER31 0xb1f
-#define CSR_MUCOUNTEREN 0x320
-#define CSR_MSCOUNTEREN 0x321
-#define CSR_MHPMEVENT3 0x323
-#define CSR_MHPMEVENT4 0x324
-#define CSR_MHPMEVENT5 0x325
-#define CSR_MHPMEVENT6 0x326
-#define CSR_MHPMEVENT7 0x327
-#define CSR_MHPMEVENT8 0x328
-#define CSR_MHPMEVENT9 0x329
-#define CSR_MHPMEVENT10 0x32a
-#define CSR_MHPMEVENT11 0x32b
-#define CSR_MHPMEVENT12 0x32c
-#define CSR_MHPMEVENT13 0x32d
-#define CSR_MHPMEVENT14 0x32e
-#define CSR_MHPMEVENT15 0x32f
-#define CSR_MHPMEVENT16 0x330
-#define CSR_MHPMEVENT17 0x331
-#define CSR_MHPMEVENT18 0x332
-#define CSR_MHPMEVENT19 0x333
-#define CSR_MHPMEVENT20 0x334
-#define CSR_MHPMEVENT21 0x335
-#define CSR_MHPMEVENT22 0x336
-#define CSR_MHPMEVENT23 0x337
-#define CSR_MHPMEVENT24 0x338
-#define CSR_MHPMEVENT25 0x339
-#define CSR_MHPMEVENT26 0x33a
-#define CSR_MHPMEVENT27 0x33b
-#define CSR_MHPMEVENT28 0x33c
-#define CSR_MHPMEVENT29 0x33d
-#define CSR_MHPMEVENT30 0x33e
-#define CSR_MHPMEVENT31 0x33f
-#define CSR_MVENDORID 0xf11
-#define CSR_MARCHID 0xf12
-#define CSR_MIMPID 0xf13
-#define CSR_MHARTID 0xf14
-#define CSR_CYCLEH 0xc80
-#define CSR_TIMEH 0xc81
-#define CSR_INSTRETH 0xc82
-#define CSR_HPMCOUNTER3H 0xc83
-#define CSR_HPMCOUNTER4H 0xc84
-#define CSR_HPMCOUNTER5H 0xc85
-#define CSR_HPMCOUNTER6H 0xc86
-#define CSR_HPMCOUNTER7H 0xc87
-#define CSR_HPMCOUNTER8H 0xc88
-#define CSR_HPMCOUNTER9H 0xc89
-#define CSR_HPMCOUNTER10H 0xc8a
-#define CSR_HPMCOUNTER11H 0xc8b
-#define CSR_HPMCOUNTER12H 0xc8c
-#define CSR_HPMCOUNTER13H 0xc8d
-#define CSR_HPMCOUNTER14H 0xc8e
-#define CSR_HPMCOUNTER15H 0xc8f
-#define CSR_HPMCOUNTER16H 0xc90
-#define CSR_HPMCOUNTER17H 0xc91
-#define CSR_HPMCOUNTER18H 0xc92
-#define CSR_HPMCOUNTER19H 0xc93
-#define CSR_HPMCOUNTER20H 0xc94
-#define CSR_HPMCOUNTER21H 0xc95
-#define CSR_HPMCOUNTER22H 0xc96
-#define CSR_HPMCOUNTER23H 0xc97
-#define CSR_HPMCOUNTER24H 0xc98
-#define CSR_HPMCOUNTER25H 0xc99
-#define CSR_HPMCOUNTER26H 0xc9a
-#define CSR_HPMCOUNTER27H 0xc9b
-#define CSR_HPMCOUNTER28H 0xc9c
-#define CSR_HPMCOUNTER29H 0xc9d
-#define CSR_HPMCOUNTER30H 0xc9e
-#define CSR_HPMCOUNTER31H 0xc9f
-#define CSR_MCYCLEH 0xb80
-#define CSR_MINSTRETH 0xb82
-#define CSR_MHPMCOUNTER3H 0xb83
-#define CSR_MHPMCOUNTER4H 0xb84
-#define CSR_MHPMCOUNTER5H 0xb85
-#define CSR_MHPMCOUNTER6H 0xb86
-#define CSR_MHPMCOUNTER7H 0xb87
-#define CSR_MHPMCOUNTER8H 0xb88
-#define CSR_MHPMCOUNTER9H 0xb89
-#define CSR_MHPMCOUNTER10H 0xb8a
-#define CSR_MHPMCOUNTER11H 0xb8b
-#define CSR_MHPMCOUNTER12H 0xb8c
-#define CSR_MHPMCOUNTER13H 0xb8d
-#define CSR_MHPMCOUNTER14H 0xb8e
-#define CSR_MHPMCOUNTER15H 0xb8f
-#define CSR_MHPMCOUNTER16H 0xb90
-#define CSR_MHPMCOUNTER17H 0xb91
-#define CSR_MHPMCOUNTER18H 0xb92
-#define CSR_MHPMCOUNTER19H 0xb93
-#define CSR_MHPMCOUNTER20H 0xb94
-#define CSR_MHPMCOUNTER21H 0xb95
-#define CSR_MHPMCOUNTER22H 0xb96
-#define CSR_MHPMCOUNTER23H 0xb97
-#define CSR_MHPMCOUNTER24H 0xb98
-#define CSR_MHPMCOUNTER25H 0xb99
-#define CSR_MHPMCOUNTER26H 0xb9a
-#define CSR_MHPMCOUNTER27H 0xb9b
-#define CSR_MHPMCOUNTER28H 0xb9c
-#define CSR_MHPMCOUNTER29H 0xb9d
-#define CSR_MHPMCOUNTER30H 0xb9e
-#define CSR_MHPMCOUNTER31H 0xb9f
-
-/* mstatus bits */
+/* Floating point round mode */
+#define FSR_RD_SHIFT        5
+#define FSR_RD              (0x7 << FSR_RD_SHIFT)
+
+/* Floating point accrued exception flags */
+#define FPEXC_NX            0x01
+#define FPEXC_UF            0x02
+#define FPEXC_OF            0x04
+#define FPEXC_DZ            0x08
+#define FPEXC_NV            0x10
+
+/* Floating point status register bits */
+#define FSR_AEXC_SHIFT      0
+#define FSR_NVA             (FPEXC_NV << FSR_AEXC_SHIFT)
+#define FSR_OFA             (FPEXC_OF << FSR_AEXC_SHIFT)
+#define FSR_UFA             (FPEXC_UF << FSR_AEXC_SHIFT)
+#define FSR_DZA             (FPEXC_DZ << FSR_AEXC_SHIFT)
+#define FSR_NXA             (FPEXC_NX << FSR_AEXC_SHIFT)
+#define FSR_AEXC            (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
+
+/* Control and Status Registers */
+
+/* User Trap Setup */
+#define CSR_USTATUS         0x000
+#define CSR_UIE             0x004
+#define CSR_UTVEC           0x005
+
+/* User Trap Handling */
+#define CSR_USCRATCH        0x040
+#define CSR_UEPC            0x041
+#define CSR_UCAUSE          0x042
+#define CSR_UTVAL           0x043
+#define CSR_UIP             0x044
+
+/* User Floating-Point CSRs */
+#define CSR_FFLAGS          0x001
+#define CSR_FRM             0x002
+#define CSR_FCSR            0x003
+
+/* User Timers and Counters */
+#define CSR_CYCLE           0xc00
+#define CSR_TIME            0xc01
+#define CSR_INSTRET         0xc02
+#define CSR_HPMCOUNTER3     0xc03
+#define CSR_HPMCOUNTER4     0xc04
+#define CSR_HPMCOUNTER5     0xc05
+#define CSR_HPMCOUNTER6     0xc06
+#define CSR_HPMCOUNTER7     0xc07
+#define CSR_HPMCOUNTER8     0xc08
+#define CSR_HPMCOUNTER9     0xc09
+#define CSR_HPMCOUNTER10    0xc0a
+#define CSR_HPMCOUNTER11    0xc0b
+#define CSR_HPMCOUNTER12    0xc0c
+#define CSR_HPMCOUNTER13    0xc0d
+#define CSR_HPMCOUNTER14    0xc0e
+#define CSR_HPMCOUNTER15    0xc0f
+#define CSR_HPMCOUNTER16    0xc10
+#define CSR_HPMCOUNTER17    0xc11
+#define CSR_HPMCOUNTER18    0xc12
+#define CSR_HPMCOUNTER19    0xc13
+#define CSR_HPMCOUNTER20    0xc14
+#define CSR_HPMCOUNTER21    0xc15
+#define CSR_HPMCOUNTER22    0xc16
+#define CSR_HPMCOUNTER23    0xc17
+#define CSR_HPMCOUNTER24    0xc18
+#define CSR_HPMCOUNTER25    0xc19
+#define CSR_HPMCOUNTER26    0xc1a
+#define CSR_HPMCOUNTER27    0xc1b
+#define CSR_HPMCOUNTER28    0xc1c
+#define CSR_HPMCOUNTER29    0xc1d
+#define CSR_HPMCOUNTER30    0xc1e
+#define CSR_HPMCOUNTER31    0xc1f
+#define CSR_CYCLEH          0xc80
+#define CSR_TIMEH           0xc81
+#define CSR_INSTRETH        0xc82
+#define CSR_HPMCOUNTER3H    0xc83
+#define CSR_HPMCOUNTER4H    0xc84
+#define CSR_HPMCOUNTER5H    0xc85
+#define CSR_HPMCOUNTER6H    0xc86
+#define CSR_HPMCOUNTER7H    0xc87
+#define CSR_HPMCOUNTER8H    0xc88
+#define CSR_HPMCOUNTER9H    0xc89
+#define CSR_HPMCOUNTER10H   0xc8a
+#define CSR_HPMCOUNTER11H   0xc8b
+#define CSR_HPMCOUNTER12H   0xc8c
+#define CSR_HPMCOUNTER13H   0xc8d
+#define CSR_HPMCOUNTER14H   0xc8e
+#define CSR_HPMCOUNTER15H   0xc8f
+#define CSR_HPMCOUNTER16H   0xc90
+#define CSR_HPMCOUNTER17H   0xc91
+#define CSR_HPMCOUNTER18H   0xc92
+#define CSR_HPMCOUNTER19H   0xc93
+#define CSR_HPMCOUNTER20H   0xc94
+#define CSR_HPMCOUNTER21H   0xc95
+#define CSR_HPMCOUNTER22H   0xc96
+#define CSR_HPMCOUNTER23H   0xc97
+#define CSR_HPMCOUNTER24H   0xc98
+#define CSR_HPMCOUNTER25H   0xc99
+#define CSR_HPMCOUNTER26H   0xc9a
+#define CSR_HPMCOUNTER27H   0xc9b
+#define CSR_HPMCOUNTER28H   0xc9c
+#define CSR_HPMCOUNTER29H   0xc9d
+#define CSR_HPMCOUNTER30H   0xc9e
+#define CSR_HPMCOUNTER31H   0xc9f
+
+/* Machine Timers and Counters */
+#define CSR_MCYCLE          0xb00
+#define CSR_MINSTRET        0xb02
+#define CSR_MCYCLEH         0xb80
+#define CSR_MINSTRETH       0xb82
+
+/* Machine Information Registers */
+#define CSR_MVENDORID       0xf11
+#define CSR_MARCHID         0xf12
+#define CSR_MIMPID          0xf13
+#define CSR_MHARTID         0xf14
+
+/* Machine Trap Setup */
+#define CSR_MSTATUS         0x300
+#define CSR_MISA            0x301
+#define CSR_MEDELEG         0x302
+#define CSR_MIDELEG         0x303
+#define CSR_MIE             0x304
+#define CSR_MTVEC           0x305
+#define CSR_MCOUNTEREN      0x306
+
+/* Legacy Counter Setup (priv v1.9.1) */
+#define CSR_MUCOUNTEREN     0x320
+#define CSR_MSCOUNTEREN     0x321
+
+/* Machine Trap Handling */
+#define CSR_MSCRATCH        0x340
+#define CSR_MEPC            0x341
+#define CSR_MCAUSE          0x342
+#define CSR_MBADADDR        0x343
+#define CSR_MIP             0x344
+
+/* Supervisor Trap Setup */
+#define CSR_SSTATUS         0x100
+#define CSR_SIE             0x104
+#define CSR_STVEC           0x105
+#define CSR_SCOUNTEREN      0x106
+
+/* Supervisor Trap Handling */
+#define CSR_SSCRATCH        0x140
+#define CSR_SEPC            0x141
+#define CSR_SCAUSE          0x142
+#define CSR_SBADADDR        0x143
+#define CSR_SIP             0x144
+
+/* Supervisor Protection and Translation */
+#define CSR_SPTBR           0x180
+#define CSR_SATP            0x180
+
+/* Physical Memory Protection */
+#define CSR_PMPCFG0         0x3a0
+#define CSR_PMPCFG1         0x3a1
+#define CSR_PMPCFG2         0x3a2
+#define CSR_PMPCFG3         0x3a3
+#define CSR_PMPADDR0        0x3b0
+#define CSR_PMPADDR1        0x3b1
+#define CSR_PMPADDR2        0x3b2
+#define CSR_PMPADDR3        0x3b3
+#define CSR_PMPADDR4        0x3b4
+#define CSR_PMPADDR5        0x3b5
+#define CSR_PMPADDR6        0x3b6
+#define CSR_PMPADDR7        0x3b7
+#define CSR_PMPADDR8        0x3b8
+#define CSR_PMPADDR9        0x3b9
+#define CSR_PMPADDR10       0x3ba
+#define CSR_PMPADDR11       0x3bb
+#define CSR_PMPADDR12       0x3bc
+#define CSR_PMPADDR13       0x3bd
+#define CSR_PMPADDR14       0x3be
+#define CSR_PMPADDR15       0x3bf
+
+/* Debug/Trace Registers (shared with Debug Mode) */
+#define CSR_TSELECT         0x7a0
+#define CSR_TDATA1          0x7a1
+#define CSR_TDATA2          0x7a2
+#define CSR_TDATA3          0x7a3
+
+/* Debug Mode Registers */
+#define CSR_DCSR            0x7b0
+#define CSR_DPC             0x7b1
+#define CSR_DSCRATCH        0x7b2
+
+/* Performance Counters */
+#define CSR_MHPMCOUNTER3    0xb03
+#define CSR_MHPMCOUNTER4    0xb04
+#define CSR_MHPMCOUNTER5    0xb05
+#define CSR_MHPMCOUNTER6    0xb06
+#define CSR_MHPMCOUNTER7    0xb07
+#define CSR_MHPMCOUNTER8    0xb08
+#define CSR_MHPMCOUNTER9    0xb09
+#define CSR_MHPMCOUNTER10   0xb0a
+#define CSR_MHPMCOUNTER11   0xb0b
+#define CSR_MHPMCOUNTER12   0xb0c
+#define CSR_MHPMCOUNTER13   0xb0d
+#define CSR_MHPMCOUNTER14   0xb0e
+#define CSR_MHPMCOUNTER15   0xb0f
+#define CSR_MHPMCOUNTER16   0xb10
+#define CSR_MHPMCOUNTER17   0xb11
+#define CSR_MHPMCOUNTER18   0xb12
+#define CSR_MHPMCOUNTER19   0xb13
+#define CSR_MHPMCOUNTER20   0xb14
+#define CSR_MHPMCOUNTER21   0xb15
+#define CSR_MHPMCOUNTER22   0xb16
+#define CSR_MHPMCOUNTER23   0xb17
+#define CSR_MHPMCOUNTER24   0xb18
+#define CSR_MHPMCOUNTER25   0xb19
+#define CSR_MHPMCOUNTER26   0xb1a
+#define CSR_MHPMCOUNTER27   0xb1b
+#define CSR_MHPMCOUNTER28   0xb1c
+#define CSR_MHPMCOUNTER29   0xb1d
+#define CSR_MHPMCOUNTER30   0xb1e
+#define CSR_MHPMCOUNTER31   0xb1f
+#define CSR_MHPMEVENT3      0x323
+#define CSR_MHPMEVENT4      0x324
+#define CSR_MHPMEVENT5      0x325
+#define CSR_MHPMEVENT6      0x326
+#define CSR_MHPMEVENT7      0x327
+#define CSR_MHPMEVENT8      0x328
+#define CSR_MHPMEVENT9      0x329
+#define CSR_MHPMEVENT10     0x32a
+#define CSR_MHPMEVENT11     0x32b
+#define CSR_MHPMEVENT12     0x32c
+#define CSR_MHPMEVENT13     0x32d
+#define CSR_MHPMEVENT14     0x32e
+#define CSR_MHPMEVENT15     0x32f
+#define CSR_MHPMEVENT16     0x330
+#define CSR_MHPMEVENT17     0x331
+#define CSR_MHPMEVENT18     0x332
+#define CSR_MHPMEVENT19     0x333
+#define CSR_MHPMEVENT20     0x334
+#define CSR_MHPMEVENT21     0x335
+#define CSR_MHPMEVENT22     0x336
+#define CSR_MHPMEVENT23     0x337
+#define CSR_MHPMEVENT24     0x338
+#define CSR_MHPMEVENT25     0x339
+#define CSR_MHPMEVENT26     0x33a
+#define CSR_MHPMEVENT27     0x33b
+#define CSR_MHPMEVENT28     0x33c
+#define CSR_MHPMEVENT29     0x33d
+#define CSR_MHPMEVENT30     0x33e
+#define CSR_MHPMEVENT31     0x33f
+#define CSR_MHPMCOUNTER3H   0xb83
+#define CSR_MHPMCOUNTER4H   0xb84
+#define CSR_MHPMCOUNTER5H   0xb85
+#define CSR_MHPMCOUNTER6H   0xb86
+#define CSR_MHPMCOUNTER7H   0xb87
+#define CSR_MHPMCOUNTER8H   0xb88
+#define CSR_MHPMCOUNTER9H   0xb89
+#define CSR_MHPMCOUNTER10H  0xb8a
+#define CSR_MHPMCOUNTER11H  0xb8b
+#define CSR_MHPMCOUNTER12H  0xb8c
+#define CSR_MHPMCOUNTER13H  0xb8d
+#define CSR_MHPMCOUNTER14H  0xb8e
+#define CSR_MHPMCOUNTER15H  0xb8f
+#define CSR_MHPMCOUNTER16H  0xb90
+#define CSR_MHPMCOUNTER17H  0xb91
+#define CSR_MHPMCOUNTER18H  0xb92
+#define CSR_MHPMCOUNTER19H  0xb93
+#define CSR_MHPMCOUNTER20H  0xb94
+#define CSR_MHPMCOUNTER21H  0xb95
+#define CSR_MHPMCOUNTER22H  0xb96
+#define CSR_MHPMCOUNTER23H  0xb97
+#define CSR_MHPMCOUNTER24H  0xb98
+#define CSR_MHPMCOUNTER25H  0xb99
+#define CSR_MHPMCOUNTER26H  0xb9a
+#define CSR_MHPMCOUNTER27H  0xb9b
+#define CSR_MHPMCOUNTER28H  0xb9c
+#define CSR_MHPMCOUNTER29H  0xb9d
+#define CSR_MHPMCOUNTER30H  0xb9e
+#define CSR_MHPMCOUNTER31H  0xb9f
+
+/* mstatus CSR bits */
 #define MSTATUS_UIE         0x00000001
 #define MSTATUS_SIE         0x00000002
 #define MSTATUS_HIE         0x00000004
@@ -276,7 +317,7 @@
 #define MSTATUS_SD MSTATUS64_SD
 #endif
 
-/* sstatus bits */
+/* sstatus CSR bits */
 #define SSTATUS_UIE         0x00000001
 #define SSTATUS_SIE         0x00000002
 #define SSTATUS_UPIE        0x00000010
@@ -297,83 +338,71 @@
 #define SSTATUS_SD SSTATUS64_SD
 #endif
 
-/* irqs */
-#define MIP_SSIP            (1 << IRQ_S_SOFT)
-#define MIP_HSIP            (1 << IRQ_H_SOFT)
-#define MIP_MSIP            (1 << IRQ_M_SOFT)
-#define MIP_STIP            (1 << IRQ_S_TIMER)
-#define MIP_HTIP            (1 << IRQ_H_TIMER)
-#define MIP_MTIP            (1 << IRQ_M_TIMER)
-#define MIP_SEIP            (1 << IRQ_S_EXT)
-#define MIP_HEIP            (1 << IRQ_H_EXT)
-#define MIP_MEIP            (1 << IRQ_M_EXT)
-
-#define SIP_SSIP            MIP_SSIP
-#define SIP_STIP            MIP_STIP
-#define SIP_SEIP            MIP_SEIP
-
+/* Privilege modes */
 #define PRV_U 0
 #define PRV_S 1
 #define PRV_H 2
 #define PRV_M 3
 
-/* privileged ISA 1.9.1 VM modes (mstatus.vm) */
-#define VM_1_09_MBARE 0
-#define VM_1_09_MBB   1
-#define VM_1_09_MBBID 2
-#define VM_1_09_SV32  8
-#define VM_1_09_SV39  9
-#define VM_1_09_SV48  10
-
-/* privileged ISA 1.10.0 VM modes (satp.mode) */
-#define VM_1_10_MBARE 0
-#define VM_1_10_SV32  1
-#define VM_1_10_SV39  8
-#define VM_1_10_SV48  9
-#define VM_1_10_SV57  10
-#define VM_1_10_SV64  11
-
-/* privileged ISA interrupt causes */
-#define IRQ_U_SOFT      0  /* since: priv-1.10 */
-#define IRQ_S_SOFT      1
-#define IRQ_H_SOFT      2  /* until: priv-1.9.1 */
-#define IRQ_M_SOFT      3  /* until: priv-1.9.1 */
-#define IRQ_U_TIMER     4  /* since: priv-1.10 */
-#define IRQ_S_TIMER     5
-#define IRQ_H_TIMER     6  /* until: priv-1.9.1 */
-#define IRQ_M_TIMER     7  /* until: priv-1.9.1 */
-#define IRQ_U_EXT       8  /* since: priv-1.10 */
-#define IRQ_S_EXT       9
-#define IRQ_H_EXT       10 /* until: priv-1.9.1 */
-#define IRQ_M_EXT       11 /* until: priv-1.9.1 */
-#define IRQ_X_COP       12 /* non-standard */
-
-/* Default addresses */
-#define DEFAULT_RSTVEC     0x00001000
-
-/* RV32 satp field masks */
-#define SATP32_MODE 0x80000000
-#define SATP32_ASID 0x7fc00000
-#define SATP32_PPN  0x003fffff
-
-/* RV64 satp field masks */
-#define SATP64_MODE 0xF000000000000000ULL
-#define SATP64_ASID 0x0FFFF00000000000ULL
-#define SATP64_PPN  0x00000FFFFFFFFFFFULL
+/* RV32 satp CSR field masks */
+#define SATP32_MODE         0x80000000
+#define SATP32_ASID         0x7fc00000
+#define SATP32_PPN          0x003fffff
+
+/* RV64 satp CSR field masks */
+#define SATP64_MODE         0xF000000000000000ULL
+#define SATP64_ASID         0x0FFFF00000000000ULL
+#define SATP64_PPN          0x00000FFFFFFFFFFFULL
 
 #if defined(TARGET_RISCV32)
-#define SATP_MODE SATP32_MODE
-#define SATP_ASID SATP32_ASID
-#define SATP_PPN  SATP32_PPN
+#define SATP_MODE           SATP32_MODE
+#define SATP_ASID           SATP32_ASID
+#define SATP_PPN            SATP32_PPN
 #endif
 #if defined(TARGET_RISCV64)
-#define SATP_MODE SATP64_MODE
-#define SATP_ASID SATP64_ASID
-#define SATP_PPN  SATP64_PPN
+#define SATP_MODE           SATP64_MODE
+#define SATP_ASID           SATP64_ASID
+#define SATP_PPN            SATP64_PPN
 #endif
 
-/* RISCV Exception Codes */
-#define EXCP_NONE                       -1 /* not a real RISCV exception code */
+/* VM modes (mstatus.vm) privileged ISA 1.9.1 */
+#define VM_1_09_MBARE       0
+#define VM_1_09_MBB         1
+#define VM_1_09_MBBID       2
+#define VM_1_09_SV32        8
+#define VM_1_09_SV39        9
+#define VM_1_09_SV48        10
+
+/* VM modes (satp.mode) privileged ISA 1.10 */
+#define VM_1_10_MBARE       0
+#define VM_1_10_SV32        1
+#define VM_1_10_SV39        8
+#define VM_1_10_SV48        9
+#define VM_1_10_SV57        10
+#define VM_1_10_SV64        11
+
+/* Page table entry (PTE) fields */
+#define PTE_V               0x001 /* Valid */
+#define PTE_R               0x002 /* Read */
+#define PTE_W               0x004 /* Write */
+#define PTE_X               0x008 /* Execute */
+#define PTE_U               0x010 /* User */
+#define PTE_G               0x020 /* Global */
+#define PTE_A               0x040 /* Accessed */
+#define PTE_D               0x080 /* Dirty */
+#define PTE_SOFT            0x300 /* Reserved for Software */
+
+/* Page table PPN shift amount */
+#define PTE_PPN_SHIFT       10
+
+/* Leaf page shift amount */
+#define PGSHIFT             12
+
+/* Default Reset Vector adress */
+#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
@@ -382,9 +411,7 @@
 #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 /* for convenience, report all
-                                                  ECALLs as this, handler
-                                                  fixes */
+#define RISCV_EXCP_U_ECALL                 0x8
 #define RISCV_EXCP_S_ECALL                 0x9
 #define RISCV_EXCP_H_ECALL                 0xa
 #define RISCV_EXCP_M_ECALL                 0xb
@@ -395,15 +422,44 @@
 #define RISCV_EXCP_INT_FLAG                0x80000000
 #define RISCV_EXCP_INT_MASK                0x7fffffff
 
-/* page table entry (PTE) fields */
-#define PTE_V     0x001 /* Valid */
-#define PTE_R     0x002 /* Read */
-#define PTE_W     0x004 /* Write */
-#define PTE_X     0x008 /* Execute */
-#define PTE_U     0x010 /* User */
-#define PTE_G     0x020 /* Global */
-#define PTE_A     0x040 /* Accessed */
-#define PTE_D     0x080 /* Dirty */
-#define PTE_SOFT  0x300 /* Reserved for Software */
-
-#define PTE_PPN_SHIFT 10
+/* Interrupt causes */
+#define IRQ_U_SOFT                         0
+#define IRQ_S_SOFT                         1
+#define IRQ_H_SOFT                         2  /* reserved */
+#define IRQ_M_SOFT                         3
+#define IRQ_U_TIMER                        4
+#define IRQ_S_TIMER                        5
+#define IRQ_H_TIMER                        6  /* reserved */
+#define IRQ_M_TIMER                        7
+#define IRQ_U_EXT                          8
+#define IRQ_S_EXT                          9
+#define IRQ_H_EXT                          10 /* reserved */
+#define IRQ_M_EXT                          11
+#define IRQ_U_CORE                         12
+#define IRQ_S_CORE                         13
+#define IRQ_H_CORE                         14 /* reserved */
+#define IRQ_M_CORE                         15
+
+/* 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_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_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_MEIP                           (1 << IRQ_M_EXT)
+#define MIP_UCIP                           (1 << IRQ_U_CORE)
+#define MIP_SCIP                           (1 << IRQ_S_CORE)
+#define MIP_HCIP                           (1 << IRQ_H_CORE)
+#define MIP_MCIP                           (1 << IRQ_M_CORE)
+
+/* sip masks */
+#define SIP_SSIP                           MIP_SSIP
+#define SIP_STIP                           MIP_STIP
+#define SIP_SEIP                           MIP_SEIP
+#define SIP_SCIP                           MIP_SCIP
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 2b9dd9da6486..fd2efcb49929 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -90,8 +90,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         target_ulong csrno)
 {
 #ifndef CONFIG_USER_ONLY
-    uint64_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP | (1 << IRQ_X_COP);
-    uint64_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP;
+    uint64_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP | MIP_SCIP;
+    uint64_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP | MIP_MCIP;
 #endif
 
     switch (csrno) {
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 08/30] RISC-V: Implement modular CSR helper interface
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (6 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 07/30] RISC-V: Update CSR and interrupt definitions Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Previous CSR code uses csr_read_helper and csr_write_helper
to update CSR registers however this interface prevents
atomic read/modify/write CSR operations; in addition
there is no trap-free method to access to CSRs due
to the monolithic CSR functions call longjmp.

The current iCSR interface is not safe to be called by
target/riscv/gdbstub.c as privilege checks or missing CSRs
may call longjmp to generate exceptions. It needs to
indicate existence so traps can be generated in the
CSR instruction helpers.

This commit moves CSR access from the monolithic switch
statements in target/riscv/op_helper.c into modular
read/write functions in target/riscv/csr.c using a new
function pointer table for dispatch (which can later
be used to allow CPUs to hook up model specific CSRs).

A read/modify/write interface is added to support atomic
CSR operations and a non-trapping interface is added
to allow exception-free access to CSRs by the debugger.

The CSR functions and CSR dispatch table are ordered
to match The RISC-V Instruction Set Manual, Volume II:
Privileged Architecture Version 1.10, 2.2 CSR Listing.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/Makefile.objs |   2 +-
 target/riscv/cpu.h         |  18 +-
 target/riscv/cpu_helper.c  |   4 +-
 target/riscv/csr.c         | 857 +++++++++++++++++++++++++++++++++++++++++++++
 target/riscv/gdbstub.c     |  10 +-
 target/riscv/op_helper.c   | 611 +-------------------------------
 6 files changed, 898 insertions(+), 604 deletions(-)
 create mode 100644 target/riscv/csr.c

diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index fcc5d34c1f2e..4072abe3e45c 100644
--- a/target/riscv/Makefile.objs
+++ b/target/riscv/Makefile.objs
@@ -1 +1 @@
-obj-y += translate.o op_helper.o cpu_helper.o cpu.o fpu_helper.o gdbstub.o pmp.o
+obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c5d485769cde..02c60c45631b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -290,9 +290,21 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
 #endif
 }
 
-void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
-        target_ulong csrno);
-target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno);
+int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
+                target_ulong new_value, target_ulong write_mask);
+
+static inline void csr_write_helper(CPURISCVState *env, target_ulong val,
+                                    int csrno)
+{
+    riscv_csrrw(env, csrno, NULL, val, -1);
+}
+
+static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
+{
+    target_ulong val = 0;
+    riscv_csrrw(env, csrno, &val, 0, 0);
+    return val;
+}
 
 #include "exec/cpu-all.h"
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6c886e99055a..1f523861b7cb 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -526,7 +526,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             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);
-        csr_write_helper(env, s, CSR_MSTATUS);
+        env->mstatus = s;
         riscv_set_mode(env, PRV_S);
     } else {
         /* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
@@ -551,7 +551,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             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);
-        csr_write_helper(env, s, CSR_MSTATUS);
+        env->mstatus = s;
         riscv_set_mode(env, PRV_M);
     }
     /* TODO yield load reservation  */
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
new file mode 100644
index 000000000000..e08f3523d854
--- /dev/null
+++ b/target/riscv/csr.c
@@ -0,0 +1,857 @@
+/*
+ * RISC-V Control and Status Registers.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "qemu/main-loop.h"
+#include "exec/exec-all.h"
+
+
+/* Control and Status Register function table forward declaration */
+
+typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
+    target_ulong *ret_value);
+typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
+    target_ulong new_value);
+typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
+    target_ulong *ret_value, target_ulong new_value, target_ulong write_mask);
+
+typedef struct {
+    riscv_csr_read_fn read;
+    riscv_csr_write_fn write;
+    riscv_csr_op_fn op;
+} riscv_csr_operations;
+
+static const riscv_csr_operations csr_ops[];
+
+
+/* User Floating-Point CSRs */
+
+static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+#endif
+    *val = cpu_riscv_get_fflags(env);
+    return 0;
+}
+
+static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+    env->mstatus |= MSTATUS_FS;
+#endif
+    cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
+    return 0;
+}
+
+static int read_frm(CPURISCVState *env, int csrno, target_ulong *val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+#endif
+    *val = env->frm;
+    return 0;
+}
+
+static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+    env->mstatus |= MSTATUS_FS;
+#endif
+    env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
+    return 0;
+}
+
+static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+#endif
+    *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
+        | (env->frm << FSR_RD_SHIFT);
+    return 0;
+}
+
+static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+    env->mstatus |= MSTATUS_FS;
+#endif
+    env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
+    cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
+    return 0;
+}
+
+/* User Timers and Counters */
+
+static int counter_enabled(CPURISCVState *env, int csrno)
+{
+#ifndef CONFIG_USER_ONLY
+    target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
+                          env->priv == PRV_S ? env->mcounteren : -1U;
+#else
+    target_ulong ctr_en = -1;
+#endif
+    return (ctr_en >> (csrno & 31)) & 1;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+static int read_zero_counter(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (!counter_enabled(env, csrno)) {
+        return -1;
+    }
+    *val = 0;
+    return 0;
+}
+#endif
+
+static int read_instret(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (!counter_enabled(env, csrno)) {
+        return -1;
+    }
+#if !defined(CONFIG_USER_ONLY)
+    if (use_icount) {
+        *val = cpu_get_icount();
+    } else {
+        *val = cpu_get_host_ticks();
+    }
+#else
+    *val = cpu_get_host_ticks();
+#endif
+    return 0;
+}
+
+#if defined(TARGET_RISCV32)
+static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (!counter_enabled(env, csrno)) {
+        return -1;
+    }
+#if !defined(CONFIG_USER_ONLY)
+    if (use_icount) {
+        *val = cpu_get_icount() >> 32;
+    } else {
+        *val = cpu_get_host_ticks() >> 32;
+    }
+#else
+    *val = cpu_get_host_ticks() >> 32;
+#endif
+    return 0;
+}
+#endif
+
+#if defined(CONFIG_USER_ONLY)
+
+static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = cpu_get_host_ticks();
+    return 0;
+}
+
+#if defined(TARGET_RISCV32)
+static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = cpu_get_host_ticks() >> 32;
+    return 0;
+}
+#endif
+
+#else
+
+/* Machine constants */
+
+#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP | MIP_MCIP)
+#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP | MIP_SCIP)
+
+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_excps =
+    (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) |
+    (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) |
+    (1ULL << (RISCV_EXCP_ILLEGAL_INST)) |
+    (1ULL << (RISCV_EXCP_BREAKPOINT)) |
+    (1ULL << (RISCV_EXCP_LOAD_ADDR_MIS)) |
+    (1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT)) |
+    (1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS)) |
+    (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_M_ECALL)) |
+    (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) |
+    (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) |
+    (1ULL << (RISCV_EXCP_STORE_PAGE_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;
+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;
+
+#if defined(TARGET_RISCV32)
+static const char valid_vm_1_09[16] = {
+    [VM_1_09_MBARE] = 1,
+    [VM_1_09_SV32] = 1,
+};
+static const char valid_vm_1_10[16] = {
+    [VM_1_10_MBARE] = 1,
+    [VM_1_10_SV32] = 1
+};
+#elif defined(TARGET_RISCV64)
+static const char valid_vm_1_09[16] = {
+    [VM_1_09_MBARE] = 1,
+    [VM_1_09_SV39] = 1,
+    [VM_1_09_SV48] = 1,
+};
+static const char valid_vm_1_10[16] = {
+    [VM_1_10_MBARE] = 1,
+    [VM_1_10_SV39] = 1,
+    [VM_1_10_SV48] = 1,
+    [VM_1_10_SV57] = 1
+};
+#endif
+
+/* Machine Information Registers */
+
+static int read_zero(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    return *val = 0;
+}
+
+static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mhartid;
+    return 0;
+}
+
+/* Machine Trap Setup */
+
+static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mstatus;
+    return 0;
+}
+
+static int validate_vm(CPURISCVState *env, target_ulong vm)
+{
+    return (env->priv_ver >= PRIV_VERSION_1_10_0) ?
+        valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf];
+}
+
+static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    target_ulong mstatus = env->mstatus;
+    target_ulong mask = 0;
+    target_ulong mpp = get_field(val, MSTATUS_MPP);
+
+    /* flush tlb on mstatus fields that affect VM */
+    if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+        if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
+                MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) {
+            tlb_flush(CPU(riscv_env_get_cpu(env)));
+        }
+        mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
+            MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
+            MSTATUS_MPP | MSTATUS_MXR |
+            (validate_vm(env, get_field(val, MSTATUS_VM)) ?
+                MSTATUS_VM : 0);
+    }
+    if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+        if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
+                MSTATUS_MPRV | MSTATUS_SUM)) {
+            tlb_flush(CPU(riscv_env_get_cpu(env)));
+        }
+        mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
+            MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
+            MSTATUS_MPP | MSTATUS_MXR;
+    }
+
+    /* silenty discard mstatus.mpp writes for unsupported modes */
+    if (mpp == PRV_H ||
+        (!riscv_has_ext(env, RVS) && mpp == PRV_S) ||
+        (!riscv_has_ext(env, RVU) && mpp == PRV_U)) {
+        mask &= ~MSTATUS_MPP;
+    }
+
+    mstatus = (mstatus & ~mask) | (val & mask);
+
+    /* Note: this is a workaround for an issue where mstatus.FS
+       does not report dirty after floating point operations
+       that modify floating point state. This workaround is
+       technically compliant with the RISC-V Privileged
+       specification as it is legal to return only off, or dirty.
+       at the expense of extra floating point save/restore. */
+
+    /* FP is always dirty or off */
+    if (mstatus & MSTATUS_FS) {
+        mstatus |= MSTATUS_FS;
+    }
+
+    int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
+                ((mstatus & MSTATUS_XS) == MSTATUS_XS);
+    mstatus = set_field(mstatus, MSTATUS_SD, dirty);
+    env->mstatus = mstatus;
+
+    return 0;
+}
+
+static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->misa;
+    return 0;
+}
+
+static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->medeleg;
+    return 0;
+}
+
+static int write_medeleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->medeleg = (env->medeleg & ~delegable_excps) | (val & delegable_excps);
+    return 0;
+}
+
+static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mideleg;
+    return 0;
+}
+
+static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
+    return 0;
+}
+
+static int read_mie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mie;
+    return 0;
+}
+
+static int write_mie(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mie = (env->mie & ~all_ints) | (val & all_ints);
+    return 0;
+}
+
+static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mtvec;
+    return 0;
+}
+
+static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val)
+{
+    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+    if ((val & 3) == 0) {
+        env->mtvec = val >> 2 << 2;
+    } else {
+        qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported");
+    }
+    return 0;
+}
+
+static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (env->priv_ver < PRIV_VERSION_1_10_0) {
+        return -1;
+    }
+    *val = env->mcounteren;
+    return 0;
+}
+
+static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (env->priv_ver < PRIV_VERSION_1_10_0) {
+        return -1;
+    }
+    env->mcounteren = val;
+    return 0;
+}
+
+static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (env->priv_ver > PRIV_VERSION_1_09_1) {
+        return -1;
+    }
+    *val = env->mcounteren;
+    return 0;
+}
+
+static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (env->priv_ver > PRIV_VERSION_1_09_1) {
+        return -1;
+    }
+    env->mcounteren = val;
+    return 0;
+}
+
+static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (env->priv_ver > PRIV_VERSION_1_09_1) {
+        return -1;
+    }
+    *val = env->scounteren;
+    return 0;
+}
+
+static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (env->priv_ver > PRIV_VERSION_1_09_1) {
+        return -1;
+    }
+    env->scounteren = val;
+    return 0;
+}
+
+/* Machine Trap Handling */
+
+static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mscratch;
+    return 0;
+}
+
+static int write_mscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mscratch = val;
+    return 0;
+}
+
+static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mepc;
+    return 0;
+}
+
+static int write_mepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mepc = val;
+    return 0;
+}
+
+static int read_mcause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mcause;
+    return 0;
+}
+
+static int write_mcause(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mcause = val;
+    return 0;
+}
+
+static int read_mbadaddr(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mbadaddr;
+    return 0;
+}
+
+static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mbadaddr = val;
+    return 0;
+}
+
+static int read_mip(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = atomic_read(&env->mip);
+    return 0;
+}
+
+static int write_mip(CPURISCVState *env, int csrno, target_ulong val)
+{
+    RISCVCPU *cpu = riscv_env_get_cpu(env);
+
+    /*
+     * csrs, csrc on mip.SEIP is not decomposable into separate read and
+     * write steps, so a different implementation is needed
+     */
+
+    qemu_mutex_lock_iothread();
+    riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
+                         (val & (MIP_SSIP | MIP_STIP)));
+    qemu_mutex_unlock_iothread();
+
+    return 0;
+}
+
+/* Supervisor Trap Setup */
+
+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;
+    return 0;
+}
+
+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);
+    return write_mstatus(env, CSR_MSTATUS, newval);
+}
+
+static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *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);
+    return write_mie(env, CSR_MIE, newval);
+}
+
+static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->stvec;
+    return 0;
+}
+
+static int write_stvec(CPURISCVState *env, int csrno, target_ulong val)
+{
+    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+    if ((val & 3) == 0) {
+        env->stvec = val >> 2 << 2;
+    } else {
+        qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported");
+    }
+    return 0;
+}
+
+static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    if (env->priv_ver < PRIV_VERSION_1_10_0) {
+        return -1;
+    }
+    *val = env->scounteren;
+    return 0;
+}
+
+static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (env->priv_ver < PRIV_VERSION_1_10_0) {
+        return -1;
+    }
+    env->scounteren = val;
+    return 0;
+}
+
+/* Supervisor Trap Handling */
+
+static int read_sscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->sscratch;
+    return 0;
+}
+
+static int write_sscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->sscratch = val;
+    return 0;
+}
+
+static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->sepc;
+    return 0;
+}
+
+static int write_sepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->sepc = val;
+    return 0;
+}
+
+static int read_scause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->scause;
+    return 0;
+}
+
+static int write_scause(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->scause = val;
+    return 0;
+}
+
+static int read_sbadaddr(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->sbadaddr;
+    return 0;
+}
+
+static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->sbadaddr = val;
+    return 0;
+}
+
+static int read_sip(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = atomic_read(&env->mip) & env->mideleg;
+    return 0;
+}
+
+static int write_sip(CPURISCVState *env, int csrno, target_ulong val)
+{
+    target_ulong newval = (atomic_read(&env->mip) & ~env->mideleg)
+                          | (val & env->mideleg);
+    return write_mip(env, CSR_MIP, newval);
+}
+
+/* Supervisor Protection and Translation */
+
+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) {
+        *val = env->satp;
+    } else {
+        *val = env->sptbr;
+    }
+    return 0;
+}
+
+static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
+        return 0;
+    }
+    if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) {
+        tlb_flush(CPU(riscv_env_get_cpu(env)));
+        env->sptbr = val & (((target_ulong)
+            1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1);
+    }
+    if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
+        validate_vm(env, get_field(val, SATP_MODE)) &&
+        ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
+    {
+        tlb_flush(CPU(riscv_env_get_cpu(env)));
+        env->satp = val;
+    }
+    return 0;
+}
+
+/* Physical Memory Protection */
+
+static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
+    return 0;
+}
+
+static int write_pmpcfg(CPURISCVState *env, int csrno, target_ulong val)
+{
+    pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
+    return 0;
+}
+
+static int read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0);
+    return 0;
+}
+
+static int write_pmpaddr(CPURISCVState *env, int csrno, target_ulong val)
+{
+    pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val);
+    return 0;
+}
+
+#endif
+
+/*
+ * riscv_csrrw - read and/or update control and status register
+ *
+ * csrr   <->  riscv_csrrw(env, csrno, ret_value, 0, 0);
+ * csrrw  <->  riscv_csrrw(env, csrno, ret_value, value, -1);
+ * csrrs  <->  riscv_csrrw(env, csrno, ret_value, -1, value);
+ * csrrc  <->  riscv_csrrw(env, csrno, ret_value, 0, value);
+ */
+
+int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
+                target_ulong new_value, target_ulong write_mask)
+{
+    int ret;
+    target_ulong old_value;
+
+    /* check privileges and return -1 if check fails */
+#if !defined(CONFIG_USER_ONLY)
+    int csr_priv = get_field(csrno, 0x300);
+    int read_only = get_field(csrno, 0xC00) == 3;
+    if ((write_mask && read_only) || (env->priv < csr_priv)) {
+        return -1;
+    }
+#endif
+
+    /* execute combined read/write operation if it exists */
+    if (csr_ops[csrno].op) {
+        return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask);
+    }
+
+    /* if no accessor exists then return failure */
+    if (!csr_ops[csrno].read) {
+        return -1;
+    }
+
+    /* read old value */
+    ret = csr_ops[csrno].read(env, csrno, &old_value);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* write value if writable and write mask set, otherwise drop writes */
+    if (write_mask) {
+        new_value = (old_value & ~write_mask) | (new_value & write_mask);
+        if (csr_ops[csrno].write) {
+            ret = csr_ops[csrno].write(env, csrno, new_value);
+            if (ret < 0) {
+                return ret;
+            }
+        }
+    }
+
+    /* return old value */
+    if (ret_value) {
+        *ret_value = old_value;
+    }
+
+    return 0;
+}
+
+/* Control and Status Register function table */
+
+static const riscv_csr_operations csr_ops[0xfff] = {
+    /* User Floating-Point CSRs */
+    [CSR_FFLAGS] =              { read_fflags,      write_fflags      },
+    [CSR_FRM] =                 { read_frm,         write_frm         },
+    [CSR_FCSR] =                { read_fcsr,        write_fcsr        },
+
+    /* User Timers and Counters */
+    [CSR_CYCLE] =               { read_instret                        },
+    [CSR_INSTRET] =             { read_instret                        },
+#if defined(TARGET_RISCV32)
+    [CSR_CYCLEH] =              { read_instreth                       },
+    [CSR_INSTRETH] =            { read_instreth                       },
+#endif
+
+    /* User-level time CSRs are only available in linux-user
+     * In privileged mode, the monitor emulates these CSRs */
+#if defined(CONFIG_USER_ONLY)
+    [CSR_TIME] =                { read_time                           },
+#if defined(TARGET_RISCV32)
+    [CSR_TIMEH] =               { read_timeh                          },
+#endif
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
+    /* Machine Timers and Counters */
+    [CSR_MCYCLE] =              { read_instret                        },
+    [CSR_MINSTRET] =            { read_instret                        },
+#if defined(TARGET_RISCV32)
+    [CSR_MCYCLEH] =             { read_instreth                       },
+    [CSR_MINSTRETH] =           { read_instreth                       },
+#endif
+
+    /* Machine Information Registers */
+    [CSR_MVENDORID] =           { read_zero                           },
+    [CSR_MARCHID] =             { read_zero                           },
+    [CSR_MIMPID] =              { read_zero                           },
+    [CSR_MHARTID] =             { read_mhartid                        },
+
+    /* Machine Trap Setup */
+    [CSR_MSTATUS] =             { read_mstatus,     write_mstatus     },
+    [CSR_MISA] =                { read_misa                           },
+    [CSR_MIDELEG] =             { read_mideleg,     write_mideleg     },
+    [CSR_MEDELEG] =             { read_medeleg,     write_medeleg     },
+    [CSR_MIE] =                 { read_mie,         write_mie         },
+    [CSR_MTVEC] =               { read_mtvec,       write_mtvec       },
+    [CSR_MCOUNTEREN] =          { read_mcounteren,  write_mcounteren  },
+
+    /* Legacy Counter Setup (priv v1.9.1) */
+    [CSR_MUCOUNTEREN] =         { read_mucounteren, write_mucounteren },
+    [CSR_MSCOUNTEREN] =         { read_mscounteren, write_mscounteren },
+
+    /* Machine Trap Handling */
+    [CSR_MSCRATCH] =            { read_mscratch,    write_mscratch    },
+    [CSR_MEPC] =                { read_mepc,        write_mepc        },
+    [CSR_MCAUSE] =              { read_mcause,      write_mcause      },
+    [CSR_MBADADDR] =            { read_mbadaddr,    write_mbadaddr    },
+    [CSR_MIP] =                 { read_mip,         write_mip         },
+
+    /* Supervisor Trap Setup */
+    [CSR_SSTATUS] =             { read_sstatus,     write_sstatus     },
+    [CSR_SIE] =                 { read_sie,         write_sie         },
+    [CSR_STVEC] =               { read_stvec,       write_stvec       },
+    [CSR_SCOUNTEREN] =          { read_scounteren,  write_scounteren  },
+
+    /* Supervisor Trap Handling */
+    [CSR_SSCRATCH] =            { read_sscratch,    write_sscratch    },
+    [CSR_SEPC] =                { read_sepc,        write_sepc        },
+    [CSR_SCAUSE] =              { read_scause,      write_scause      },
+    [CSR_SBADADDR] =            { read_sbadaddr,    write_sbadaddr    },
+    [CSR_SIP] =                 { read_sip,         write_sip         },
+
+    /* Supervisor Protection and Translation */
+    [CSR_SATP] =                { read_satp,        write_satp        },
+
+    /* Physical Memory Protection */
+    [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { read_pmpcfg,  write_pmpcfg   },
+    [CSR_PMPADDR0 ... CSR_PMPADDR15] = { read_pmpaddr, write_pmpaddr  },
+
+    /* Performance Counters */
+    [CSR_HPMCOUNTER3   ... CSR_HPMCOUNTER31] =    { read_zero_counter },
+    [CSR_MHPMCOUNTER3  ... CSR_MHPMCOUNTER31] =   { read_zero         },
+    [CSR_MHPMEVENT3    ... CSR_MHPMEVENT31] =     { read_zero         },
+#if defined(TARGET_RISCV32)
+    [CSR_HPMCOUNTER3H  ... CSR_HPMCOUNTER31H] =   { read_zero_counter },
+    [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] =  { read_zero         },
+#endif
+#endif
+};
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 4f919b6c3413..3cabb21cd012 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -33,7 +33,10 @@ int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
     } else if (n < 65) {
         return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
     } else if (n < 4096 + 65) {
-        return gdb_get_regl(mem_buf, csr_read_helper(env, n - 65));
+        target_ulong val = 0;
+        if (riscv_csrrw(env, n - 65, &val, 0, 0) == 0) {
+            return gdb_get_regl(mem_buf, val);
+        }
     }
     return 0;
 }
@@ -56,7 +59,10 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
         env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
         return sizeof(uint64_t);
     } else if (n < 4096 + 65) {
-        csr_write_helper(env, ldtul_p(mem_buf), n - 65);
+        target_ulong val = ldtul_p(mem_buf);
+        if (riscv_csrrw(env, n - 65, NULL, val, -1) == 0) {
+            return sizeof(target_ulong);
+        }
     }
     return 0;
 }
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index fd2efcb49929..81bd1a77ea90 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -24,39 +24,6 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 
-#ifndef CONFIG_USER_ONLY
-
-#if defined(TARGET_RISCV32)
-static const char valid_vm_1_09[16] = {
-    [VM_1_09_MBARE] = 1,
-    [VM_1_09_SV32] = 1,
-};
-static const char valid_vm_1_10[16] = {
-    [VM_1_10_MBARE] = 1,
-    [VM_1_10_SV32] = 1
-};
-#elif defined(TARGET_RISCV64)
-static const char valid_vm_1_09[16] = {
-    [VM_1_09_MBARE] = 1,
-    [VM_1_09_SV39] = 1,
-    [VM_1_09_SV48] = 1,
-};
-static const char valid_vm_1_10[16] = {
-    [VM_1_10_MBARE] = 1,
-    [VM_1_10_SV39] = 1,
-    [VM_1_10_SV48] = 1,
-    [VM_1_10_SV57] = 1
-};
-#endif
-
-static int validate_vm(CPURISCVState *env, target_ulong vm)
-{
-    return (env->priv_ver >= PRIV_VERSION_1_10_0) ?
-        valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf];
-}
-
-#endif
-
 /* Exceptions processing helpers */
 void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
                                           uint32_t exception, uintptr_t pc)
@@ -72,582 +39,34 @@ void helper_raise_exception(CPURISCVState *env, uint32_t exception)
     do_raise_exception_err(env, exception, 0);
 }
 
-static void validate_mstatus_fs(CPURISCVState *env, uintptr_t ra)
-{
-#ifndef CONFIG_USER_ONLY
-    if (!(env->mstatus & MSTATUS_FS)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, ra);
-    }
-#endif
-}
-
-/*
- * Handle writes to CSRs and any resulting special behavior
- *
- * Adapted from Spike's processor_t::set_csr
- */
-void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
-        target_ulong csrno)
-{
-#ifndef CONFIG_USER_ONLY
-    uint64_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP | MIP_SCIP;
-    uint64_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP | MIP_MCIP;
-#endif
-
-    switch (csrno) {
-    case CSR_FFLAGS:
-        validate_mstatus_fs(env, GETPC());
-        cpu_riscv_set_fflags(env, val_to_write & (FSR_AEXC >> FSR_AEXC_SHIFT));
-        break;
-    case CSR_FRM:
-        validate_mstatus_fs(env, GETPC());
-        env->frm = val_to_write & (FSR_RD >> FSR_RD_SHIFT);
-        break;
-    case CSR_FCSR:
-        validate_mstatus_fs(env, GETPC());
-        env->frm = (val_to_write & FSR_RD) >> FSR_RD_SHIFT;
-        cpu_riscv_set_fflags(env, (val_to_write & FSR_AEXC) >> FSR_AEXC_SHIFT);
-        break;
-#ifndef CONFIG_USER_ONLY
-    case CSR_MSTATUS: {
-        target_ulong mstatus = env->mstatus;
-        target_ulong mask = 0;
-        target_ulong mpp = get_field(val_to_write, MSTATUS_MPP);
-
-        /* flush tlb on mstatus fields that affect VM */
-        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
-            if ((val_to_write ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
-                    MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) {
-                helper_tlb_flush(env);
-            }
-            mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
-                MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
-                MSTATUS_MPP | MSTATUS_MXR |
-                (validate_vm(env, get_field(val_to_write, MSTATUS_VM)) ?
-                    MSTATUS_VM : 0);
-        }
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            if ((val_to_write ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
-                    MSTATUS_MPRV | MSTATUS_SUM)) {
-                helper_tlb_flush(env);
-            }
-            mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
-                MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
-                MSTATUS_MPP | MSTATUS_MXR;
-        }
-
-        /* silenty discard mstatus.mpp writes for unsupported modes */
-        if (mpp == PRV_H ||
-            (!riscv_has_ext(env, RVS) && mpp == PRV_S) ||
-            (!riscv_has_ext(env, RVU) && mpp == PRV_U)) {
-            mask &= ~MSTATUS_MPP;
-        }
-
-        mstatus = (mstatus & ~mask) | (val_to_write & mask);
-
-        /* Note: this is a workaround for an issue where mstatus.FS
-           does not report dirty after floating point operations
-           that modify floating point state. This workaround is
-           technically compliant with the RISC-V Privileged
-           specification as it is legal to return only off, or dirty.
-           at the expense of extra floating point save/restore. */
-
-        /* FP is always dirty or off */
-        if (mstatus & MSTATUS_FS) {
-            mstatus |= MSTATUS_FS;
-        }
-
-        int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
-                    ((mstatus & MSTATUS_XS) == MSTATUS_XS);
-        mstatus = set_field(mstatus, MSTATUS_SD, dirty);
-        env->mstatus = mstatus;
-        break;
-    }
-    case CSR_MIP: {
-        /*
-         * Since the writeable bits in MIP are not set asynchrously by the
-         * CLINT, no additional locking is needed for read-modifiy-write
-         * CSR operations
-         */
-        qemu_mutex_lock_iothread();
-        RISCVCPU *cpu = riscv_env_get_cpu(env);
-        riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
-                                  (val_to_write & (MIP_SSIP | MIP_STIP)));
-        /*
-         * csrs, csrc on mip.SEIP is not decomposable into separate read and
-         * write steps, so a different implementation is needed
-         */
-        qemu_mutex_unlock_iothread();
-        break;
-    }
-    case CSR_MIE: {
-        env->mie = (env->mie & ~all_ints) |
-            (val_to_write & all_ints);
-        break;
-    }
-    case CSR_MIDELEG:
-        env->mideleg = (env->mideleg & ~delegable_ints)
-                                | (val_to_write & delegable_ints);
-        break;
-    case CSR_MEDELEG: {
-        target_ulong mask = 0;
-        mask |= 1ULL << (RISCV_EXCP_INST_ADDR_MIS);
-        mask |= 1ULL << (RISCV_EXCP_INST_ACCESS_FAULT);
-        mask |= 1ULL << (RISCV_EXCP_ILLEGAL_INST);
-        mask |= 1ULL << (RISCV_EXCP_BREAKPOINT);
-        mask |= 1ULL << (RISCV_EXCP_LOAD_ADDR_MIS);
-        mask |= 1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT);
-        mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS);
-        mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT);
-        mask |= 1ULL << (RISCV_EXCP_U_ECALL);
-        mask |= 1ULL << (RISCV_EXCP_S_ECALL);
-        mask |= 1ULL << (RISCV_EXCP_H_ECALL);
-        mask |= 1ULL << (RISCV_EXCP_M_ECALL);
-        mask |= 1ULL << (RISCV_EXCP_INST_PAGE_FAULT);
-        mask |= 1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT);
-        mask |= 1ULL << (RISCV_EXCP_STORE_PAGE_FAULT);
-        env->medeleg = (env->medeleg & ~mask)
-                                | (val_to_write & mask);
-        break;
-    }
-    case CSR_MINSTRET:
-        /* minstret is WARL so unsupported writes are ignored */
-        break;
-    case CSR_MCYCLE:
-        /* mcycle is WARL so unsupported writes are ignored */
-        break;
-#if defined(TARGET_RISCV32)
-    case CSR_MINSTRETH:
-        /* minstreth is WARL so unsupported writes are ignored */
-        break;
-    case CSR_MCYCLEH:
-        /* mcycleh is WARL so unsupported writes are ignored */
-        break;
-#endif
-    case CSR_MUCOUNTEREN:
-        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
-            env->scounteren = val_to_write;
-            break;
-        } else {
-            goto do_illegal;
-        }
-    case CSR_MSCOUNTEREN:
-        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
-            env->mcounteren = val_to_write;
-            break;
-        } else {
-            goto do_illegal;
-        }
-    case CSR_SSTATUS: {
-        target_ulong ms = env->mstatus;
-        target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
-            | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
-            | SSTATUS_SUM | SSTATUS_SD;
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            mask |= SSTATUS_MXR;
-        }
-        ms = (ms & ~mask) | (val_to_write & mask);
-        csr_write_helper(env, ms, CSR_MSTATUS);
-        break;
-    }
-    case CSR_SIP: {
-        qemu_mutex_lock_iothread();
-        target_ulong next_mip = (env->mip & ~env->mideleg)
-                                | (val_to_write & env->mideleg);
-        qemu_mutex_unlock_iothread();
-        csr_write_helper(env, next_mip, CSR_MIP);
-        break;
-    }
-    case CSR_SIE: {
-        target_ulong next_mie = (env->mie & ~env->mideleg)
-                                | (val_to_write & env->mideleg);
-        csr_write_helper(env, next_mie, CSR_MIE);
-        break;
-    }
-    case CSR_SATP: /* CSR_SPTBR */ {
-        if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
-            break;
-        }
-        if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr))
-        {
-            helper_tlb_flush(env);
-            env->sptbr = val_to_write & (((target_ulong)
-                1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1);
-        }
-        if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
-            validate_vm(env, get_field(val_to_write, SATP_MODE)) &&
-            ((val_to_write ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
-        {
-            helper_tlb_flush(env);
-            env->satp = val_to_write;
-        }
-        break;
-    }
-    case CSR_SEPC:
-        env->sepc = val_to_write;
-        break;
-    case CSR_STVEC:
-        /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
-        if ((val_to_write & 3) == 0) {
-            env->stvec = val_to_write >> 2 << 2;
-        } else {
-            qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported");
-        }
-        break;
-    case CSR_SCOUNTEREN:
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            env->scounteren = val_to_write;
-            break;
-        } else {
-            goto do_illegal;
-        }
-    case CSR_SSCRATCH:
-        env->sscratch = val_to_write;
-        break;
-    case CSR_SCAUSE:
-        env->scause = val_to_write;
-        break;
-    case CSR_SBADADDR:
-        env->sbadaddr = val_to_write;
-        break;
-    case CSR_MEPC:
-        env->mepc = val_to_write;
-        break;
-    case CSR_MTVEC:
-        /* bits [1:0] indicate mode; 0 = direct, 1 = vectored, 2 >= reserved */
-        if ((val_to_write & 3) == 0) {
-            env->mtvec = val_to_write >> 2 << 2;
-        } else {
-            qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported");
-        }
-        break;
-    case CSR_MCOUNTEREN:
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            env->mcounteren = val_to_write;
-            break;
-        } else {
-            goto do_illegal;
-        }
-    case CSR_MSCRATCH:
-        env->mscratch = val_to_write;
-        break;
-    case CSR_MCAUSE:
-        env->mcause = val_to_write;
-        break;
-    case CSR_MBADADDR:
-        env->mbadaddr = val_to_write;
-        break;
-    case CSR_MISA:
-        /* misa is WARL so unsupported writes are ignored */
-        break;
-    case CSR_PMPCFG0:
-    case CSR_PMPCFG1:
-    case CSR_PMPCFG2:
-    case CSR_PMPCFG3:
-       pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val_to_write);
-       break;
-    case CSR_PMPADDR0:
-    case CSR_PMPADDR1:
-    case CSR_PMPADDR2:
-    case CSR_PMPADDR3:
-    case CSR_PMPADDR4:
-    case CSR_PMPADDR5:
-    case CSR_PMPADDR6:
-    case CSR_PMPADDR7:
-    case CSR_PMPADDR8:
-    case CSR_PMPADDR9:
-    case CSR_PMPADDR10:
-    case CSR_PMPADDR11:
-    case CSR_PMPADDR12:
-    case CSR_PMPADDR13:
-    case CSR_PMPADDR14:
-    case CSR_PMPADDR15:
-       pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write);
-       break;
-#endif
-#if !defined(CONFIG_USER_ONLY)
-    do_illegal:
-#endif
-    default:
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
-    }
-}
-
-/*
- * Handle reads to CSRs and any resulting special behavior
- *
- * Adapted from Spike's processor_t::get_csr
- */
-target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
-{
-#ifndef CONFIG_USER_ONLY
-    target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
-                          env->priv == PRV_S ? env->mcounteren : -1U;
-#else
-    target_ulong ctr_en = -1;
-#endif
-    target_ulong ctr_ok = (ctr_en >> (csrno & 31)) & 1;
-
-    if (csrno >= CSR_HPMCOUNTER3 && csrno <= CSR_HPMCOUNTER31) {
-        if (ctr_ok) {
-            return 0;
-        }
-    }
-#if defined(TARGET_RISCV32)
-    if (csrno >= CSR_HPMCOUNTER3H && csrno <= CSR_HPMCOUNTER31H) {
-        if (ctr_ok) {
-            return 0;
-        }
-    }
-#endif
-    if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) {
-        return 0;
-    }
-#if defined(TARGET_RISCV32)
-    if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) {
-        return 0;
-    }
-#endif
-    if (csrno >= CSR_MHPMEVENT3 && csrno <= CSR_MHPMEVENT31) {
-        return 0;
-    }
-
-    switch (csrno) {
-    case CSR_FFLAGS:
-        validate_mstatus_fs(env, GETPC());
-        return cpu_riscv_get_fflags(env);
-    case CSR_FRM:
-        validate_mstatus_fs(env, GETPC());
-        return env->frm;
-    case CSR_FCSR:
-        validate_mstatus_fs(env, GETPC());
-        return (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
-                | (env->frm << FSR_RD_SHIFT);
-    /* rdtime/rdtimeh is trapped and emulated by bbl in system mode */
-#ifdef CONFIG_USER_ONLY
-    case CSR_TIME:
-        return cpu_get_host_ticks();
-#if defined(TARGET_RISCV32)
-    case CSR_TIMEH:
-        return cpu_get_host_ticks() >> 32;
-#endif
-#endif
-    case CSR_INSTRET:
-    case CSR_CYCLE:
-        if (ctr_ok) {
-#if !defined(CONFIG_USER_ONLY)
-            if (use_icount) {
-                return cpu_get_icount();
-            } else {
-                return cpu_get_host_ticks();
-            }
-#else
-            return cpu_get_host_ticks();
-#endif
-        }
-        break;
-#if defined(TARGET_RISCV32)
-    case CSR_INSTRETH:
-    case CSR_CYCLEH:
-        if (ctr_ok) {
-#if !defined(CONFIG_USER_ONLY)
-            if (use_icount) {
-                return cpu_get_icount() >> 32;
-            } else {
-                return cpu_get_host_ticks() >> 32;
-            }
-#else
-            return cpu_get_host_ticks() >> 32;
-#endif
-        }
-        break;
-#endif
-#ifndef CONFIG_USER_ONLY
-    case CSR_MINSTRET:
-    case CSR_MCYCLE:
-        if (use_icount) {
-            return cpu_get_icount();
-        } else {
-            return cpu_get_host_ticks();
-        }
-    case CSR_MINSTRETH:
-    case CSR_MCYCLEH:
-#if defined(TARGET_RISCV32)
-        if (use_icount) {
-            return cpu_get_icount() >> 32;
-        } else {
-            return cpu_get_host_ticks() >> 32;
-        }
-#endif
-        break;
-    case CSR_MUCOUNTEREN:
-        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
-            return env->scounteren;
-        } else {
-            break; /* illegal instruction */
-        }
-    case CSR_MSCOUNTEREN:
-        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
-            return env->mcounteren;
-        } else {
-            break; /* illegal instruction */
-        }
-    case CSR_SSTATUS: {
-        target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
-            | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
-            | SSTATUS_SUM | SSTATUS_SD;
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            mask |= SSTATUS_MXR;
-        }
-        return env->mstatus & mask;
-    }
-    case CSR_SIP: {
-        qemu_mutex_lock_iothread();
-        target_ulong tmp = env->mip & env->mideleg;
-        qemu_mutex_unlock_iothread();
-        return tmp;
-    }
-    case CSR_SIE:
-        return env->mie & env->mideleg;
-    case CSR_SEPC:
-        return env->sepc;
-    case CSR_SBADADDR:
-        return env->sbadaddr;
-    case CSR_STVEC:
-        return env->stvec;
-    case CSR_SCOUNTEREN:
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            return env->scounteren;
-        } else {
-            break; /* illegal instruction */
-        }
-    case CSR_SCAUSE:
-        return env->scause;
-    case CSR_SATP: /* CSR_SPTBR */
-        if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
-            return 0;
-        }
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            return env->satp;
-        } else {
-            return env->sptbr;
-        }
-    case CSR_SSCRATCH:
-        return env->sscratch;
-    case CSR_MSTATUS:
-        return env->mstatus;
-    case CSR_MIP: {
-        qemu_mutex_lock_iothread();
-        target_ulong tmp = env->mip;
-        qemu_mutex_unlock_iothread();
-        return tmp;
-    }
-    case CSR_MIE:
-        return env->mie;
-    case CSR_MEPC:
-        return env->mepc;
-    case CSR_MSCRATCH:
-        return env->mscratch;
-    case CSR_MCAUSE:
-        return env->mcause;
-    case CSR_MBADADDR:
-        return env->mbadaddr;
-    case CSR_MISA:
-        return env->misa;
-    case CSR_MARCHID:
-        return 0; /* as spike does */
-    case CSR_MIMPID:
-        return 0; /* as spike does */
-    case CSR_MVENDORID:
-        return 0; /* as spike does */
-    case CSR_MHARTID:
-        return env->mhartid;
-    case CSR_MTVEC:
-        return env->mtvec;
-    case CSR_MCOUNTEREN:
-        if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-            return env->mcounteren;
-        } else {
-            break; /* illegal instruction */
-        }
-    case CSR_MEDELEG:
-        return env->medeleg;
-    case CSR_MIDELEG:
-        return env->mideleg;
-    case CSR_PMPCFG0:
-    case CSR_PMPCFG1:
-    case CSR_PMPCFG2:
-    case CSR_PMPCFG3:
-       return pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
-    case CSR_PMPADDR0:
-    case CSR_PMPADDR1:
-    case CSR_PMPADDR2:
-    case CSR_PMPADDR3:
-    case CSR_PMPADDR4:
-    case CSR_PMPADDR5:
-    case CSR_PMPADDR6:
-    case CSR_PMPADDR7:
-    case CSR_PMPADDR8:
-    case CSR_PMPADDR9:
-    case CSR_PMPADDR10:
-    case CSR_PMPADDR11:
-    case CSR_PMPADDR12:
-    case CSR_PMPADDR13:
-    case CSR_PMPADDR14:
-    case CSR_PMPADDR15:
-       return pmpaddr_csr_read(env, csrno - CSR_PMPADDR0);
-#endif
-    }
-    /* used by e.g. MTIME read */
-    do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
-}
-
-/*
- * Check that CSR access is allowed.
- *
- * Adapted from Spike's decode.h:validate_csr
- */
-static void validate_csr(CPURISCVState *env, uint64_t which,
-                         uint64_t write, uintptr_t ra)
-{
-#ifndef CONFIG_USER_ONLY
-    unsigned csr_priv = get_field((which), 0x300);
-    unsigned csr_read_only = get_field((which), 0xC00) == 3;
-    if (((write) && csr_read_only) || (env->priv < csr_priv)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, ra);
-    }
-#endif
-}
-
 target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
         target_ulong csr)
 {
-    validate_csr(env, csr, 1, GETPC());
-    uint64_t csr_backup = csr_read_helper(env, csr);
-    csr_write_helper(env, src, csr);
-    return csr_backup;
+    target_ulong val = 0;
+    if (riscv_csrrw(env, csr, &val, src, -1) < 0) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
+    return val;
 }
 
 target_ulong helper_csrrs(CPURISCVState *env, target_ulong src,
         target_ulong csr, target_ulong rs1_pass)
 {
-    validate_csr(env, csr, rs1_pass != 0, GETPC());
-    uint64_t csr_backup = csr_read_helper(env, csr);
-    if (rs1_pass != 0) {
-        csr_write_helper(env, src | csr_backup, csr);
+    target_ulong val = 0;
+    if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
-    return csr_backup;
+    return val;
 }
 
 target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
         target_ulong csr, target_ulong rs1_pass)
 {
-    validate_csr(env, csr, rs1_pass != 0, GETPC());
-    uint64_t csr_backup = csr_read_helper(env, csr);
-    if (rs1_pass != 0) {
-        csr_write_helper(env, (~src) & csr_backup, csr);
+    target_ulong val = 0;
+    if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
-    return csr_backup;
+    return val;
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -672,7 +91,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_set_mode(env, prev_priv);
-    csr_write_helper(env, mstatus, CSR_MSTATUS);
+    env->mstatus = mstatus;
 
     return retpc;
 }
@@ -697,7 +116,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_set_mode(env, prev_priv);
-    csr_write_helper(env, mstatus, CSR_MSTATUS);
+    env->mstatus = mstatus;
 
     return retpc;
 }
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (7 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 08/30] RISC-V: Implement modular CSR helper interface Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-29 23:34   ` Alistair Francis
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 10/30] RISC-V: Implement existential predicates for CSRs Michael Clark
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Use the new CSR read/modify/write interface to implement
atomic updates to mip/sip.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/csr.c | 56 +++++++++++++++++++++++++++---------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e08f3523d854..631a5ff9f7d8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -493,25 +493,31 @@ static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
-static int read_mip(CPURISCVState *env, int csrno, target_ulong *val)
-{
-    *val = atomic_read(&env->mip);
-    return 0;
-}
-
-static int write_mip(CPURISCVState *env, int csrno, target_ulong val)
+static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
+                   target_ulong new_value, target_ulong write_mask)
 {
     RISCVCPU *cpu = riscv_env_get_cpu(env);
+    target_ulong mask = write_mask & delegable_ints;
+    uint32_t old_mip;
+
+    /* We can't allow the supervisor to control SEIP as this would allow the
+     * supervisor to clear a pending external interrupt which will result in
+     * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
+     * hardware controlled when a PLIC is attached. This should be an option
+     * for CPUs with software-delegated Supervisor External Interrupts. */
+    mask &= ~MIP_SEIP;
+
+    if (mask) {
+        qemu_mutex_lock_iothread();
+        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
+        qemu_mutex_unlock_iothread();
+    } else {
+        old_mip = atomic_read(&env->mip);
+    }
 
-    /*
-     * csrs, csrc on mip.SEIP is not decomposable into separate read and
-     * write steps, so a different implementation is needed
-     */
-
-    qemu_mutex_lock_iothread();
-    riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
-                         (val & (MIP_SSIP | MIP_STIP)));
-    qemu_mutex_unlock_iothread();
+    if (ret_value) {
+        *ret_value = old_mip;
+    }
 
     return 0;
 }
@@ -631,17 +637,11 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
     return 0;
 }
 
-static int read_sip(CPURISCVState *env, int csrno, target_ulong *val)
-{
-    *val = atomic_read(&env->mip) & env->mideleg;
-    return 0;
-}
-
-static int write_sip(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)
 {
-    target_ulong newval = (atomic_read(&env->mip) & ~env->mideleg)
-                          | (val & env->mideleg);
-    return write_mip(env, CSR_MIP, newval);
+    return rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
+                   write_mask & env->mideleg);
 }
 
 /* Supervisor Protection and Translation */
@@ -823,7 +823,7 @@ static const riscv_csr_operations csr_ops[0xfff] = {
     [CSR_MEPC] =                { read_mepc,        write_mepc        },
     [CSR_MCAUSE] =              { read_mcause,      write_mcause      },
     [CSR_MBADADDR] =            { read_mbadaddr,    write_mbadaddr    },
-    [CSR_MIP] =                 { read_mip,         write_mip         },
+    [CSR_MIP] =                 { NULL,     NULL,     rmw_mip         },
 
     /* Supervisor Trap Setup */
     [CSR_SSTATUS] =             { read_sstatus,     write_sstatus     },
@@ -836,7 +836,7 @@ static const riscv_csr_operations csr_ops[0xfff] = {
     [CSR_SEPC] =                { read_sepc,        write_sepc        },
     [CSR_SCAUSE] =              { read_scause,      write_scause      },
     [CSR_SBADADDR] =            { read_sbadaddr,    write_sbadaddr    },
-    [CSR_SIP] =                 { read_sip,         write_sip         },
+    [CSR_SIP] =                 { NULL,     NULL,     rmw_sip         },
 
     /* Supervisor Protection and Translation */
     [CSR_SATP] =                { read_satp,        write_satp        },
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 10/30] RISC-V: Implement existential predicates for CSRs
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (8 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

CSR predicate functions are added to the CSR table.
mstatus.FS and counter enable checks are moved
to predicate functions and two new predicates are
added to check misa.S for s* CSRs and a new PMP
CPU feature for pmp* CSRs.

Processors that don't implement S-mode will trap
on access to s* CSRs and processors that don't
implement PMP will trap on accesses to pmp* CSRs.

PMP checks are disabled in riscv_cpu_handle_mmu_fault
when the PMP CPU feature is not present.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu.c        |   6 ++
 target/riscv/cpu.h        |   5 +-
 target/riscv/cpu_helper.c |   3 +-
 target/riscv/csr.c        | 172 ++++++++++++++++++++++++++--------------------
 4 files changed, 107 insertions(+), 79 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d630e8fd6c62..9f47f2072c56 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -124,6 +124,7 @@ static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
     set_resetvec(env, DEFAULT_RSTVEC);
     set_feature(env, RISCV_FEATURE_MMU);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
@@ -133,6 +134,7 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
     set_resetvec(env, DEFAULT_RSTVEC);
     set_feature(env, RISCV_FEATURE_MMU);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 static void rv32imacu_nommu_cpu_init(Object *obj)
@@ -141,6 +143,7 @@ static void rv32imacu_nommu_cpu_init(Object *obj)
     set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
     set_resetvec(env, DEFAULT_RSTVEC);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 #elif defined(TARGET_RISCV64)
@@ -152,6 +155,7 @@ static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
     set_resetvec(env, DEFAULT_RSTVEC);
     set_feature(env, RISCV_FEATURE_MMU);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 static void rv64gcsu_priv1_10_0_cpu_init(Object *obj)
@@ -161,6 +165,7 @@ static void rv64gcsu_priv1_10_0_cpu_init(Object *obj)
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
     set_resetvec(env, DEFAULT_RSTVEC);
     set_feature(env, RISCV_FEATURE_MMU);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 static void rv64imacu_nommu_cpu_init(Object *obj)
@@ -169,6 +174,7 @@ static void rv64imacu_nommu_cpu_init(Object *obj)
     set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
     set_resetvec(env, DEFAULT_RSTVEC);
+    set_feature(env, RISCV_FEATURE_PMP);
 }
 
 #endif
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 02c60c45631b..3a3d91447736 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -83,9 +83,10 @@
 /* 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
    is currently no bit in misa to indicate whether an MMU exists or not
-   so a cpu features bitfield is required */
+   so a cpu features bitfield is required, likewise for optional PMP support */
 enum {
-    RISCV_FEATURE_MMU
+    RISCV_FEATURE_MMU,
+    RISCV_FEATURE_PMP
 };
 
 #define USER_VERSION_2_02_0 0x00020200
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 1f523861b7cb..bc15e19022cc 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -404,7 +404,8 @@ int riscv_cpu_handle_mmu_fault(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 (!pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << rw)) {
+    if (riscv_feature(env, RISCV_FEATURE_PMP) &&
+        !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << rw)) {
         ret = TRANSLATE_FAIL;
     }
     if (ret == TRANSLATE_SUCCESS) {
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 631a5ff9f7d8..0e6c0c365154 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -26,6 +26,7 @@
 
 /* Control and Status Register function table forward declaration */
 
+typedef int (*riscv_csr_predicate_fn)(CPURISCVState *env, int csrno);
 typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
     target_ulong *ret_value);
 typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
@@ -34,6 +35,7 @@ typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
     target_ulong *ret_value, target_ulong new_value, target_ulong write_mask);
 
 typedef struct {
+    riscv_csr_predicate_fn predicate;
     riscv_csr_read_fn read;
     riscv_csr_write_fn write;
     riscv_csr_op_fn op;
@@ -42,6 +44,47 @@ typedef struct {
 static const riscv_csr_operations csr_ops[];
 
 
+/* Predicates */
+
+static int fs(CPURISCVState *env, int csrno)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if (!(env->mstatus & MSTATUS_FS)) {
+        return -1;
+    }
+#endif
+    return 0;
+}
+
+static int ctr(CPURISCVState *env, int csrno)
+{
+#if !defined(CONFIG_USER_ONLY)
+    target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
+                          env->priv == PRV_S ? env->mcounteren : -1U;
+    if (!(ctr_en & (1 << (csrno & 31)))) {
+        return -1;
+    }
+#endif
+    return 0;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+static int any(CPURISCVState *env, int csrno)
+{
+    return 0;
+}
+
+static int smode(CPURISCVState *env, int csrno)
+{
+    return -!riscv_has_ext(env, RVS);
+}
+
+static int pmp(CPURISCVState *env, int csrno)
+{
+    return -!riscv_feature(env, RISCV_FEATURE_PMP);
+}
+#endif
+
 /* User Floating-Point CSRs */
 
 static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
@@ -117,33 +160,8 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
 
 /* User Timers and Counters */
 
-static int counter_enabled(CPURISCVState *env, int csrno)
-{
-#ifndef CONFIG_USER_ONLY
-    target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
-                          env->priv == PRV_S ? env->mcounteren : -1U;
-#else
-    target_ulong ctr_en = -1;
-#endif
-    return (ctr_en >> (csrno & 31)) & 1;
-}
-
-#if !defined(CONFIG_USER_ONLY)
-static int read_zero_counter(CPURISCVState *env, int csrno, target_ulong *val)
-{
-    if (!counter_enabled(env, csrno)) {
-        return -1;
-    }
-    *val = 0;
-    return 0;
-}
-#endif
-
 static int read_instret(CPURISCVState *env, int csrno, target_ulong *val)
 {
-    if (!counter_enabled(env, csrno)) {
-        return -1;
-    }
 #if !defined(CONFIG_USER_ONLY)
     if (use_icount) {
         *val = cpu_get_icount();
@@ -159,9 +177,6 @@ static int read_instret(CPURISCVState *env, int csrno, target_ulong *val)
 #if defined(TARGET_RISCV32)
 static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)
 {
-    if (!counter_enabled(env, csrno)) {
-        return -1;
-    }
 #if !defined(CONFIG_USER_ONLY)
     if (use_icount) {
         *val = cpu_get_icount() >> 32;
@@ -730,6 +745,11 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
     }
 #endif
 
+    /* check predicate */
+    if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) {
+        return -1;
+    }
+
     /* execute combined read/write operation if it exists */
     if (csr_ops[csrno].op) {
         return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask);
@@ -769,89 +789,89 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
 
 static const riscv_csr_operations csr_ops[0xfff] = {
     /* User Floating-Point CSRs */
-    [CSR_FFLAGS] =              { read_fflags,      write_fflags      },
-    [CSR_FRM] =                 { read_frm,         write_frm         },
-    [CSR_FCSR] =                { read_fcsr,        write_fcsr        },
+    [CSR_FFLAGS] =              { fs,   read_fflags,      write_fflags      },
+    [CSR_FRM] =                 { fs,   read_frm,         write_frm         },
+    [CSR_FCSR] =                { fs,   read_fcsr,        write_fcsr        },
 
     /* User Timers and Counters */
-    [CSR_CYCLE] =               { read_instret                        },
-    [CSR_INSTRET] =             { read_instret                        },
+    [CSR_CYCLE] =               { ctr,  read_instret                        },
+    [CSR_INSTRET] =             { ctr,  read_instret                        },
 #if defined(TARGET_RISCV32)
-    [CSR_CYCLEH] =              { read_instreth                       },
-    [CSR_INSTRETH] =            { read_instreth                       },
+    [CSR_CYCLEH] =              { ctr,  read_instreth                       },
+    [CSR_INSTRETH] =            { ctr,  read_instreth                       },
 #endif
 
     /* User-level time CSRs are only available in linux-user
      * In privileged mode, the monitor emulates these CSRs */
 #if defined(CONFIG_USER_ONLY)
-    [CSR_TIME] =                { read_time                           },
+    [CSR_TIME] =                { ctr,  read_time                           },
 #if defined(TARGET_RISCV32)
-    [CSR_TIMEH] =               { read_timeh                          },
+    [CSR_TIMEH] =               { ctr,  read_timeh                          },
 #endif
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
     /* Machine Timers and Counters */
-    [CSR_MCYCLE] =              { read_instret                        },
-    [CSR_MINSTRET] =            { read_instret                        },
+    [CSR_MCYCLE] =              { any,  read_instret                        },
+    [CSR_MINSTRET] =            { any,  read_instret                        },
 #if defined(TARGET_RISCV32)
-    [CSR_MCYCLEH] =             { read_instreth                       },
-    [CSR_MINSTRETH] =           { read_instreth                       },
+    [CSR_MCYCLEH] =             { any,  read_instreth                       },
+    [CSR_MINSTRETH] =           { any,  read_instreth                       },
 #endif
 
     /* Machine Information Registers */
-    [CSR_MVENDORID] =           { read_zero                           },
-    [CSR_MARCHID] =             { read_zero                           },
-    [CSR_MIMPID] =              { read_zero                           },
-    [CSR_MHARTID] =             { read_mhartid                        },
+    [CSR_MVENDORID] =           { any,  read_zero                           },
+    [CSR_MARCHID] =             { any,  read_zero                           },
+    [CSR_MIMPID] =              { any,  read_zero                           },
+    [CSR_MHARTID] =             { any,  read_mhartid                        },
 
     /* Machine Trap Setup */
-    [CSR_MSTATUS] =             { read_mstatus,     write_mstatus     },
-    [CSR_MISA] =                { read_misa                           },
-    [CSR_MIDELEG] =             { read_mideleg,     write_mideleg     },
-    [CSR_MEDELEG] =             { read_medeleg,     write_medeleg     },
-    [CSR_MIE] =                 { read_mie,         write_mie         },
-    [CSR_MTVEC] =               { read_mtvec,       write_mtvec       },
-    [CSR_MCOUNTEREN] =          { read_mcounteren,  write_mcounteren  },
+    [CSR_MSTATUS] =             { any,  read_mstatus,     write_mstatus     },
+    [CSR_MISA] =                { any,  read_misa                           },
+    [CSR_MIDELEG] =             { any,  read_mideleg,     write_mideleg     },
+    [CSR_MEDELEG] =             { any,  read_medeleg,     write_medeleg     },
+    [CSR_MIE] =                 { any,  read_mie,         write_mie         },
+    [CSR_MTVEC] =               { any,  read_mtvec,       write_mtvec       },
+    [CSR_MCOUNTEREN] =          { any,  read_mcounteren,  write_mcounteren  },
 
     /* Legacy Counter Setup (priv v1.9.1) */
-    [CSR_MUCOUNTEREN] =         { read_mucounteren, write_mucounteren },
-    [CSR_MSCOUNTEREN] =         { read_mscounteren, write_mscounteren },
+    [CSR_MUCOUNTEREN] =         { any,  read_mucounteren, write_mucounteren },
+    [CSR_MSCOUNTEREN] =         { any,  read_mscounteren, write_mscounteren },
 
     /* Machine Trap Handling */
-    [CSR_MSCRATCH] =            { read_mscratch,    write_mscratch    },
-    [CSR_MEPC] =                { read_mepc,        write_mepc        },
-    [CSR_MCAUSE] =              { read_mcause,      write_mcause      },
-    [CSR_MBADADDR] =            { read_mbadaddr,    write_mbadaddr    },
-    [CSR_MIP] =                 { NULL,     NULL,     rmw_mip         },
+    [CSR_MSCRATCH] =            { any,  read_mscratch,    write_mscratch    },
+    [CSR_MEPC] =                { any,  read_mepc,        write_mepc        },
+    [CSR_MCAUSE] =              { any,  read_mcause,      write_mcause      },
+    [CSR_MBADADDR] =            { any,  read_mbadaddr,    write_mbadaddr    },
+    [CSR_MIP] =                 { any,  NULL,     NULL,     rmw_mip         },
 
     /* Supervisor Trap Setup */
-    [CSR_SSTATUS] =             { read_sstatus,     write_sstatus     },
-    [CSR_SIE] =                 { read_sie,         write_sie         },
-    [CSR_STVEC] =               { read_stvec,       write_stvec       },
-    [CSR_SCOUNTEREN] =          { read_scounteren,  write_scounteren  },
+    [CSR_SSTATUS] =             { smode, read_sstatus,     write_sstatus     },
+    [CSR_SIE] =                 { smode, read_sie,         write_sie         },
+    [CSR_STVEC] =               { smode, read_stvec,       write_stvec       },
+    [CSR_SCOUNTEREN] =          { smode, read_scounteren,  write_scounteren  },
 
     /* Supervisor Trap Handling */
-    [CSR_SSCRATCH] =            { read_sscratch,    write_sscratch    },
-    [CSR_SEPC] =                { read_sepc,        write_sepc        },
-    [CSR_SCAUSE] =              { read_scause,      write_scause      },
-    [CSR_SBADADDR] =            { read_sbadaddr,    write_sbadaddr    },
-    [CSR_SIP] =                 { NULL,     NULL,     rmw_sip         },
+    [CSR_SSCRATCH] =            { smode, read_sscratch,    write_sscratch    },
+    [CSR_SEPC] =                { smode, read_sepc,        write_sepc        },
+    [CSR_SCAUSE] =              { smode, read_scause,      write_scause      },
+    [CSR_SBADADDR] =            { smode, read_sbadaddr,    write_sbadaddr    },
+    [CSR_SIP] =                 { smode, NULL,     NULL,     rmw_sip         },
 
     /* Supervisor Protection and Translation */
-    [CSR_SATP] =                { read_satp,        write_satp        },
+    [CSR_SATP] =                { smode, read_satp,        write_satp        },
 
     /* Physical Memory Protection */
-    [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { read_pmpcfg,  write_pmpcfg   },
-    [CSR_PMPADDR0 ... CSR_PMPADDR15] = { read_pmpaddr, write_pmpaddr  },
+    [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
+    [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
 
     /* Performance Counters */
-    [CSR_HPMCOUNTER3   ... CSR_HPMCOUNTER31] =    { read_zero_counter },
-    [CSR_MHPMCOUNTER3  ... CSR_MHPMCOUNTER31] =   { read_zero         },
-    [CSR_MHPMEVENT3    ... CSR_MHPMEVENT31] =     { read_zero         },
+    [CSR_HPMCOUNTER3   ... CSR_HPMCOUNTER31] =    { ctr,  read_zero          },
+    [CSR_MHPMCOUNTER3  ... CSR_MHPMCOUNTER31] =   { any,  read_zero          },
+    [CSR_MHPMEVENT3    ... CSR_MHPMEVENT31] =     { any,  read_zero          },
 #if defined(TARGET_RISCV32)
-    [CSR_HPMCOUNTER3H  ... CSR_HPMCOUNTER31H] =   { read_zero_counter },
-    [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] =  { read_zero         },
+    [CSR_HPMCOUNTER3H  ... CSR_HPMCOUNTER31H] =   { ctr,  read_zero          },
+    [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] =  { any,  read_zero          },
 #endif
 #endif
 };
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (9 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 10/30] RISC-V: Implement existential predicates for CSRs Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-23 12:25   ` Philippe Mathieu-Daudé
  2018-05-29 23:40   ` Alistair Francis
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty Michael Clark
                   ` (18 subsequent siblings)
  29 siblings, 2 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Richard Henderson, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, Michael Clark

From: Richard Henderson <richard.henderson@linaro.org>

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu.h       |  6 +++---
 target/riscv/translate.c | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 3a3d91447736..242a8fcbe180 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -276,8 +276,8 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
 target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
 void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
 
-#define TB_FLAGS_MMU_MASK  3
-#define TB_FLAGS_FP_ENABLE MSTATUS_FS
+#define TB_FLAGS_MMU_MASK   3
+#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
 
 static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
@@ -285,7 +285,7 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     *pc = env->pc;
     *cs_base = 0;
 #ifdef CONFIG_USER_ONLY
-    *flags = TB_FLAGS_FP_ENABLE;
+    *flags = TB_FLAGS_MSTATUS_FS;
 #else
     *flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
 #endif
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ee2bbc55b051..466b9551cbd9 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -44,7 +44,7 @@ typedef struct DisasContext {
     /* pc_succ_insn points to the instruction following base.pc_next */
     target_ulong pc_succ_insn;
     uint32_t opcode;
-    uint32_t flags;
+    uint32_t mstatus_fs;
     uint32_t mem_idx;
     /* Remember the rounding mode encoded in the previous fp instruction,
        which we have already installed into env->fp_status.  Or -1 for
@@ -656,7 +656,7 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
 {
     TCGv t0;
 
-    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+    if (ctx->mstatus_fs == 0) {
         gen_exception_illegal(ctx);
         return;
     }
@@ -686,7 +686,7 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
 {
     TCGv t0;
 
-    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+    if (ctx->mstatus_fs == 0) {
         gen_exception_illegal(ctx);
         return;
     }
@@ -945,7 +945,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 {
     TCGv t0 = NULL;
 
-    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+    if (ctx->mstatus_fs == 0) {
         goto do_illegal;
     }
 
@@ -1810,8 +1810,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
     ctx->pc_succ_insn = ctx->base.pc_first;
-    ctx->flags = ctx->base.tb->flags;
     ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
+    ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
     ctx->frm = -1;  /* unknown rounding mode */
 }
 
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (10 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
@ 2018-05-23  0:14 ` Michael Clark
  2018-05-29 23:38   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
                   ` (17 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Richard Henderson, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, Michael Clark

From: Richard Henderson <richard.henderson@linaro.org>

Modifed from Richard Henderson's patch [1] to integrate
with the new control and status register implementation.

[1] https://lists.nongnu.org/archive/html/qemu-devel/2018-03/msg07034.html

Note: the f* CSRs already mark mstatus.FS dirty using
env->mstatus |= mstatus.FS so the bug in the first
spin of this patch has been fixed in a prior commit.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Michael Clark <mjc@sifive.com>

Co-authored-by: Richard Henderson <richard.henderson@linaro.org>
Co-authored-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/csr.c       | 12 ------------
 target/riscv/translate.c | 40 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0e6c0c365154..b4452388ff02 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -325,18 +325,6 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
 
     mstatus = (mstatus & ~mask) | (val & mask);
 
-    /* Note: this is a workaround for an issue where mstatus.FS
-       does not report dirty after floating point operations
-       that modify floating point state. This workaround is
-       technically compliant with the RISC-V Privileged
-       specification as it is legal to return only off, or dirty.
-       at the expense of extra floating point save/restore. */
-
-    /* FP is always dirty or off */
-    if (mstatus & MSTATUS_FS) {
-        mstatus |= MSTATUS_FS;
-    }
-
     int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
                 ((mstatus & MSTATUS_XS) == MSTATUS_XS);
     mstatus = set_field(mstatus, MSTATUS_SD, dirty);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 466b9551cbd9..a980611eb611 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -651,6 +651,31 @@ static void gen_store(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
     tcg_temp_free(dat);
 }
 
+#ifndef CONFIG_USER_ONLY
+/* The states of mstatus_fs are:
+ * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
+ * We will have already diagnosed disabled state,
+ * and need to turn initial/clean into dirty.
+ */
+static void mark_fs_dirty(DisasContext *ctx)
+{
+    TCGv tmp;
+    if (ctx->mstatus_fs == MSTATUS_FS) {
+        return;
+    }
+    /* Remember the state change for the rest of the TB.  */
+    ctx->mstatus_fs = MSTATUS_FS;
+
+    tmp = tcg_temp_new();
+    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));
+    tcg_temp_free(tmp);
+}
+#else
+static inline void mark_fs_dirty(DisasContext *ctx) { }
+#endif
+
 static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
         int rs1, target_long imm)
 {
@@ -679,6 +704,8 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
         break;
     }
     tcg_temp_free(t0);
+
+    mark_fs_dirty(ctx);
 }
 
 static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
@@ -944,6 +971,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
                          int rs1, int rs2, int rm)
 {
     TCGv t0 = NULL;
+    bool fp_output = true;
 
     if (ctx->mstatus_fs == 0) {
         goto do_illegal;
@@ -1006,6 +1034,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         }
         gen_set_gpr(rd, t0);
         tcg_temp_free(t0);
+        fp_output = false;
         break;
 
     case OPC_RISC_FCVT_W_S:
@@ -1035,6 +1064,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         }
         gen_set_gpr(rd, t0);
         tcg_temp_free(t0);
+        fp_output = false;
         break;
 
     case OPC_RISC_FCVT_S_W:
@@ -1085,6 +1115,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         }
         gen_set_gpr(rd, t0);
         tcg_temp_free(t0);
+        fp_output = false;
         break;
 
     case OPC_RISC_FMV_S_X:
@@ -1177,6 +1208,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         }
         gen_set_gpr(rd, t0);
         tcg_temp_free(t0);
+        fp_output = false;
         break;
 
     case OPC_RISC_FCVT_W_D:
@@ -1206,6 +1238,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         }
         gen_set_gpr(rd, t0);
         tcg_temp_free(t0);
+        fp_output = false;
         break;
 
     case OPC_RISC_FCVT_D_W:
@@ -1253,6 +1286,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         default:
             goto do_illegal;
         }
+        fp_output = false;
         break;
 
     case OPC_RISC_FMV_D_X:
@@ -1269,7 +1303,11 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
             tcg_temp_free(t0);
         }
         gen_exception_illegal(ctx);
-        break;
+        return;
+    }
+
+    if (fp_output) {
+        mark_fs_dirty(ctx);
     }
 }
 
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (11 preceding siblings ...)
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:26   ` Philippe Mathieu-Daudé
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 14/30] RISC-V: Add public API for the CSR dispatch table Michael Clark
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, Matthew Suozzo

This adds the necessary minimum to support S-mode
virtualization for priv ISA >= v1.10

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Matthew Suozzo <msuozzo@google.com>
Signed-off-by: Michael Clark <mjc@sifive.com>

Co-authored-by: Matthew Suozzo <msuozzo@google.com>
Co-authored-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/csr.c       | 17 +++++++++++++----
 target/riscv/op_helper.c | 25 +++++++++++++++++++++----
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b4452388ff02..509215327243 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -313,7 +313,8 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
         }
         mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
             MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
-            MSTATUS_MPP | MSTATUS_MXR;
+            MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
+            MSTATUS_TW;
     }
 
     /* silenty discard mstatus.mpp writes for unsupported modes */
@@ -654,7 +655,11 @@ 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) {
-        *val = env->satp;
+        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+            return -1;
+        } else {
+            *val = env->satp;
+        }
     } else {
         *val = env->sptbr;
     }
@@ -675,8 +680,12 @@ 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)))
     {
-        tlb_flush(CPU(riscv_env_get_cpu(env)));
-        env->satp = val;
+        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+            return -1;
+        } else {
+            tlb_flush(CPU(riscv_env_get_cpu(env)));
+            env->satp = val;
+        }
     }
     return 0;
 }
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 81bd1a77ea90..77c79ba36e0b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -82,6 +82,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
         do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
     }
 
+    if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
+        get_field(env->mstatus, MSTATUS_TSR)) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
+
     target_ulong mstatus = env->mstatus;
     target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
     mstatus = set_field(mstatus,
@@ -125,16 +130,28 @@ void helper_wfi(CPURISCVState *env)
 {
     CPUState *cs = CPU(riscv_env_get_cpu(env));
 
-    cs->halted = 1;
-    cs->exception_index = EXCP_HLT;
-    cpu_loop_exit(cs);
+    if (env->priv == PRV_S &&
+        env->priv_ver >= PRIV_VERSION_1_10_0 &&
+        get_field(env->mstatus, MSTATUS_TW)) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    } else {
+        cs->halted = 1;
+        cs->exception_index = EXCP_HLT;
+        cpu_loop_exit(cs);
+    }
 }
 
 void helper_tlb_flush(CPURISCVState *env)
 {
     RISCVCPU *cpu = riscv_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
-    tlb_flush(cs);
+    if (env->priv == PRV_S &&
+        env->priv_ver >= PRIV_VERSION_1_10_0 &&
+        get_field(env->mstatus, MSTATUS_TVM)) {
+        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    } else {
+        tlb_flush(cs);
+    }
 }
 
 #endif /* !CONFIG_USER_ONLY */
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 14/30] RISC-V: Add public API for the CSR dispatch table
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (12 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging Michael Clark
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

This allows hardware and/or derived cpu instances
to override or implement new CSR operations.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu.h | 18 ++++++++++++++++++
 target/riscv/csr.c | 35 ++++++++++++++++++-----------------
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 242a8fcbe180..1ade90d23bbc 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -307,6 +307,24 @@ static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
     return val;
 }
 
+typedef int (*riscv_csr_predicate_fn)(CPURISCVState *env, int csrno);
+typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
+    target_ulong *ret_value);
+typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
+    target_ulong new_value);
+typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
+    target_ulong *ret_value, target_ulong new_value, target_ulong write_mask);
+
+typedef struct {
+    riscv_csr_predicate_fn predicate;
+    riscv_csr_read_fn read;
+    riscv_csr_write_fn write;
+    riscv_csr_op_fn op;
+} riscv_csr_operations;
+
+void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
+void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
+
 #include "exec/cpu-all.h"
 
 #endif /* RISCV_CPU_H */
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 509215327243..0f886e04b130 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -23,28 +23,29 @@
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
 
+/* CSR function table */
 
-/* Control and Status Register function table forward declaration */
+static riscv_csr_operations csr_ops[];
 
-typedef int (*riscv_csr_predicate_fn)(CPURISCVState *env, int csrno);
-typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
-    target_ulong *ret_value);
-typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
-    target_ulong new_value);
-typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
-    target_ulong *ret_value, target_ulong new_value, target_ulong write_mask);
+/* CSR function table constants */
 
-typedef struct {
-    riscv_csr_predicate_fn predicate;
-    riscv_csr_read_fn read;
-    riscv_csr_write_fn write;
-    riscv_csr_op_fn op;
-} riscv_csr_operations;
+enum {
+    CSR_TABLE_SIZE = 0xfff
+};
+
+/* CSR function table public API */
 
-static const riscv_csr_operations csr_ops[];
+void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
+{
+    *ops = csr_ops[csrno & CSR_TABLE_SIZE];
+}
 
+void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
+{
+    csr_ops[csrno & CSR_TABLE_SIZE] = *ops;
+}
 
-/* Predicates */
+/* CSR function table predicates (private) */
 
 static int fs(CPURISCVState *env, int csrno)
 {
@@ -784,7 +785,7 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
 
 /* Control and Status Register function table */
 
-static const riscv_csr_operations csr_ops[0xfff] = {
+static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
     /* User Floating-Point CSRs */
     [CSR_FFLAGS] =              { fs,   read_fflags,      write_fflags      },
     [CSR_FRM] =                 { fs,   read_frm,         write_frm         },
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (13 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 14/30] RISC-V: Add public API for the CSR dispatch table Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:33   ` Philippe Mathieu-Daudé
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Add carriage return that was erroneously removed
when converting to qemu_log. Change hard coded
core number to the actual hartid.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu_helper.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index bc15e19022cc..69592c037042 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -446,11 +446,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     if (RISCV_DEBUG_INTERRUPT) {
         int log_cause = cs->exception_index & RISCV_EXCP_INT_MASK;
         if (cs->exception_index & RISCV_EXCP_INT_FLAG) {
-            qemu_log_mask(LOG_TRACE, "core   0: trap %s, epc 0x" TARGET_FMT_lx,
-                riscv_intr_names[log_cause], env->pc);
+            qemu_log_mask(LOG_TRACE, "core "
+                TARGET_FMT_ld ": trap %s, epc 0x" TARGET_FMT_lx "\n",
+                env->mhartid, riscv_intr_names[log_cause], env->pc);
         } else {
-            qemu_log_mask(LOG_TRACE, "core   0: intr %s, epc 0x" TARGET_FMT_lx,
-                riscv_excp_names[log_cause], env->pc);
+            qemu_log_mask(LOG_TRACE, "core "
+                TARGET_FMT_ld ": intr %s, epc 0x" TARGET_FMT_lx "\n",
+                env->mhartid, riscv_excp_names[log_cause], env->pc);
         }
     }
 
@@ -512,8 +514,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
         if (hasbadaddr) {
             if (RISCV_DEBUG_INTERRUPT) {
-                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
-                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
+                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
+                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
             }
             env->sbadaddr = env->badaddr;
         } else {
@@ -537,8 +539,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
         if (hasbadaddr) {
             if (RISCV_DEBUG_INTERRUPT) {
-                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
-                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
+                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
+                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
             }
             env->mbadaddr = env->badaddr;
         } else {
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (14 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:36   ` Philippe Mathieu-Daudé
  2018-05-29 23:43   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC Michael Clark
                   ` (13 subsequent siblings)
  29 siblings, 2 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

* Add riscv prefix to raise_exception function
* Add riscv prefix to CSR read/write functions
* Add riscv prefix to signal handler function
* Add riscv prefix to get fflags function
* Remove redundant declaration of riscv_cpu_init
  and rename cpu_riscv_init to riscv_cpu_init
* rename riscv_set_mode to riscv_cpu_set_mode

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 linux-user/riscv/signal.c |  4 ++--
 target/riscv/cpu.h        | 21 ++++++++++-----------
 target/riscv/cpu_helper.c | 10 +++++-----
 target/riscv/csr.c        |  8 ++++----
 target/riscv/fpu_helper.c |  6 +++---
 target/riscv/op_helper.c  | 28 ++++++++++++++--------------
 6 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index ef599e319a10..f03bc7212b49 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -84,7 +84,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
         __put_user(env->fpr[i], &sc->fpr[i]);
     }
 
-    uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
+    uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
     __put_user(fcsr, &sc->fcsr);
 }
 
@@ -160,7 +160,7 @@ static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
 
     uint32_t fcsr;
     __get_user(fcsr, &sc->fcsr);
-    csr_write_helper(env, fcsr, CSR_FCSR);
+    riscv_csr_write(env, CSR_FCSR, fcsr);
 }
 
 static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 1ade90d23bbc..d6bb3136db18 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -257,7 +257,7 @@ char *riscv_isa_string(RISCVCPU *cpu);
 void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
 #define cpu_init(cpu_model) cpu_generic_init(TYPE_RISCV_CPU, cpu_model)
-#define cpu_signal_handler cpu_riscv_signal_handler
+#define cpu_signal_handler riscv_cpu_signal_handler
 #define cpu_list riscv_cpu_list
 #define cpu_mmu_index riscv_cpu_mmu_index
 
@@ -265,16 +265,15 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 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 */
 #endif
-void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
 
 void riscv_translate_init(void);
-RISCVCPU *cpu_riscv_init(const char *cpu_model);
-int cpu_riscv_signal_handler(int host_signum, void *pinfo, void *puc);
-void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
-                                          uint32_t exception, uintptr_t pc);
+int riscv_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
+void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
+                                         uint32_t exception, uintptr_t pc);
 
-target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
-void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
 
 #define TB_FLAGS_MMU_MASK   3
 #define TB_FLAGS_MSTATUS_FS MSTATUS_FS
@@ -294,13 +293,13 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
 int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
                 target_ulong new_value, target_ulong write_mask);
 
-static inline void csr_write_helper(CPURISCVState *env, target_ulong val,
-                                    int csrno)
+static inline void riscv_csr_write(CPURISCVState *env, int csrno,
+                                   target_ulong val)
 {
     riscv_csrrw(env, csrno, NULL, val, -1);
 }
 
-static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
+static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
 {
     target_ulong val = 0;
     riscv_csrrw(env, csrno, &val, 0, 0);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 69592c037042..b4bbf7a9fa0a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -93,7 +93,7 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
     return old;
 }
 
-void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
 {
     if (newpriv > PRV_M) {
         g_assert_not_reached();
@@ -366,7 +366,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
         g_assert_not_reached();
     }
     env->badaddr = addr;
-    do_raise_exception_err(env, cs->exception_index, retaddr);
+    riscv_raise_exception(env, cs->exception_index, retaddr);
 }
 
 /* called by qemu's softmmu to fill the qemu tlb */
@@ -378,7 +378,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
     if (ret == TRANSLATE_FAIL) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         CPURISCVState *env = &cpu->env;
-        do_raise_exception_err(env, cs->exception_index, retaddr);
+        riscv_raise_exception(env, cs->exception_index, retaddr);
     }
 }
 
@@ -530,7 +530,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         s = set_field(s, MSTATUS_SPP, env->priv);
         s = set_field(s, MSTATUS_SIE, 0);
         env->mstatus = s;
-        riscv_set_mode(env, PRV_S);
+        riscv_cpu_set_mode(env, PRV_S);
     } else {
         /* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
         env->pc = env->mtvec;
@@ -555,7 +555,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         s = set_field(s, MSTATUS_MPP, env->priv);
         s = set_field(s, MSTATUS_MIE, 0);
         env->mstatus = s;
-        riscv_set_mode(env, PRV_M);
+        riscv_cpu_set_mode(env, PRV_M);
     }
     /* TODO yield load reservation  */
 #endif
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0f886e04b130..45e33d876034 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -95,7 +95,7 @@ static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
         return -1;
     }
 #endif
-    *val = cpu_riscv_get_fflags(env);
+    *val = riscv_cpu_get_fflags(env);
     return 0;
 }
 
@@ -107,7 +107,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
     }
     env->mstatus |= MSTATUS_FS;
 #endif
-    cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
+    riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
     return 0;
 }
 
@@ -141,7 +141,7 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
         return -1;
     }
 #endif
-    *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
+    *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
         | (env->frm << FSR_RD_SHIFT);
     return 0;
 }
@@ -155,7 +155,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
     env->mstatus |= MSTATUS_FS;
 #endif
     env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
-    cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
+    riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
     return 0;
 }
 
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index fdb87d8d82cb..1452a153f261 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -23,7 +23,7 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 
-target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
 {
     int soft = get_float_exception_flags(&env->fp_status);
     target_ulong hard = 0;
@@ -37,7 +37,7 @@ target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
     return hard;
 }
 
-void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong hard)
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
 {
     int soft = 0;
 
@@ -74,7 +74,7 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
         softrm = float_round_ties_away;
         break;
     default:
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
     set_float_rounding_mode(softrm, &env->fp_status);
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 77c79ba36e0b..b7dc18a41e21 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -25,7 +25,7 @@
 #include "exec/helper-proto.h"
 
 /* Exceptions processing helpers */
-void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
+void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
                                           uint32_t exception, uintptr_t pc)
 {
     CPUState *cs = CPU(riscv_env_get_cpu(env));
@@ -36,7 +36,7 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
 
 void helper_raise_exception(CPURISCVState *env, uint32_t exception)
 {
-    do_raise_exception_err(env, exception, 0);
+    riscv_raise_exception(env, exception, 0);
 }
 
 target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
@@ -44,7 +44,7 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
 {
     target_ulong val = 0;
     if (riscv_csrrw(env, csr, &val, src, -1) < 0) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
     return val;
 }
@@ -54,7 +54,7 @@ target_ulong helper_csrrs(CPURISCVState *env, target_ulong src,
 {
     target_ulong val = 0;
     if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
     return val;
 }
@@ -64,7 +64,7 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
 {
     target_ulong val = 0;
     if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
     return val;
 }
@@ -74,17 +74,17 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
 {
     if (!(env->priv >= PRV_S)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
     target_ulong retpc = env->sepc;
     if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
-        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
     }
 
     if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
         get_field(env->mstatus, MSTATUS_TSR)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
     target_ulong mstatus = env->mstatus;
@@ -95,7 +95,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
         get_field(mstatus, MSTATUS_SPIE));
     mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
     mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
-    riscv_set_mode(env, prev_priv);
+    riscv_cpu_set_mode(env, prev_priv);
     env->mstatus = mstatus;
 
     return retpc;
@@ -104,12 +104,12 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
 target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
 {
     if (!(env->priv >= PRV_M)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     }
 
     target_ulong retpc = env->mepc;
     if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
-        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
     }
 
     target_ulong mstatus = env->mstatus;
@@ -120,7 +120,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
         get_field(mstatus, MSTATUS_MPIE));
     mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
     mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
-    riscv_set_mode(env, prev_priv);
+    riscv_cpu_set_mode(env, prev_priv);
     env->mstatus = mstatus;
 
     return retpc;
@@ -133,7 +133,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)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     } else {
         cs->halted = 1;
         cs->exception_index = EXCP_HLT;
@@ -148,7 +148,7 @@ void helper_tlb_flush(CPURISCVState *env)
     if (env->priv == PRV_S &&
         env->priv_ver >= PRIV_VERSION_1_10_0 &&
         get_field(env->mstatus, MSTATUS_TVM)) {
-        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
     } else {
         tlb_flush(cs);
     }
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (15 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:37   ` Philippe Mathieu-Daudé
  2018-05-29 23:47   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config Michael Clark
                   ` (12 subsequent siblings)
  29 siblings, 2 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

The mode variable only uses the lower 4-bits (M,H,S,U) so
replace the GCC specific __builtin_popcount with ctpop8.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_plic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index b267ff88902d..dc6f4924e282 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -383,7 +383,7 @@ static void parse_hart_config(SiFivePLICState *plic)
     p = plic->hart_config;
     while ((c = *p++)) {
         if (c == ',') {
-            addrid += __builtin_popcount(modes);
+            addrid += ctpop8(modes);
             modes = 0;
             hartid++;
         } else {
@@ -397,7 +397,7 @@ static void parse_hart_config(SiFivePLICState *plic)
         }
     }
     if (modes) {
-        addrid += __builtin_popcount(modes);
+        addrid += ctpop8(modes);
     }
     hartid++;
 
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (16 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:40   ` Philippe Mathieu-Daudé
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 19/30] RISC-V: Allow interrupt controllers to claim interrupts Michael Clark
                   ` (11 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/virt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ad03113e0f72..321fa6e8122a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -385,6 +385,8 @@ static void riscv_virt_board_init(MachineState *machine)
     serial_mm_init(system_memory, memmap[VIRT_UART0].base,
         0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
         serial_hd(0), DEVICE_LITTLE_ENDIAN);
+
+    g_free(plic_hart_config);
 }
 
 static void riscv_virt_board_machine_init(MachineClass *mc)
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 19/30] RISC-V: Allow interrupt controllers to claim interrupts
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (17 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext Michael Clark
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

We can't allow the supervisor to control SEIP as this would allow the
supervisor to clear a pending external interrupt which will result in
lost a interrupt in the case a PLIC is attached. The SEIP bit must be
hardware controlled when a PLIC is attached.

This logic was previously hard-coded so SEIP was always masked even
if no PLIC was attached. This patch adds riscv_cpu_claim_interrupts
so that the PLIC can register control of SEIP. In the case of models
without a PLIC (spike), the SEIP bit remains software controlled.

This interface allows for hardware control of supervisor timer and
software interrupts by other interrupt controller models.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_plic.c    | 13 +++++++++++++
 target/riscv/cpu.h        |  2 ++
 target/riscv/cpu_helper.c | 11 +++++++++++
 target/riscv/csr.c        | 12 ++++--------
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index dc6f4924e282..28e28d932f7c 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -23,6 +23,7 @@
 #include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "target/riscv/cpu.h"
+#include "sysemu/sysemu.h"
 #include "hw/riscv/sifive_plic.h"
 
 #define RISCV_DEBUG_PLIC 0
@@ -447,6 +448,18 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
     for (i = 0; i <= plic->num_sources; i++) {
         plic->irqs[i] = qemu_allocate_irq(sifive_plic_irq_request, plic, i);
     }
+
+    /* We can't allow the supervisor to control SEIP as this would allow the
+     * supervisor to clear a pending external interrupt which will result in
+     * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
+     * hardware controlled when a PLIC is attached. */
+    for (i = 0; i < smp_cpus; i++) {
+        RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i));
+        if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
+            error_report("sifive_plic_realize: SEIP already claimed");
+            exit(1);
+        }
+    }
 }
 
 static void sifive_plic_class_init(ObjectClass *klass, void *data)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d6bb3136db18..ae0e3f6a544d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -138,6 +138,7 @@ struct CPURISCVState {
      * mip is 32-bits to allow atomic_read on 32-bit hosts.
      */
     uint32_t mip;
+    uint32_t miclaim;
 
     target_ulong mie;
     target_ulong mideleg;
@@ -262,6 +263,7 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #define cpu_mmu_index riscv_cpu_mmu_index
 
 #ifndef CONFIG_USER_ONLY
+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 */
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b4bbf7a9fa0a..7c9f6c46c75a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -72,6 +72,17 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 
 #if !defined(CONFIG_USER_ONLY)
 
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
+{
+    CPURISCVState *env = &cpu->env;
+    if (env->miclaim & interrupts) {
+        return -1;
+    } else {
+        env->miclaim |= interrupts;
+        return 0;
+    }
+}
+
 /* iothread_mutex must be held */
 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
 {
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 45e33d876034..9bbe81a110a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -502,15 +502,11 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
                    target_ulong new_value, target_ulong write_mask)
 {
     RISCVCPU *cpu = riscv_env_get_cpu(env);
-    target_ulong mask = write_mask & delegable_ints;
-    uint32_t old_mip;
 
-    /* We can't allow the supervisor to control SEIP as this would allow the
-     * supervisor to clear a pending external interrupt which will result in
-     * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
-     * hardware controlled when a PLIC is attached. This should be an option
-     * for CPUs with software-delegated Supervisor External Interrupts. */
-    mask &= ~MIP_SEIP;
+    /* Allow software control of delegable interrupts not claimed by hardware */
+    target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
+
+    uint32_t old_mip;
 
     if (mask) {
         qemu_mutex_lock_iothread();
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (18 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 19/30] RISC-V: Allow interrupt controllers to claim interrupts Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:42   ` Philippe Mathieu-Daudé
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 21/30] RISC-V: Add misa.MAFD checks to translate Michael Clark
                   ` (9 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis, Emilio G . Cota

gen methods should access state from DisasContext. Add misa
field to the DisasContext struct and remove CPURISCVState
argument from all gen methods.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Emilio G. Cota <cota@braap.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/translate.c | 78 ++++++++++++++++++++++++++----------------------
 1 file changed, 42 insertions(+), 36 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index a980611eb611..fd21b133a5a4 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -45,6 +45,7 @@ typedef struct DisasContext {
     target_ulong pc_succ_insn;
     uint32_t opcode;
     uint32_t mstatus_fs;
+    uint32_t misa;
     uint32_t mem_idx;
     /* Remember the rounding mode encoded in the previous fp instruction,
        which we have already installed into env->fp_status.  Or -1 for
@@ -74,6 +75,11 @@ static const int tcg_memop_lookup[8] = {
 #define CASE_OP_32_64(X) case X
 #endif
 
+static inline bool has_ext(DisasContext *ctx, uint32_t ext)
+{
+    return ctx->misa & ext;
+}
+
 static void generate_exception(DisasContext *ctx, int excp)
 {
     tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -505,14 +511,13 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd,
     tcg_temp_free(source1);
 }
 
-static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
-                    target_ulong imm)
+static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
 {
     target_ulong next_pc;
 
     /* check misaligned: */
     next_pc = ctx->base.pc_next + imm;
-    if (!riscv_has_ext(env, RVC)) {
+    if (!has_ext(ctx, RVC)) {
         if ((next_pc & 0x3) != 0) {
             gen_exception_inst_addr_mis(ctx);
             return;
@@ -526,8 +531,8 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
     ctx->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
-                     int rd, int rs1, target_long imm)
+static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+                     target_long imm)
 {
     /* no chaining with JALR */
     TCGLabel *misaligned = NULL;
@@ -539,7 +544,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
         tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
         tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
 
-        if (!riscv_has_ext(env, RVC)) {
+        if (!has_ext(ctx, RVC)) {
             misaligned = gen_new_label();
             tcg_gen_andi_tl(t0, cpu_pc, 0x2);
             tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
@@ -564,8 +569,8 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
     tcg_temp_free(t0);
 }
 
-static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
-                       int rs1, int rs2, target_long bimm)
+static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
+                       target_long bimm)
 {
     TCGLabel *l = gen_new_label();
     TCGv source1, source2;
@@ -602,7 +607,7 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
 
     gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
     gen_set_label(l); /* branch taken */
-    if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
+    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
         /* misaligned */
         gen_exception_inst_addr_mis(ctx);
     } else {
@@ -1311,8 +1316,8 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
     }
 }
 
-static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
-                      int rd, int rs1, int csr)
+static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+                       int csr)
 {
     TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
     source1 = tcg_temp_new();
@@ -1354,7 +1359,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
             gen_exception_illegal(ctx);
             break;
         case 0x102: /* SRET */
-            if (riscv_has_ext(env, RVS)) {
+            if (has_ext(ctx, RVS)) {
                 gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
                 tcg_gen_exit_tb(0); /* no chaining */
                 ctx->base.is_jmp = DISAS_NORETURN;
@@ -1495,7 +1500,7 @@ static void decode_RV32_64C0(DisasContext *ctx)
     }
 }
 
-static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C1(DisasContext *ctx)
 {
     uint8_t funct3 = extract32(ctx->opcode, 13, 3);
     uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
@@ -1515,7 +1520,7 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
                       GET_C_IMM(ctx->opcode));
 #else
         /* C.JAL(RV32) -> jal x1, offset[11:1] */
-        gen_jal(env, ctx, 1, GET_C_J_IMM(ctx->opcode));
+        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
 #endif
         break;
     case 2:
@@ -1594,22 +1599,22 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
         break;
     case 5:
         /* C.J -> jal x0, offset[11:1]*/
-        gen_jal(env, ctx, 0, GET_C_J_IMM(ctx->opcode));
+        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
         break;
     case 6:
         /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
         rs1s = GET_C_RS1S(ctx->opcode);
-        gen_branch(env, ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
+        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
         break;
     case 7:
         /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
         rs1s = GET_C_RS1S(ctx->opcode);
-        gen_branch(env, ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
+        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
         break;
     }
 }
 
-static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C2(DisasContext *ctx)
 {
     uint8_t rd, rs2;
     uint8_t funct3 = extract32(ctx->opcode, 13, 3);
@@ -1643,7 +1648,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
         if (extract32(ctx->opcode, 12, 1) == 0) {
             if (rs2 == 0) {
                 /* C.JR -> jalr x0, rs1, 0*/
-                gen_jalr(env, ctx, OPC_RISC_JALR, 0, rd, 0);
+                gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0);
             } else {
                 /* C.MV -> add rd, x0, rs2 */
                 gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
@@ -1651,11 +1656,11 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
         } else {
             if (rd == 0) {
                 /* C.EBREAK -> ebreak*/
-                gen_system(env, ctx, OPC_RISC_ECALL, 0, 0, 0x1);
+                gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
             } else {
                 if (rs2 == 0) {
                     /* C.JALR -> jalr x1, rs1, 0*/
-                    gen_jalr(env, ctx, OPC_RISC_JALR, 1, rd, 0);
+                    gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0);
                 } else {
                     /* C.ADD -> add rd, rd, rs2 */
                     gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
@@ -1687,7 +1692,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
     }
 }
 
-static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C(DisasContext *ctx)
 {
     uint8_t op = extract32(ctx->opcode, 0, 2);
 
@@ -1696,15 +1701,15 @@ static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
         decode_RV32_64C0(ctx);
         break;
     case 1:
-        decode_RV32_64C1(env, ctx);
+        decode_RV32_64C1(ctx);
         break;
     case 2:
-        decode_RV32_64C2(env, ctx);
+        decode_RV32_64C2(ctx);
         break;
     }
 }
 
-static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64G(DisasContext *ctx)
 {
     int rs1;
     int rs2;
@@ -1739,13 +1744,13 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
         break;
     case OPC_RISC_JAL:
         imm = GET_JAL_IMM(ctx->opcode);
-        gen_jal(env, ctx, rd, imm);
+        gen_jal(ctx, rd, imm);
         break;
     case OPC_RISC_JALR:
-        gen_jalr(env, ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
+        gen_jalr(ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
         break;
     case OPC_RISC_BRANCH:
-        gen_branch(env, ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
+        gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
                    GET_B_IMM(ctx->opcode));
         break;
     case OPC_RISC_LOAD:
@@ -1818,7 +1823,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
 #endif
         break;
     case OPC_RISC_SYSTEM:
-        gen_system(env, ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
+        gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
                    (ctx->opcode & 0xFFF00000) >> 20);
         break;
     default:
@@ -1827,29 +1832,31 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
     }
 }
 
-static void decode_opc(CPURISCVState *env, DisasContext *ctx)
+static void decode_opc(DisasContext *ctx)
 {
     /* check for compressed insn */
     if (extract32(ctx->opcode, 0, 2) != 3) {
-        if (!riscv_has_ext(env, RVC)) {
+        if (!has_ext(ctx, RVC)) {
             gen_exception_illegal(ctx);
         } else {
             ctx->pc_succ_insn = ctx->base.pc_next + 2;
-            decode_RV32_64C(env, ctx);
+            decode_RV32_64C(ctx);
         }
     } else {
         ctx->pc_succ_insn = ctx->base.pc_next + 4;
-        decode_RV32_64G(env, ctx);
+        decode_RV32_64G(ctx);
     }
 }
 
-static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
+static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    CPURISCVState *env = cpu->env_ptr;
 
     ctx->pc_succ_insn = ctx->base.pc_first;
     ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
     ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
+    ctx->misa = env->misa;
     ctx->frm = -1;  /* unknown rounding mode */
 }
 
@@ -1880,14 +1887,13 @@ static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
     return true;
 }
 
-
 static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     CPURISCVState *env = cpu->env_ptr;
 
     ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
-    decode_opc(env, ctx);
+    decode_opc(ctx);
     ctx->base.pc_next = ctx->pc_succ_insn;
 
     if (ctx->base.is_jmp == DISAS_NEXT) {
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 21/30] RISC-V: Add misa.MAFD checks to translate
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (19 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support Michael Clark
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis, Emilio G . Cota

Add misa checks for M, A, F and D extensions and if they are
not present generate illegal instructions. This improves
emulation accurary for harts with a limited set of extensions.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Emilio G. Cota <cota@braap.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/translate.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 158 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index fd21b133a5a4..e488101ff56d 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -290,24 +290,42 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         tcg_gen_and_tl(source1, source1, source2);
         break;
     CASE_OP_32_64(OPC_RISC_MUL):
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_mul_tl(source1, source1, source2);
         break;
     case OPC_RISC_MULH:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_muls2_tl(source2, source1, source1, source2);
         break;
     case OPC_RISC_MULHSU:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         gen_mulhsu(source1, source1, source2);
         break;
     case OPC_RISC_MULHU:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_mulu2_tl(source2, source1, source1, source2);
         break;
 #if defined(TARGET_RISCV64)
     case OPC_RISC_DIVW:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_ext32s_tl(source1, source1);
         tcg_gen_ext32s_tl(source2, source2);
         /* fall through to DIV */
 #endif
     case OPC_RISC_DIV:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         /* Handle by altering args to tcg_gen_div to produce req'd results:
          * For overflow: want source1 in source1 and 1 in source2
          * For div by zero: want -1 in source1 and 1 in source2 -> -1 result */
@@ -339,11 +357,17 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         break;
 #if defined(TARGET_RISCV64)
     case OPC_RISC_DIVUW:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_ext32u_tl(source1, source1);
         tcg_gen_ext32u_tl(source2, source2);
         /* fall through to DIVU */
 #endif
     case OPC_RISC_DIVU:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         cond1 = tcg_temp_new();
         zeroreg = tcg_const_tl(0);
         resultopt1 = tcg_temp_new();
@@ -363,11 +387,17 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         break;
 #if defined(TARGET_RISCV64)
     case OPC_RISC_REMW:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_ext32s_tl(source1, source1);
         tcg_gen_ext32s_tl(source2, source2);
         /* fall through to REM */
 #endif
     case OPC_RISC_REM:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         cond1 = tcg_temp_new();
         cond2 = tcg_temp_new();
         zeroreg = tcg_const_tl(0);
@@ -395,11 +425,17 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         break;
 #if defined(TARGET_RISCV64)
     case OPC_RISC_REMUW:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         tcg_gen_ext32u_tl(source1, source1);
         tcg_gen_ext32u_tl(source2, source2);
         /* fall through to REMU */
 #endif
     case OPC_RISC_REMU:
+        if (!has_ext(ctx, RVM)) {
+            goto do_illegal;
+        }
         cond1 = tcg_temp_new();
         zeroreg = tcg_const_tl(0);
         resultopt1 = tcg_temp_new();
@@ -417,6 +453,7 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         tcg_temp_free(zeroreg);
         tcg_temp_free(resultopt1);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         return;
@@ -697,13 +734,20 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
 
     switch (opc) {
     case OPC_RISC_FLW:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL);
         /* RISC-V requires NaN-boxing of narrower width floating point values */
         tcg_gen_ori_i64(cpu_fpr[rd], cpu_fpr[rd], 0xffffffff00000000ULL);
         break;
     case OPC_RISC_FLD:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -729,11 +773,18 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
 
     switch (opc) {
     case OPC_RISC_FSW:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL);
         break;
     case OPC_RISC_FSD:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -897,15 +948,22 @@ static void gen_fp_fmadd(DisasContext *ctx, uint32_t opc, int rd,
 {
     switch (opc) {
     case OPC_RISC_FMADD_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                            cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
     case OPC_RISC_FMADD_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                            cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -917,15 +975,22 @@ static void gen_fp_fmsub(DisasContext *ctx, uint32_t opc, int rd,
 {
     switch (opc) {
     case OPC_RISC_FMSUB_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                            cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
     case OPC_RISC_FMSUB_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                            cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -937,15 +1002,22 @@ static void gen_fp_fnmsub(DisasContext *ctx, uint32_t opc, int rd,
 {
     switch (opc) {
     case OPC_RISC_FNMSUB_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fnmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                             cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
     case OPC_RISC_FNMSUB_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fnmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                             cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -957,15 +1029,22 @@ static void gen_fp_fnmadd(DisasContext *ctx, uint32_t opc, int rd,
 {
     switch (opc) {
     case OPC_RISC_FNMADD_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fnmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                             cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
     case OPC_RISC_FNMADD_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fnmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
                             cpu_fpr[rs2], cpu_fpr[rs3]);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
@@ -984,30 +1063,51 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     switch (opc) {
     case OPC_RISC_FADD_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FSUB_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FMUL_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmul_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FDIV_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fdiv_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FSQRT_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fsqrt_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]);
         break;
     case OPC_RISC_FSGNJ_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         gen_fsgnj(ctx, rd, rs1, rs2, rm, INT32_MIN);
         break;
 
     case OPC_RISC_FMIN_S:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         /* also handles: OPC_RISC_FMAX_S */
         switch (rm) {
         case 0x0:
@@ -1023,6 +1123,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FEQ_S:
         /* also handles: OPC_RISC_FLT_S, OPC_RISC_FLE_S */
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         switch (rm) {
         case 0x0:
@@ -1044,6 +1147,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FCVT_W_S:
         /* also OPC_RISC_FCVT_WU_S, OPC_RISC_FCVT_L_S, OPC_RISC_FCVT_LU_S */
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         switch (rs2) {
         case 0: /* FCVT_W_S */
@@ -1074,6 +1180,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FCVT_S_W:
         /* also OPC_RISC_FCVT_S_WU, OPC_RISC_FCVT_S_L, OPC_RISC_FCVT_S_LU */
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         gen_get_gpr(t0, rs1);
         switch (rs2) {
@@ -1103,6 +1212,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FMV_X_S:
         /* also OPC_RISC_FCLASS_S */
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         switch (rm) {
         case 0: /* FMV */
@@ -1124,6 +1236,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         break;
 
     case OPC_RISC_FMV_S_X:
+        if (!has_ext(ctx, RVF)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         gen_get_gpr(t0, rs1);
 #if defined(TARGET_RISCV64)
@@ -1136,22 +1251,37 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     /* double */
     case OPC_RISC_FADD_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FSUB_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FMUL_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fmul_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FDIV_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fdiv_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
         break;
     case OPC_RISC_FSQRT_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         gen_set_rm(ctx, rm);
         gen_helper_fsqrt_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]);
         break;
@@ -1161,6 +1291,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FMIN_D:
         /* also OPC_RISC_FMAX_D */
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         switch (rm) {
         case 0:
             gen_helper_fmin_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
@@ -1174,6 +1307,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         break;
 
     case OPC_RISC_FCVT_S_D:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         switch (rs2) {
         case 1:
             gen_set_rm(ctx, rm);
@@ -1185,6 +1321,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         break;
 
     case OPC_RISC_FCVT_D_S:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         switch (rs2) {
         case 0:
             gen_set_rm(ctx, rm);
@@ -1197,6 +1336,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FEQ_D:
         /* also OPC_RISC_FLT_D, OPC_RISC_FLE_D */
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         switch (rm) {
         case 0:
@@ -1218,6 +1360,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FCVT_W_D:
         /* also OPC_RISC_FCVT_WU_D, OPC_RISC_FCVT_L_D, OPC_RISC_FCVT_LU_D */
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         switch (rs2) {
         case 0:
@@ -1248,6 +1393,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 
     case OPC_RISC_FCVT_D_W:
         /* also OPC_RISC_FCVT_D_WU, OPC_RISC_FCVT_D_L, OPC_RISC_FCVT_D_LU */
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         gen_get_gpr(t0, rs1);
         switch (rs2) {
@@ -1278,6 +1426,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
 #if defined(TARGET_RISCV64)
     case OPC_RISC_FMV_X_D:
         /* also OPC_RISC_FCLASS_D */
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         switch (rm) {
         case 0: /* FMV */
             gen_set_gpr(rd, cpu_fpr[rs1]);
@@ -1295,6 +1446,9 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
         break;
 
     case OPC_RISC_FMV_D_X:
+        if (!has_ext(ctx, RVD)) {
+            goto do_illegal;
+        }
         t0 = tcg_temp_new();
         gen_get_gpr(t0, rs1);
         tcg_gen_mov_tl(cpu_fpr[rd], t0);
@@ -1786,6 +1940,9 @@ static void decode_RV32_64G(DisasContext *ctx)
                      GET_STORE_IMM(ctx->opcode));
         break;
     case OPC_RISC_ATOMIC:
+        if (!has_ext(ctx, RVA)) {
+            goto do_illegal;
+        }
         gen_atomic(ctx, MASK_OP_ATOMIC(ctx->opcode), rd, rs1, rs2);
         break;
     case OPC_RISC_FMADD:
@@ -1826,6 +1983,7 @@ static void decode_RV32_64G(DisasContext *ctx)
         gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
                    (ctx->opcode & 0xFFF00000) >> 20);
         break;
+    do_illegal:
     default:
         gen_exception_illegal(ctx);
         break;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (20 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 21/30] RISC-V: Add misa.MAFD checks to translate Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-25 18:53   ` Richard Henderson
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes Michael Clark
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

This patch adds support for writing misa. misa is validated based
on rules in the ISA specification. 'E' is mutually exclusive with
all other extensions. 'D' depends on 'F' so 'D' bit is dropped
if 'F' is not present. A conservative approach to consistency is
taken by flushing the translation cache on misa writes. misa_mask
is added to the CPU struct to store the original set of extensions.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu.c      |  2 +-
 target/riscv/cpu.h      |  4 +++-
 target/riscv/cpu_bits.h | 11 +++++++++++
 target/riscv/csr.c      | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9f47f2072c56..d59e1c0c146d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -86,7 +86,7 @@ typedef struct RISCVCPUInfo {
 
 static void set_misa(CPURISCVState *env, target_ulong misa)
 {
-    env->misa = misa;
+    env->misa_mask = env->misa = misa;
 }
 
 static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index ae0e3f6a544d..830a9d476dce 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -86,7 +86,8 @@
    so a cpu features bitfield is required, likewise for optional PMP support */
 enum {
     RISCV_FEATURE_MMU,
-    RISCV_FEATURE_PMP
+    RISCV_FEATURE_PMP,
+    RISCV_FEATURE_MISA_RW
 };
 
 #define USER_VERSION_2_02_0 0x00020200
@@ -118,6 +119,7 @@ struct CPURISCVState {
     target_ulong user_ver;
     target_ulong priv_ver;
     target_ulong misa;
+    target_ulong misa_mask;
 
     uint32_t features;
 
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 878de6233846..55b45a40ca3f 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -311,10 +311,21 @@
 #define MSTATUS32_SD        0x80000000
 #define MSTATUS64_SD        0x8000000000000000ULL
 
+#define MISA32_MXL          0xC0000000
+#define MISA64_MXL          0xC000000000000000ULL
+
+#define MXL_RV32            1
+#define MXL_RV64            2
+#define MXL_RV128           3
+
 #if defined(TARGET_RISCV32)
 #define MSTATUS_SD MSTATUS32_SD
+#define MISA_MXL MISA32_MXL
+#define MXL_VAL MXL_RV32
 #elif defined(TARGET_RISCV64)
 #define MSTATUS_SD MSTATUS64_SD
+#define MISA_MXL MISA64_MXL
+#define MXL_VAL MXL_RV64
 #endif
 
 /* sstatus CSR bits */
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9bbe81a110a5..0be973002ee2 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -341,6 +341,56 @@ static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
     return 0;
 }
 
+static int write_misa(CPURISCVState *env, int csrno, target_ulong val)
+{
+    if (!riscv_feature(env, RISCV_FEATURE_MISA_RW)) {
+        /* drop write to misa */
+        return 0;
+    }
+
+    /* 'I' or 'E' must be present */
+    if (!(val & (RVI | RVE))) {
+        /* it not, drop write to misa */
+        return 0;
+    }
+
+    /* 'E' excludes all other extensions */
+    if (val & RVE) {
+        /* when we support 'E' we can do "val = RVE;" however
+         * for now we just drop writes if 'E' is present */
+        return 0;
+    }
+
+    /* Mask extensions that are not supported by this hart */
+    val &= env->misa_mask;
+
+    /* Mask extensions that are not supported by QEMU */
+    val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+
+    /* 'D' depends on 'F', so clear 'D' if 'F' is not present */
+    if ((val & RVD) && !(val & RVF)) {
+        val &= ~RVD;
+    }
+
+    /* Suppress 'C' if next instruction is not aligned
+       TODO: this should check next_pc */
+    if ((val & RVC) && (GETPC() & ~3) != 0) {
+        val &= ~RVC;
+    }
+
+    /* misa.MXL writes are not supported by QEMU */
+    val = (env->misa & MISA_MXL) | (val & ~MISA_MXL);
+
+    /* flush translation cache */
+    if (val != env->misa) {
+        tb_flush(CPU(riscv_env_get_cpu(env)));
+    }
+
+    env->misa = val;
+
+    return 0;
+}
+
 static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val)
 {
     *val = env->medeleg;
@@ -821,7 +871,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 
     /* Machine Trap Setup */
     [CSR_MSTATUS] =             { any,  read_mstatus,     write_mstatus     },
-    [CSR_MISA] =                { any,  read_misa                           },
+    [CSR_MISA] =                { any,  read_misa,        write_misa        },
     [CSR_MIDELEG] =             { any,  read_mideleg,     write_mideleg     },
     [CSR_MEDELEG] =             { any,  read_medeleg,     write_medeleg     },
     [CSR_MIE] =                 { any,  read_mie,         write_mie         },
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (21 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-25 22:40   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads Michael Clark
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

A missing shift made updates to the low order bits
of timecmp erroneously copy the old low order bits
into the high order bits of the 64-bit timecmp
register. Add the missing shift and rename timecmp
local variables to timecmp_hi and timecmp_lo.

This bug didn't show up as the low order bits are
usually written first followed by the high order
bits meaning the high order bits contained an invalid
value between the timecmp_lo and timecmp_hi update.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Co-Authored-by: Johannes Haring <johannes.haring@gmx.net>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_clint.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 0d2fd52487e6..d4c159e93736 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/riscv/sifive_clint.c
@@ -146,15 +146,15 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
             error_report("clint: invalid timecmp hartid: %zu", hartid);
         } else if ((addr & 0x7) == 0) {
             /* timecmp_lo */
-            uint64_t timecmp = env->timecmp;
+            uint64_t timecmp_hi = env->timecmp >> 32;
             sifive_clint_write_timecmp(RISCV_CPU(cpu),
-                timecmp << 32 | (value & 0xFFFFFFFF));
+                timecmp_hi << 32 | (value & 0xFFFFFFFF));
             return;
         } else if ((addr & 0x7) == 4) {
             /* timecmp_hi */
-            uint64_t timecmp = env->timecmp;
+            uint64_t timecmp_lo = env->timecmp;
             sifive_clint_write_timecmp(RISCV_CPU(cpu),
-                value << 32 | (timecmp & 0xFFFFFFFF));
+                value << 32 | (timecmp_lo & 0xFFFFFFFF));
         } else {
             error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
         }
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (22 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-25 22:38   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 25/30] RISC-V: Enable second UART on sifive_e and sifive_u Michael Clark
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

The address calculation for the pending bitfield had
a copy paste bug. This bug went unnoticed because the Linux
PLIC driver does not read the pending bitfield, rather it
reads pending interrupt numbers from the claim register
and writes acknowledgements back to the claim register.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Reported-by: Vincent Siles <vincent.siles@ens-lyon.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_plic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 28e28d932f7c..b81d29faff99 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -215,7 +215,7 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
     } else if (addr >= plic->pending_base && /* 1 bit per source */
                addr < plic->pending_base + (plic->num_sources >> 3))
     {
-        uint32_t word = (addr - plic->priority_base) >> 2;
+        uint32_t word = (addr - plic->pending_base) >> 2;
         if (RISCV_DEBUG_PLIC) {
             qemu_log("plic: read pending: word=%d value=%d\n",
                 word, plic->pending[word]);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 25/30] RISC-V: Enable second UART on sifive_e and sifive_u
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (23 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints Michael Clark
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

Previously the second UARTs on the sifive_e and sifive_u machines
where disabled due to check-qtest-riscv32 and check-qtest-riscv64
failures. Recent changes in the QEMU core serial code have
resolved these failures so the second UARTs can be instantiated.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/sifive_e.c | 4 ++--
 hw/riscv/sifive_u.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index e4ecb7aa4bb6..159209199537 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -155,8 +155,8 @@ static void riscv_sifive_e_init(MachineState *machine)
         memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size);
     sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm0",
         memmap[SIFIVE_E_PWM0].base, memmap[SIFIVE_E_PWM0].size);
-    /* sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base,
-        serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART1_IRQ]); */
+    sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base,
+        serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART1_IRQ]);
     sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi1",
         memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size);
     sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm1",
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index c05dcbba955e..326b0f434cff 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -299,8 +299,8 @@ static void riscv_sifive_u_init(MachineState *machine)
         memmap[SIFIVE_U_PLIC].size);
     sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
         serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
-    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
-        serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */
+    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
+        serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]);
     sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
         memmap[SIFIVE_U_CLINT].size, smp_cpus,
         SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (24 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 25/30] RISC-V: Enable second UART on sifive_e and sifive_u Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-24 22:45   ` Alistair Francis
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines Michael Clark
                   ` (3 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis

Remove machine generated constraints that are not
referenced by the pseudo-instruction constraints.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 disas/riscv.c | 138 ----------------------------------------------------------
 1 file changed, 138 deletions(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index 7fd1019623ee..27546dd7902c 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -87,33 +87,10 @@ typedef enum {
 
 typedef enum {
     rvc_end,
-    rvc_simm_6,
-    rvc_imm_6,
-    rvc_imm_7,
-    rvc_imm_8,
-    rvc_imm_9,
-    rvc_imm_10,
-    rvc_imm_12,
-    rvc_imm_18,
-    rvc_imm_nz,
-    rvc_imm_x2,
-    rvc_imm_x4,
-    rvc_imm_x8,
-    rvc_imm_x16,
-    rvc_rd_b3,
-    rvc_rs1_b3,
-    rvc_rs2_b3,
-    rvc_rd_eq_rs1,
     rvc_rd_eq_ra,
-    rvc_rd_eq_sp,
     rvc_rd_eq_x0,
-    rvc_rs1_eq_sp,
     rvc_rs1_eq_x0,
     rvc_rs2_eq_x0,
-    rvc_rd_ne_x0_x2,
-    rvc_rd_ne_x0,
-    rvc_rs1_ne_x0,
-    rvc_rs2_ne_x0,
     rvc_rs2_eq_rs1,
     rvc_rs1_eq_ra,
     rvc_imm_eq_zero,
@@ -2522,111 +2499,16 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
     uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
     while (*c != rvc_end) {
         switch (*c) {
-        case rvc_simm_6:
-            if (!(imm >= -32 && imm < 32)) {
-                return false;
-            }
-            break;
-        case rvc_imm_6:
-            if (!(imm <= 63)) {
-                return false;
-            }
-            break;
-        case rvc_imm_7:
-            if (!(imm <= 127)) {
-                return false;
-            }
-            break;
-        case rvc_imm_8:
-            if (!(imm <= 255)) {
-                return false;
-            }
-            break;
-        case rvc_imm_9:
-            if (!(imm <= 511)) {
-                return false;
-            }
-            break;
-        case rvc_imm_10:
-            if (!(imm <= 1023)) {
-                return false;
-            }
-            break;
-        case rvc_imm_12:
-            if (!(imm <= 4095)) {
-                return false;
-            }
-            break;
-        case rvc_imm_18:
-            if (!(imm <= 262143)) {
-                return false;
-            }
-            break;
-        case rvc_imm_nz:
-            if (!(imm != 0)) {
-                return false;
-            }
-            break;
-        case rvc_imm_x2:
-            if (!((imm & 0b1) == 0)) {
-                return false;
-            }
-            break;
-        case rvc_imm_x4:
-            if (!((imm & 0b11) == 0)) {
-                return false;
-            }
-            break;
-        case rvc_imm_x8:
-            if (!((imm & 0b111) == 0)) {
-                return false;
-            }
-            break;
-        case rvc_imm_x16:
-            if (!((imm & 0b1111) == 0)) {
-                return false;
-            }
-            break;
-        case rvc_rd_b3:
-            if (!(rd  >= 8 && rd  <= 15)) {
-                return false;
-            }
-            break;
-        case rvc_rs1_b3:
-            if (!(rs1 >= 8 && rs1 <= 15)) {
-                return false;
-            }
-            break;
-        case rvc_rs2_b3:
-            if (!(rs2 >= 8 && rs2 <= 15)) {
-                return false;
-            }
-            break;
-        case rvc_rd_eq_rs1:
-            if (!(rd == rs1)) {
-                return false;
-            }
-            break;
         case rvc_rd_eq_ra:
             if (!(rd == 1)) {
                 return false;
             }
             break;
-        case rvc_rd_eq_sp:
-            if (!(rd == 2)) {
-                return false;
-            }
-            break;
         case rvc_rd_eq_x0:
             if (!(rd == 0)) {
                 return false;
             }
             break;
-        case rvc_rs1_eq_sp:
-            if (!(rs1 == 2)) {
-                return false;
-            }
-            break;
         case rvc_rs1_eq_x0:
             if (!(rs1 == 0)) {
                 return false;
@@ -2637,26 +2519,6 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
                 return false;
             }
             break;
-        case rvc_rd_ne_x0_x2:
-            if (!(rd != 0 && rd != 2)) {
-                return false;
-            }
-            break;
-        case rvc_rd_ne_x0:
-            if (!(rd != 0)) {
-                return false;
-            }
-            break;
-        case rvc_rs1_ne_x0:
-            if (!(rs1 != 0)) {
-                return false;
-            }
-            break;
-        case rvc_rs2_ne_x0:
-            if (!(rs2 != 0)) {
-                return false;
-            }
-            break;
         case rvc_rs2_eq_rs1:
             if (!(rs2 == rs1)) {
                 return false;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (25 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  6:44   ` Laurent Vivier
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 28/30] RISC-V: linux-user support for RVE ABI Michael Clark
                   ` (2 subsequent siblings)
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Michael Tokarev, Laurent Vivier,
	Richard Henderson, Alistair Francis

Refer to the RISC-V PSABI specification for details:

- https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md

Cc: Michael Tokarev <mjt@tls.msk.ru>
Cc: Laurent Vivier <laurent@vivier.eu>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 include/elf.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index 934dbbd6b3ae..d363ba85a688 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1285,6 +1285,14 @@ typedef struct {
 #define R_IA64_DTPREL64LSB	0xb7	/* @dtprel(sym + add), data8 LSB */
 #define R_IA64_LTOFF_DTPREL22	0xba	/* @ltoff(@dtprel(s+a)), imm22 */
 
+/* RISC-V specific definitions.  */
+#define EF_RISCV_RVC 0x0001
+#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
+#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
+#define EF_RISCV_FLOAT_ABI_QUAD (0x0006
+#define EF_RISCV_RVE 0x0008
+#define EF_RISCV_TSO 0x0010
+
 typedef struct elf32_rel {
   Elf32_Addr	r_offset;
   Elf32_Word	r_info;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 28/30] RISC-V: linux-user support for RVE ABI
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (26 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree Michael Clark
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload Michael Clark
  29 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Kito Cheng, Palmer Dabbelt, Sagar Karandikar,
	Bastian Koppelmann, Alistair Francis, Michael Clark

From: Kito Cheng <kito.cheng@gmail.com>

This change checks elf_flags for EF_RISCV_RVE and if
present uses the RVE linux syscall ABI which uses t0
for the syscall number instead of a7.

Warn and exit if a non-RVE ABI binary is run on a
cpu with the RVE extension as it is incompatible.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Co-authored-by: Kito Cheng <kito.cheng@gmail.com>
Co-authored-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 linux-user/riscv/cpu_loop.c | 14 +++++++++++++-
 target/riscv/cpu.h          |  4 ++++
 target/riscv/cpu_user.h     |  3 ++-
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index f137d39d7e82..5f6a941c6c19 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -20,6 +20,7 @@
 #include "qemu/osdep.h"
 #include "qemu.h"
 #include "cpu_loop-common.h"
+#include "elf.h"
 
 void cpu_loop(CPURISCVState *env)
 {
@@ -53,7 +54,8 @@ void cpu_loop(CPURISCVState *env)
                 ret = 0;
             } else {
                 ret = do_syscall(env,
-                                 env->gpr[xA7],
+                                 env->gpr[(env->elf_flags & EF_RISCV_RVE)
+                                    ? xT0 : xA7],
                                  env->gpr[xA0],
                                  env->gpr[xA1],
                                  env->gpr[xA2],
@@ -113,6 +115,16 @@ void cpu_loop(CPURISCVState *env)
 
 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
 {
+    CPUState *cpu = ENV_GET_CPU(env);
+    TaskState *ts = cpu->opaque;
+    struct image_info *info = ts->info;
+
     env->pc = regs->sepc;
     env->gpr[xSP] = regs->sp;
+    env->elf_flags = info->elf_flags;
+
+    if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
+        fprintf(stderr, "Incompatible ELF: RVE cpu requires RVE ABI binary\n");
+        exit(EXIT_FAILURE);
+    }
 }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 830a9d476dce..0823461ae9f2 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -123,6 +123,10 @@ struct CPURISCVState {
 
     uint32_t features;
 
+#ifdef CONFIG_USER_ONLY
+    uint32_t elf_flags;
+#endif
+
 #ifndef CONFIG_USER_ONLY
     target_ulong priv;
     target_ulong resetvec;
diff --git a/target/riscv/cpu_user.h b/target/riscv/cpu_user.h
index c2199610abff..52d380aa98c2 100644
--- a/target/riscv/cpu_user.h
+++ b/target/riscv/cpu_user.h
@@ -10,4 +10,5 @@
 #define xA4 14
 #define xA5 15
 #define xA6 16
-#define xA7 17  /* syscall number goes here */
+#define xA7 17  /* syscall number for RVI ABI */
+#define xT0 5   /* syscall number for RVE ABI */
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (27 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 28/30] RISC-V: linux-user support for RVE ABI Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:45   ` Philippe Mathieu-Daudé
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload Michael Clark
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches, Michael Clark

---
 hw/riscv/sifive_u.c | 4 +++-
 hw/riscv/spike.c    | 6 ++++--
 hw/riscv/virt.c     | 4 +++-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 326b0f434cff..02721d43c474 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -206,7 +206,9 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
 
     qemu_fdt_add_subnode(fdt, "/chosen");
     qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
-    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    if (cmdline) {
+        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    }
     g_free(nodename);
 }
 
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index f94e2b670799..5dd7d28aed4e 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -156,8 +156,10 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
     g_free(cells);
     g_free(nodename);
 
-    qemu_fdt_add_subnode(fdt, "/chosen");
-    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    if (cmdline) {
+        qemu_fdt_add_subnode(fdt, "/chosen");
+        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    }
  }
 
 static void spike_v1_10_0_board_init(MachineState *machine)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 321fa6e8122a..c889aa3cd269 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -253,7 +253,9 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
 
     qemu_fdt_add_subnode(fdt, "/chosen");
     qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
-    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    if (cmdline) {
+        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
+    }
     g_free(nodename);
 
     return fdt;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload
  2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
                   ` (28 preceding siblings ...)
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree Michael Clark
@ 2018-05-23  0:15 ` Michael Clark
  2018-05-23 12:49   ` Philippe Mathieu-Daudé
  29 siblings, 1 reply; 61+ messages in thread
From: Michael Clark @ 2018-05-23  0:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches, Michael Clark, Palmer Dabbelt, Alistair Francis

Support for separate firmware and kernel payload is added
by updating BBL to read optional preloaded kernel address
attributes from device-tree using a similar mechanism to
that used to pass init ramdisk addresses to linux kernel.

    chosen {
        riscv,kernel-start = <0x00000000 0x80200000>;
        riscv,kernel-end = <0x00000000 0x80590634>;
    };

These attributes are added by QEMU and read by BBL when combining
-bios <firmware-image> and -kernel <kernel-image> options. e.g.

$ qemu-system-riscv64 -machine virt -bios bbl -kernel vmlinux

With this change, bbl can be compiled without --with-payload
and the dummy payload alignment is altered to make the memory
footprint of the firmware-only bbl smaller. The dummy payload
message is updated to indicate the alternative load method.

This load method could also be supported by a first stage boot
loader that reads seperate firmware and kernel from SPI flash.
The main advantage of this new mechanism is that it eases kernel
development by avoiding the riscv-pk packaging step after kernel
builds, makes building per repository artefacts for CI simpler,
and mimics bootloaders on other platforms that can load a kernel
image file directly. Ultimately BBL should use an SPI driver to
load the kernel image however this mechanism supports use cases
such such as QEMU's -bios, -kernel and -initrd options following
examples from other platforms that pass kernel entry to firmware
via device-tree.

The board is also changed to use the firmware address from the
loaded firmware or combined firmware+kernel. This is normally
equal to the DRAM base address of 0x8000_0000, however now it
is possible to boot firmware at different load addresses because
the reset code jumps to the actual firmware entry address.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 hw/riscv/Makefile.objs  |   1 +
 hw/riscv/boot.c         | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/riscv/virt.c         |  67 +++----------------
 include/hw/riscv/boot.h |  30 +++++++++
 4 files changed, 213 insertions(+), 57 deletions(-)
 create mode 100644 hw/riscv/boot.c
 create mode 100644 include/hw/riscv/boot.h

diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
index 1dde01d39dcc..d36b004ab0f9 100644
--- a/hw/riscv/Makefile.objs
+++ b/hw/riscv/Makefile.objs
@@ -1,3 +1,4 @@
+obj-y += boot.o
 obj-y += riscv_htif.o
 obj-y += riscv_hart.o
 obj-y += sifive_e.o
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
new file mode 100644
index 000000000000..cf4e5d594638
--- /dev/null
+++ b/hw/riscv/boot.c
@@ -0,0 +1,172 @@
+/*
+ * QEMU RISCV firmware and kernel loader
+ *
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "sysemu/device_tree.h"
+#include "elf.h"
+#include "hw/riscv/boot.h"
+
+#define RISCV_BOOT_DEBUG 0
+
+#define boot_debug(fs, ...) \
+    if (RISCV_BOOT_DEBUG) { \
+        fprintf(stderr, "boot: %s: "fs, __func__, ##__VA_ARGS__); \
+    }
+
+static uint64_t kernel_offset;
+
+static uint64_t kernel_translate(void *opaque, uint64_t addr)
+{
+    /* mask kernel virtual address and offset by load address */
+    if (kernel_offset) {
+        return (addr & 0x7fffffff) + kernel_offset;
+    } else {
+        return addr;
+    }
+}
+
+hwaddr riscv_load_firmware(const char *filename)
+{
+    uint64_t firmware_entry, firmware_start, firmware_end;
+
+    if (load_elf(filename, NULL, NULL,
+                 &firmware_entry, &firmware_start, &firmware_end,
+                 0, EM_RISCV, 1, 0) < 0) {
+        error_report("riscv_boot: could not load firmware '%s'", filename);
+        exit(1);
+    }
+
+    /* align kernel load address to the megapage after the firmware */
+#if defined(TARGET_RISCV32)
+    kernel_offset = (firmware_end + 0x3fffff) & ~0x3fffff;
+#else
+    kernel_offset = (firmware_end + 0x1fffff) & ~0x1fffff;
+#endif
+
+    boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
+               "end=0x" TARGET_FMT_plx " kernel_offset=0x" TARGET_FMT_plx "\n",
+               firmware_entry, firmware_start, firmware_end, kernel_offset);
+
+    return firmware_entry;
+}
+
+hwaddr riscv_load_kernel(const char *filename, void *fdt)
+{
+    uint64_t kernel_entry, kernel_start, kernel_end;
+
+    if (load_elf(filename, kernel_translate, NULL,
+                 &kernel_entry, &kernel_start, &kernel_end,
+                 0, EM_RISCV, 1, 0) < 0) {
+        error_report("riscv_boot: could not load kernel '%s'", filename);
+        exit(1);
+    }
+
+    boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
+               "end=0x" TARGET_FMT_plx "\n", kernel_entry, kernel_start,
+               kernel_end);
+
+    /*
+     * pass kernel load address via device-tree to firmware
+     *
+     * BBL reads the kernel address from device-tree
+     */
+    if (fdt) {
+        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-end",
+                               kernel_end >> 32, kernel_end);
+        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-start",
+                               kernel_start >> 32, kernel_start);
+    }
+
+    return kernel_entry;
+}
+
+void riscv_load_initrd(const char *filename, uint64_t mem_size,
+                       hwaddr firmware_entry, void *fdt)
+{
+    uint64_t start, size;
+
+    /* We want to put the initrd far enough into RAM that when the
+     * kernel is uncompressed it will not clobber the initrd. However
+     * on boards without much RAM we must ensure that we still leave
+     * enough room for a decent sized initrd, and on boards with large
+     * amounts of RAM we must avoid the initrd being so far up in RAM
+     * that it is outside lowmem and inaccessible to the kernel.
+     * So for boards with less  than 256MB of RAM we put the initrd
+     * halfway into RAM, and for boards with 256MB of RAM or more we put
+     * the initrd at 128MB.
+     */
+    start = firmware_entry + MIN(mem_size / 2, 128 * 1024 * 1024);
+
+    size = load_ramdisk(filename, start, mem_size - start);
+    if (size == -1) {
+        size = load_image_targphys(filename, start, mem_size - start);
+        if (size == -1) {
+            error_report("riscv_boot: could not load ramdisk '%s'", filename);
+            exit(1);
+        }
+    }
+
+    boot_debug("start=0x" TARGET_FMT_plx " end=0x" TARGET_FMT_plx "\n",
+               start, start + size);
+
+    /*
+     * pass initrd load address via device-tree to kernel
+     *
+     * linux-kernel reads the initrd address from device-tree
+     */
+    if (fdt) {
+        qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-end",
+                               (start + size) >> 32, start + size);
+        qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-start",
+                               start >> 32, start);
+    }
+}
+
+hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt)
+{
+    hwaddr firmware_entry = 0;
+
+    /* load firmware e.g. -bios bbl */
+    if (machine->firmware) {
+        firmware_entry = riscv_load_firmware(machine->firmware);
+    }
+
+    /* load combined bbl+kernel or separate kernel */
+    if (machine->kernel_filename) {
+        if (machine->firmware) {
+            /* load separate bios and kernel e.g. -bios bbl -kernel vmlinux */
+            riscv_load_kernel(machine->kernel_filename, fdt);
+        } else {
+            /* load traditional combined bbl+kernel e.g. -kernel bbl_vmlimux */
+            firmware_entry = riscv_load_kernel(machine->kernel_filename, NULL);
+        }
+        if (machine->initrd_filename) {
+            /* load separate initrd */
+            riscv_load_initrd(machine->initrd_filename, machine->ram_size,
+                              firmware_entry, fdt);
+        }
+    }
+
+    return firmware_entry;
+}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index c889aa3cd269..984ddf0635fd 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -33,6 +33,7 @@
 #include "hw/riscv/sifive_plic.h"
 #include "hw/riscv/sifive_clint.h"
 #include "hw/riscv/sifive_test.h"
+#include "hw/riscv/boot.h"
 #include "hw/riscv/virt.h"
 #include "chardev/char.h"
 #include "sysemu/arch_init.h"
@@ -56,47 +57,6 @@ static const struct MemmapEntry {
     [VIRT_DRAM] =     { 0x80000000,        0x0 },
 };
 
-static uint64_t load_kernel(const char *kernel_filename)
-{
-    uint64_t kernel_entry, kernel_high;
-
-    if (load_elf(kernel_filename, NULL, NULL,
-                 &kernel_entry, NULL, &kernel_high,
-                 0, EM_RISCV, 1, 0) < 0) {
-        error_report("qemu: could not load kernel '%s'", kernel_filename);
-        exit(1);
-    }
-    return kernel_entry;
-}
-
-static hwaddr load_initrd(const char *filename, uint64_t mem_size,
-                          uint64_t kernel_entry, hwaddr *start)
-{
-    int size;
-
-    /* We want to put the initrd far enough into RAM that when the
-     * kernel is uncompressed it will not clobber the initrd. However
-     * on boards without much RAM we must ensure that we still leave
-     * enough room for a decent sized initrd, and on boards with large
-     * amounts of RAM we must avoid the initrd being so far up in RAM
-     * that it is outside lowmem and inaccessible to the kernel.
-     * So for boards with less  than 256MB of RAM we put the initrd
-     * halfway into RAM, and for boards with 256MB of RAM or more we put
-     * the initrd at 128MB.
-     */
-    *start = kernel_entry + MIN(mem_size / 2, 128 * 1024 * 1024);
-
-    size = load_ramdisk(filename, *start, mem_size - *start);
-    if (size == -1) {
-        size = load_image_targphys(filename, *start, mem_size - *start);
-        if (size == -1) {
-            error_report("qemu: could not load ramdisk '%s'", filename);
-            exit(1);
-        }
-    }
-    return *start + size;
-}
-
 static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
     uint64_t mem_size, const char *cmdline)
 {
@@ -273,6 +233,7 @@ static void riscv_virt_board_init(MachineState *machine)
     size_t plic_hart_config_len;
     int i;
     void *fdt;
+    hwaddr firmware_entry;
 
     /* Initialize SOC */
     object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@@ -300,20 +261,12 @@ static void riscv_virt_board_init(MachineState *machine)
     memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
                                 mask_rom);
 
-    if (machine->kernel_filename) {
-        uint64_t kernel_entry = load_kernel(machine->kernel_filename);
-
-        if (machine->initrd_filename) {
-            hwaddr start;
-            hwaddr end = load_initrd(machine->initrd_filename,
-                                     machine->ram_size, kernel_entry,
-                                     &start);
-            qemu_fdt_setprop_cell(fdt, "/chosen",
-                                  "linux,initrd-start", start);
-            qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                                  end);
-        }
-    }
+    /*
+     * combined firmware and kernel: -kernel bbl_vmlimux
+     * separate firmware and kernel: -bios bbl -kernel vmlinux
+     * firmware, kernel and ramdisk: -bios bbl -kernel vmlinux -initrd initramfs
+     */
+    firmware_entry = riscv_load_firmware_kernel_initrd(machine, fdt);
 
     /* reset vector */
     uint32_t reset_vec[8] = {
@@ -327,8 +280,8 @@ static void riscv_virt_board_init(MachineState *machine)
 #endif
         0x00028067,                  /*     jr     t0 */
         0x00000000,
-        memmap[VIRT_DRAM].base,      /* start: .dword memmap[VIRT_DRAM].base */
-        0x00000000,
+        firmware_entry,              /* .word firmware_entry */
+        firmware_entry >> 32,
                                      /* dtb: */
     };
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
new file mode 100644
index 000000000000..aa30bf1c45b2
--- /dev/null
+++ b/include/hw/riscv/boot.h
@@ -0,0 +1,30 @@
+/*
+ * QEMU RISCV firmware and kernel loader interface
+ *
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RISCV_BOOT_H
+#define HW_RISCV_BOOT_H
+
+hwaddr riscv_load_firmware(const char *filename);
+hwaddr riscv_load_kernel(const char *filename, void *fdt);
+void riscv_load_initrd(const char *filename, uint64_t mem_size,
+                       hwaddr firmware_entry, void *fdt);
+hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt);
+
+#endif
-- 
2.7.0

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

* Re: [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines Michael Clark
@ 2018-05-23  6:44   ` Laurent Vivier
  2018-05-25  7:17     ` Michael Clark
  0 siblings, 1 reply; 61+ messages in thread
From: Laurent Vivier @ 2018-05-23  6:44 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: patches, Michael Tokarev, Richard Henderson, Alistair Francis

Le 23/05/2018 à 02:15, Michael Clark a écrit :
> Refer to the RISC-V PSABI specification for details:
> 
> - https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
> 
> Cc: Michael Tokarev <mjt@tls.msk.ru>
> Cc: Laurent Vivier <laurent@vivier.eu>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> ---
>  include/elf.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/elf.h b/include/elf.h
> index 934dbbd6b3ae..d363ba85a688 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -1285,6 +1285,14 @@ typedef struct {
>  #define R_IA64_DTPREL64LSB	0xb7	/* @dtprel(sym + add), data8 LSB */
>  #define R_IA64_LTOFF_DTPREL22	0xba	/* @ltoff(@dtprel(s+a)), imm22 */
>  
> +/* RISC-V specific definitions.  */
> +#define EF_RISCV_RVC 0x0001
> +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
> +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
> +#define EF_RISCV_FLOAT_ABI_QUAD (0x0006
                                   ^
Typo here -------------------------|

Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
@ 2018-05-23 12:23   ` Philippe Mathieu-Daudé
  2018-05-25 15:20   ` Richard Henderson
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:23 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 09:14 PM, Michael Clark wrote:
> This patch makes op_helper.c contain only instruction
> operation helpers used by translate.c and moves any
> unrelated cpu helpers into cpu_helper.c. No logic is
> changed by this patch.
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  target/riscv/Makefile.objs              |  2 +-
>  target/riscv/{helper.c => cpu_helper.c} | 35 ++++++++++++++++++++++++++++++++-
>  target/riscv/op_helper.c                | 34 --------------------------------
>  3 files changed, 35 insertions(+), 36 deletions(-)
>  rename target/riscv/{helper.c => cpu_helper.c} (95%)
> 
> diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
> index abd0a7cde333..fcc5d34c1f2e 100644
> --- a/target/riscv/Makefile.objs
> +++ b/target/riscv/Makefile.objs
> @@ -1 +1 @@
> -obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o gdbstub.o pmp.o
> +obj-y += translate.o op_helper.o cpu_helper.o cpu.o fpu_helper.o gdbstub.o pmp.o
> diff --git a/target/riscv/helper.c b/target/riscv/cpu_helper.c
> similarity index 95%
> rename from target/riscv/helper.c
> rename to target/riscv/cpu_helper.c
> index 47d116e9c13f..6c886e99055a 100644
> --- a/target/riscv/helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1,5 +1,5 @@
>  /*
> - * RISC-V emulation helpers for qemu.
> + * RISC-V CPU helpers for qemu.
>   *
>   * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
>   * Copyright (c) 2017-2018 SiFive, Inc.
> @@ -72,6 +72,39 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
>  
>  #if !defined(CONFIG_USER_ONLY)
>  
> +/* iothread_mutex must be held */
> +uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
> +{
> +    CPURISCVState *env = &cpu->env;
> +    uint32_t old, new, cmp = atomic_read(&env->mip);
> +
> +    do {
> +        old = cmp;
> +        new = (old & ~mask) | (value & mask);
> +        cmp = atomic_cmpxchg(&env->mip, old, new);
> +    } while (old != cmp);
> +
> +    if (new && !old) {
> +        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> +    } else if (!new && old) {
> +        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> +    }
> +
> +    return old;
> +}
> +
> +void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> +{
> +    if (newpriv > PRV_M) {
> +        g_assert_not_reached();
> +    }
> +    if (newpriv == PRV_H) {
> +        newpriv = PRV_U;
> +    }
> +    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
> +    env->priv = newpriv;
> +}
> +
>  /* get_physical_address - get the physical address for this virtual address
>   *
>   * Do a page table walk to obtain the physical address corresponding to a
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 5a02795bf931..2b9dd9da6486 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -652,39 +652,6 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  
>  #ifndef CONFIG_USER_ONLY
>  
> -/* iothread_mutex must be held */
> -uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
> -{
> -    CPURISCVState *env = &cpu->env;
> -    uint32_t old, new, cmp = atomic_read(&env->mip);
> -
> -    do {
> -        old = cmp;
> -        new = (old & ~mask) | (value & mask);
> -        cmp = atomic_cmpxchg(&env->mip, old, new);
> -    } while (old != cmp);
> -
> -    if (new && !old) {
> -        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    } else if (!new && old) {
> -        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    }
> -
> -    return old;
> -}
> -
> -void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> -{
> -    if (newpriv > PRV_M) {
> -        g_assert_not_reached();
> -    }
> -    if (newpriv == PRV_H) {
> -        newpriv = PRV_U;
> -    }
> -    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
> -    env->priv = newpriv;
> -}
> -
>  target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  {
>      if (!(env->priv >= PRV_S)) {
> @@ -735,7 +702,6 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>      return retpc;
>  }
>  
> -
>  void helper_wfi(CPURISCVState *env)
>  {
>      CPUState *cs = CPU(riscv_env_get_cpu(env));
> 

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

* Re: [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
@ 2018-05-23 12:25   ` Philippe Mathieu-Daudé
  2018-05-29 23:40   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:25 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Richard Henderson, Alistair Francis, patches

On 05/22/2018 09:14 PM, Michael Clark wrote:
> From: Richard Henderson <richard.henderson@linaro.org>
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  target/riscv/cpu.h       |  6 +++---
>  target/riscv/translate.c | 10 +++++-----
>  2 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 3a3d91447736..242a8fcbe180 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -276,8 +276,8 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
>  target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
>  void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
>  
> -#define TB_FLAGS_MMU_MASK  3
> -#define TB_FLAGS_FP_ENABLE MSTATUS_FS
> +#define TB_FLAGS_MMU_MASK   3
> +#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
>  
>  static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>                                          target_ulong *cs_base, uint32_t *flags)
> @@ -285,7 +285,7 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      *pc = env->pc;
>      *cs_base = 0;
>  #ifdef CONFIG_USER_ONLY
> -    *flags = TB_FLAGS_FP_ENABLE;
> +    *flags = TB_FLAGS_MSTATUS_FS;
>  #else
>      *flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
>  #endif
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index ee2bbc55b051..466b9551cbd9 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -44,7 +44,7 @@ typedef struct DisasContext {
>      /* pc_succ_insn points to the instruction following base.pc_next */
>      target_ulong pc_succ_insn;
>      uint32_t opcode;
> -    uint32_t flags;
> +    uint32_t mstatus_fs;
>      uint32_t mem_idx;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
> @@ -656,7 +656,7 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
>  {
>      TCGv t0;
>  
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          gen_exception_illegal(ctx);
>          return;
>      }
> @@ -686,7 +686,7 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
>  {
>      TCGv t0;
>  
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          gen_exception_illegal(ctx);
>          return;
>      }
> @@ -945,7 +945,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>  {
>      TCGv t0 = NULL;
>  
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          goto do_illegal;
>      }
>  
> @@ -1810,8 +1810,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      DisasContext *ctx = container_of(dcbase, DisasContext, base);
>  
>      ctx->pc_succ_insn = ctx->base.pc_first;
> -    ctx->flags = ctx->base.tb->flags;
>      ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
> +    ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
>      ctx->frm = -1;  /* unknown rounding mode */
>  }
>  
> 

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

* Re: [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
@ 2018-05-23 12:26   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:26 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Matthew Suozzo, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, patches

Hi Michael,

On 05/22/2018 09:15 PM, Michael Clark wrote:
> This adds the necessary minimum to support S-mode
> virtualization for priv ISA >= v1.10
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Cc: Matthew Suozzo <msuozzo@google.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> 
> Co-authored-by: Matthew Suozzo <msuozzo@google.com>

Isn't it simply another Signed-off-by?

> Co-authored-by: Michael Clark <mjc@sifive.com>
> ---
>  target/riscv/csr.c       | 17 +++++++++++++----
>  target/riscv/op_helper.c | 25 +++++++++++++++++++++----
>  2 files changed, 34 insertions(+), 8 deletions(-)
> 
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index b4452388ff02..509215327243 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -313,7 +313,8 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>          }
>          mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
>              MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
> -            MSTATUS_MPP | MSTATUS_MXR;
> +            MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
> +            MSTATUS_TW;
>      }
>  
>      /* silenty discard mstatus.mpp writes for unsupported modes */
> @@ -654,7 +655,11 @@ 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) {
> -        *val = env->satp;
> +        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> +            return -1;
> +        } else {
> +            *val = env->satp;
> +        }
>      } else {
>          *val = env->sptbr;
>      }
> @@ -675,8 +680,12 @@ 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)))
>      {
> -        tlb_flush(CPU(riscv_env_get_cpu(env)));
> -        env->satp = val;
> +        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
> +            return -1;
> +        } else {
> +            tlb_flush(CPU(riscv_env_get_cpu(env)));
> +            env->satp = val;
> +        }
>      }
>      return 0;
>  }
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 81bd1a77ea90..77c79ba36e0b 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -82,6 +82,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>  
> +    if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
> +        get_field(env->mstatus, MSTATUS_TSR)) {
> +        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    }
> +
>      target_ulong mstatus = env->mstatus;
>      target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
>      mstatus = set_field(mstatus,
> @@ -125,16 +130,28 @@ void helper_wfi(CPURISCVState *env)
>  {
>      CPUState *cs = CPU(riscv_env_get_cpu(env));
>  
> -    cs->halted = 1;
> -    cs->exception_index = EXCP_HLT;
> -    cpu_loop_exit(cs);
> +    if (env->priv == PRV_S &&
> +        env->priv_ver >= PRIV_VERSION_1_10_0 &&
> +        get_field(env->mstatus, MSTATUS_TW)) {
> +        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    } else {
> +        cs->halted = 1;
> +        cs->exception_index = EXCP_HLT;
> +        cpu_loop_exit(cs);
> +    }
>  }
>  
>  void helper_tlb_flush(CPURISCVState *env)
>  {
>      RISCVCPU *cpu = riscv_env_get_cpu(env);
>      CPUState *cs = CPU(cpu);
> -    tlb_flush(cs);
> +    if (env->priv == PRV_S &&
> +        env->priv_ver >= PRIV_VERSION_1_10_0 &&
> +        get_field(env->mstatus, MSTATUS_TVM)) {
> +        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    } else {
> +        tlb_flush(cs);
> +    }
>  }
>  
>  #endif /* !CONFIG_USER_ONLY */
> 

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

* Re: [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging Michael Clark
@ 2018-05-23 12:33   ` Philippe Mathieu-Daudé
  2018-05-24 22:47     ` Alistair Francis
  0 siblings, 1 reply; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:33 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

Hi Michael,

On 05/22/2018 09:15 PM, Michael Clark wrote:
> Add carriage return that was erroneously removed
> when converting to qemu_log. Change hard coded
> core number to the actual hartid.

I think it makes more sens to move this patch before your 6/30 "Move
non-ops from op_helper to cpu_helper".

> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  target/riscv/cpu_helper.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index bc15e19022cc..69592c037042 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -446,11 +446,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>      if (RISCV_DEBUG_INTERRUPT) {
>          int log_cause = cs->exception_index & RISCV_EXCP_INT_MASK;
>          if (cs->exception_index & RISCV_EXCP_INT_FLAG) {
> -            qemu_log_mask(LOG_TRACE, "core   0: trap %s, epc 0x" TARGET_FMT_lx,
> -                riscv_intr_names[log_cause], env->pc);
> +            qemu_log_mask(LOG_TRACE, "core "
> +                TARGET_FMT_ld ": trap %s, epc 0x" TARGET_FMT_lx "\n",
> +                env->mhartid, riscv_intr_names[log_cause], env->pc);
>          } else {
> -            qemu_log_mask(LOG_TRACE, "core   0: intr %s, epc 0x" TARGET_FMT_lx,
> -                riscv_excp_names[log_cause], env->pc);
> +            qemu_log_mask(LOG_TRACE, "core "
> +                TARGET_FMT_ld ": intr %s, epc 0x" TARGET_FMT_lx "\n",
> +                env->mhartid, riscv_excp_names[log_cause], env->pc);
>          }
>      }
>  
> @@ -512,8 +514,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  
>          if (hasbadaddr) {
>              if (RISCV_DEBUG_INTERRUPT) {
> -                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
> -                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
> +                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
> +                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
>              }
>              env->sbadaddr = env->badaddr;
>          } else {
> @@ -537,8 +539,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  
>          if (hasbadaddr) {
>              if (RISCV_DEBUG_INTERRUPT) {
> -                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
> -                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
> +                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
> +                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
>              }
>              env->mbadaddr = env->badaddr;
>          } else {
> 

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

* Re: [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
@ 2018-05-23 12:36   ` Philippe Mathieu-Daudé
  2018-05-29 23:43   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:36 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 09:15 PM, Michael Clark wrote:
> * Add riscv prefix to raise_exception function
> * Add riscv prefix to CSR read/write functions
> * Add riscv prefix to signal handler function
> * Add riscv prefix to get fflags function
> * Remove redundant declaration of riscv_cpu_init
>   and rename cpu_riscv_init to riscv_cpu_init
> * rename riscv_set_mode to riscv_cpu_set_mode
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> ---
>  linux-user/riscv/signal.c |  4 ++--
>  target/riscv/cpu.h        | 21 ++++++++++-----------
>  target/riscv/cpu_helper.c | 10 +++++-----
>  target/riscv/csr.c        |  8 ++++----
>  target/riscv/fpu_helper.c |  6 +++---
>  target/riscv/op_helper.c  | 28 ++++++++++++++--------------
>  6 files changed, 38 insertions(+), 39 deletions(-)
> 
> diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
> index ef599e319a10..f03bc7212b49 100644
> --- a/linux-user/riscv/signal.c
> +++ b/linux-user/riscv/signal.c
> @@ -84,7 +84,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
>          __put_user(env->fpr[i], &sc->fpr[i]);
>      }
>  
> -    uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
> +    uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
>      __put_user(fcsr, &sc->fcsr);
>  }
>  
> @@ -160,7 +160,7 @@ static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
>  
>      uint32_t fcsr;
>      __get_user(fcsr, &sc->fcsr);
> -    csr_write_helper(env, fcsr, CSR_FCSR);
> +    riscv_csr_write(env, CSR_FCSR, fcsr);
>  }
>  
>  static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 1ade90d23bbc..d6bb3136db18 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -257,7 +257,7 @@ char *riscv_isa_string(RISCVCPU *cpu);
>  void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  
>  #define cpu_init(cpu_model) cpu_generic_init(TYPE_RISCV_CPU, cpu_model)
> -#define cpu_signal_handler cpu_riscv_signal_handler
> +#define cpu_signal_handler riscv_cpu_signal_handler
>  #define cpu_list riscv_cpu_list
>  #define cpu_mmu_index riscv_cpu_mmu_index
>  
> @@ -265,16 +265,15 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  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 */
>  #endif
> -void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
>  
>  void riscv_translate_init(void);
> -RISCVCPU *cpu_riscv_init(const char *cpu_model);
> -int cpu_riscv_signal_handler(int host_signum, void *pinfo, void *puc);
> -void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
> -                                          uint32_t exception, uintptr_t pc);
> +int riscv_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
> +void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
> +                                         uint32_t exception, uintptr_t pc);
>  
> -target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
> -void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>  
>  #define TB_FLAGS_MMU_MASK   3
>  #define TB_FLAGS_MSTATUS_FS MSTATUS_FS
> @@ -294,13 +293,13 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>  int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
>                  target_ulong new_value, target_ulong write_mask);
>  
> -static inline void csr_write_helper(CPURISCVState *env, target_ulong val,
> -                                    int csrno)
> +static inline void riscv_csr_write(CPURISCVState *env, int csrno,
> +                                   target_ulong val)
>  {
>      riscv_csrrw(env, csrno, NULL, val, -1);
>  }
>  
> -static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
> +static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
>  {
>      target_ulong val = 0;
>      riscv_csrrw(env, csrno, &val, 0, 0);
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 69592c037042..b4bbf7a9fa0a 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -93,7 +93,7 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
>      return old;
>  }
>  
> -void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
>  {
>      if (newpriv > PRV_M) {
>          g_assert_not_reached();
> @@ -366,7 +366,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>          g_assert_not_reached();
>      }
>      env->badaddr = addr;
> -    do_raise_exception_err(env, cs->exception_index, retaddr);
> +    riscv_raise_exception(env, cs->exception_index, retaddr);
>  }
>  
>  /* called by qemu's softmmu to fill the qemu tlb */
> @@ -378,7 +378,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
>      if (ret == TRANSLATE_FAIL) {
>          RISCVCPU *cpu = RISCV_CPU(cs);
>          CPURISCVState *env = &cpu->env;
> -        do_raise_exception_err(env, cs->exception_index, retaddr);
> +        riscv_raise_exception(env, cs->exception_index, retaddr);
>      }
>  }
>  
> @@ -530,7 +530,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          s = set_field(s, MSTATUS_SPP, env->priv);
>          s = set_field(s, MSTATUS_SIE, 0);
>          env->mstatus = s;
> -        riscv_set_mode(env, PRV_S);
> +        riscv_cpu_set_mode(env, PRV_S);
>      } else {
>          /* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
>          env->pc = env->mtvec;
> @@ -555,7 +555,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          s = set_field(s, MSTATUS_MPP, env->priv);
>          s = set_field(s, MSTATUS_MIE, 0);
>          env->mstatus = s;
> -        riscv_set_mode(env, PRV_M);
> +        riscv_cpu_set_mode(env, PRV_M);
>      }
>      /* TODO yield load reservation  */
>  #endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 0f886e04b130..45e33d876034 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -95,7 +95,7 @@ static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
>          return -1;
>      }
>  #endif
> -    *val = cpu_riscv_get_fflags(env);
> +    *val = riscv_cpu_get_fflags(env);
>      return 0;
>  }
>  
> @@ -107,7 +107,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
>      }
>      env->mstatus |= MSTATUS_FS;
>  #endif
> -    cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> +    riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
>      return 0;
>  }
>  
> @@ -141,7 +141,7 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
>          return -1;
>      }
>  #endif
> -    *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
> +    *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
>          | (env->frm << FSR_RD_SHIFT);
>      return 0;
>  }
> @@ -155,7 +155,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
>      env->mstatus |= MSTATUS_FS;
>  #endif
>      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> -    cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> +    riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
>      return 0;
>  }
>  
> diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
> index fdb87d8d82cb..1452a153f261 100644
> --- a/target/riscv/fpu_helper.c
> +++ b/target/riscv/fpu_helper.c
> @@ -23,7 +23,7 @@
>  #include "exec/exec-all.h"
>  #include "exec/helper-proto.h"
>  
> -target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
>  {
>      int soft = get_float_exception_flags(&env->fp_status);
>      target_ulong hard = 0;
> @@ -37,7 +37,7 @@ target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
>      return hard;
>  }
>  
> -void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong hard)
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
>  {
>      int soft = 0;
>  
> @@ -74,7 +74,7 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
>          softrm = float_round_ties_away;
>          break;
>      default:
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>  
>      set_float_rounding_mode(softrm, &env->fp_status);
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 77c79ba36e0b..b7dc18a41e21 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -25,7 +25,7 @@
>  #include "exec/helper-proto.h"
>  
>  /* Exceptions processing helpers */
> -void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
> +void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
>                                            uint32_t exception, uintptr_t pc)

You forgot to remove an extra space to align arguments.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

>  {
>      CPUState *cs = CPU(riscv_env_get_cpu(env));
> @@ -36,7 +36,7 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
>  
>  void helper_raise_exception(CPURISCVState *env, uint32_t exception)
>  {
> -    do_raise_exception_err(env, exception, 0);
> +    riscv_raise_exception(env, exception, 0);
>  }
>  
>  target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
> @@ -44,7 +44,7 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, src, -1) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -54,7 +54,7 @@ target_ulong helper_csrrs(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -64,7 +64,7 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -74,17 +74,17 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  {
>      if (!(env->priv >= PRV_S)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>  
>      target_ulong retpc = env->sepc;
>      if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> -        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>  
>      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
>          get_field(env->mstatus, MSTATUS_TSR)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>  
>      target_ulong mstatus = env->mstatus;
> @@ -95,7 +95,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          get_field(mstatus, MSTATUS_SPIE));
>      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> -    riscv_set_mode(env, prev_priv);
> +    riscv_cpu_set_mode(env, prev_priv);
>      env->mstatus = mstatus;
>  
>      return retpc;
> @@ -104,12 +104,12 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  {
>      if (!(env->priv >= PRV_M)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>  
>      target_ulong retpc = env->mepc;
>      if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> -        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>  
>      target_ulong mstatus = env->mstatus;
> @@ -120,7 +120,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          get_field(mstatus, MSTATUS_MPIE));
>      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> -    riscv_set_mode(env, prev_priv);
> +    riscv_cpu_set_mode(env, prev_priv);
>      env->mstatus = mstatus;
>  
>      return retpc;
> @@ -133,7 +133,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)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          cs->halted = 1;
>          cs->exception_index = EXCP_HLT;
> @@ -148,7 +148,7 @@ void helper_tlb_flush(CPURISCVState *env)
>      if (env->priv == PRV_S &&
>          env->priv_ver >= PRIV_VERSION_1_10_0 &&
>          get_field(env->mstatus, MSTATUS_TVM)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          tlb_flush(cs);
>      }
> 

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

* Re: [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC Michael Clark
@ 2018-05-23 12:37   ` Philippe Mathieu-Daudé
  2018-05-29 23:47   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:37 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 09:15 PM, Michael Clark wrote:
> The mode variable only uses the lower 4-bits (M,H,S,U) so
> replace the GCC specific __builtin_popcount with ctpop8.
> 
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/riscv/sifive_plic.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
> index b267ff88902d..dc6f4924e282 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -383,7 +383,7 @@ static void parse_hart_config(SiFivePLICState *plic)
>      p = plic->hart_config;
>      while ((c = *p++)) {
>          if (c == ',') {
> -            addrid += __builtin_popcount(modes);
> +            addrid += ctpop8(modes);
>              modes = 0;
>              hartid++;
>          } else {
> @@ -397,7 +397,7 @@ static void parse_hart_config(SiFivePLICState *plic)
>          }
>      }
>      if (modes) {
> -        addrid += __builtin_popcount(modes);
> +        addrid += ctpop8(modes);
>      }
>      hartid++;
>  
> 

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

* Re: [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config Michael Clark
@ 2018-05-23 12:40   ` Philippe Mathieu-Daudé
  2018-05-24 22:43     ` Alistair Francis
  0 siblings, 1 reply; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:40 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 09:15 PM, Michael Clark wrote:
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/riscv/virt.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index ad03113e0f72..321fa6e8122a 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -385,6 +385,8 @@ static void riscv_virt_board_init(MachineState *machine)
>      serial_mm_init(system_memory, memmap[VIRT_UART0].base,
>          0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
>          serial_hd(0), DEVICE_LITTLE_ENDIAN);
> +
> +    g_free(plic_hart_config);
>  }
>  
>  static void riscv_virt_board_machine_init(MachineClass *mc)
> 

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

* Re: [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext Michael Clark
@ 2018-05-23 12:42   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:42 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Emilio G . Cota, Alistair Francis, patches

On 05/22/2018 09:15 PM, Michael Clark wrote:
> gen methods should access state from DisasContext. Add misa
> field to the DisasContext struct and remove CPURISCVState
> argument from all gen methods.
> 
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Cc: Emilio G. Cota <cota@braap.org>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

I already reviewed this one:
http://lists.nongnu.org/archive/html/qemu-devel/2018-05/msg02255.html

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  target/riscv/translate.c | 78 ++++++++++++++++++++++++++----------------------
>  1 file changed, 42 insertions(+), 36 deletions(-)
> 
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index a980611eb611..fd21b133a5a4 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -45,6 +45,7 @@ typedef struct DisasContext {
>      target_ulong pc_succ_insn;
>      uint32_t opcode;
>      uint32_t mstatus_fs;
> +    uint32_t misa;
>      uint32_t mem_idx;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
> @@ -74,6 +75,11 @@ static const int tcg_memop_lookup[8] = {
>  #define CASE_OP_32_64(X) case X
>  #endif
>  
> +static inline bool has_ext(DisasContext *ctx, uint32_t ext)
> +{
> +    return ctx->misa & ext;
> +}
> +
>  static void generate_exception(DisasContext *ctx, int excp)
>  {
>      tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
> @@ -505,14 +511,13 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd,
>      tcg_temp_free(source1);
>  }
>  
> -static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
> -                    target_ulong imm)
> +static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
>  {
>      target_ulong next_pc;
>  
>      /* check misaligned: */
>      next_pc = ctx->base.pc_next + imm;
> -    if (!riscv_has_ext(env, RVC)) {
> +    if (!has_ext(ctx, RVC)) {
>          if ((next_pc & 0x3) != 0) {
>              gen_exception_inst_addr_mis(ctx);
>              return;
> @@ -526,8 +531,8 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
>      ctx->base.is_jmp = DISAS_NORETURN;
>  }
>  
> -static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
> -                     int rd, int rs1, target_long imm)
> +static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1,
> +                     target_long imm)
>  {
>      /* no chaining with JALR */
>      TCGLabel *misaligned = NULL;
> @@ -539,7 +544,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
>          tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
>          tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
>  
> -        if (!riscv_has_ext(env, RVC)) {
> +        if (!has_ext(ctx, RVC)) {
>              misaligned = gen_new_label();
>              tcg_gen_andi_tl(t0, cpu_pc, 0x2);
>              tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
> @@ -564,8 +569,8 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
>      tcg_temp_free(t0);
>  }
>  
> -static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
> -                       int rs1, int rs2, target_long bimm)
> +static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
> +                       target_long bimm)
>  {
>      TCGLabel *l = gen_new_label();
>      TCGv source1, source2;
> @@ -602,7 +607,7 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
>  
>      gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
>      gen_set_label(l); /* branch taken */
> -    if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
> +    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
>          /* misaligned */
>          gen_exception_inst_addr_mis(ctx);
>      } else {
> @@ -1311,8 +1316,8 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>      }
>  }
>  
> -static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
> -                      int rd, int rs1, int csr)
> +static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
> +                       int csr)
>  {
>      TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
>      source1 = tcg_temp_new();
> @@ -1354,7 +1359,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
>              gen_exception_illegal(ctx);
>              break;
>          case 0x102: /* SRET */
> -            if (riscv_has_ext(env, RVS)) {
> +            if (has_ext(ctx, RVS)) {
>                  gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
>                  tcg_gen_exit_tb(0); /* no chaining */
>                  ctx->base.is_jmp = DISAS_NORETURN;
> @@ -1495,7 +1500,7 @@ static void decode_RV32_64C0(DisasContext *ctx)
>      }
>  }
>  
> -static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
> +static void decode_RV32_64C1(DisasContext *ctx)
>  {
>      uint8_t funct3 = extract32(ctx->opcode, 13, 3);
>      uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
> @@ -1515,7 +1520,7 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
>                        GET_C_IMM(ctx->opcode));
>  #else
>          /* C.JAL(RV32) -> jal x1, offset[11:1] */
> -        gen_jal(env, ctx, 1, GET_C_J_IMM(ctx->opcode));
> +        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
>  #endif
>          break;
>      case 2:
> @@ -1594,22 +1599,22 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
>          break;
>      case 5:
>          /* C.J -> jal x0, offset[11:1]*/
> -        gen_jal(env, ctx, 0, GET_C_J_IMM(ctx->opcode));
> +        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
>          break;
>      case 6:
>          /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
>          rs1s = GET_C_RS1S(ctx->opcode);
> -        gen_branch(env, ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> +        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>          break;
>      case 7:
>          /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
>          rs1s = GET_C_RS1S(ctx->opcode);
> -        gen_branch(env, ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> +        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>          break;
>      }
>  }
>  
> -static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
> +static void decode_RV32_64C2(DisasContext *ctx)
>  {
>      uint8_t rd, rs2;
>      uint8_t funct3 = extract32(ctx->opcode, 13, 3);
> @@ -1643,7 +1648,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
>          if (extract32(ctx->opcode, 12, 1) == 0) {
>              if (rs2 == 0) {
>                  /* C.JR -> jalr x0, rs1, 0*/
> -                gen_jalr(env, ctx, OPC_RISC_JALR, 0, rd, 0);
> +                gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0);
>              } else {
>                  /* C.MV -> add rd, x0, rs2 */
>                  gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
> @@ -1651,11 +1656,11 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
>          } else {
>              if (rd == 0) {
>                  /* C.EBREAK -> ebreak*/
> -                gen_system(env, ctx, OPC_RISC_ECALL, 0, 0, 0x1);
> +                gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
>              } else {
>                  if (rs2 == 0) {
>                      /* C.JALR -> jalr x1, rs1, 0*/
> -                    gen_jalr(env, ctx, OPC_RISC_JALR, 1, rd, 0);
> +                    gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0);
>                  } else {
>                      /* C.ADD -> add rd, rd, rs2 */
>                      gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
> @@ -1687,7 +1692,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
>      }
>  }
>  
> -static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
> +static void decode_RV32_64C(DisasContext *ctx)
>  {
>      uint8_t op = extract32(ctx->opcode, 0, 2);
>  
> @@ -1696,15 +1701,15 @@ static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
>          decode_RV32_64C0(ctx);
>          break;
>      case 1:
> -        decode_RV32_64C1(env, ctx);
> +        decode_RV32_64C1(ctx);
>          break;
>      case 2:
> -        decode_RV32_64C2(env, ctx);
> +        decode_RV32_64C2(ctx);
>          break;
>      }
>  }
>  
> -static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
> +static void decode_RV32_64G(DisasContext *ctx)
>  {
>      int rs1;
>      int rs2;
> @@ -1739,13 +1744,13 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
>          break;
>      case OPC_RISC_JAL:
>          imm = GET_JAL_IMM(ctx->opcode);
> -        gen_jal(env, ctx, rd, imm);
> +        gen_jal(ctx, rd, imm);
>          break;
>      case OPC_RISC_JALR:
> -        gen_jalr(env, ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
> +        gen_jalr(ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
>          break;
>      case OPC_RISC_BRANCH:
> -        gen_branch(env, ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
> +        gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
>                     GET_B_IMM(ctx->opcode));
>          break;
>      case OPC_RISC_LOAD:
> @@ -1818,7 +1823,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
>  #endif
>          break;
>      case OPC_RISC_SYSTEM:
> -        gen_system(env, ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
> +        gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
>                     (ctx->opcode & 0xFFF00000) >> 20);
>          break;
>      default:
> @@ -1827,29 +1832,31 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
>      }
>  }
>  
> -static void decode_opc(CPURISCVState *env, DisasContext *ctx)
> +static void decode_opc(DisasContext *ctx)
>  {
>      /* check for compressed insn */
>      if (extract32(ctx->opcode, 0, 2) != 3) {
> -        if (!riscv_has_ext(env, RVC)) {
> +        if (!has_ext(ctx, RVC)) {
>              gen_exception_illegal(ctx);
>          } else {
>              ctx->pc_succ_insn = ctx->base.pc_next + 2;
> -            decode_RV32_64C(env, ctx);
> +            decode_RV32_64C(ctx);
>          }
>      } else {
>          ctx->pc_succ_insn = ctx->base.pc_next + 4;
> -        decode_RV32_64G(env, ctx);
> +        decode_RV32_64G(ctx);
>      }
>  }
>  
> -static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
> +static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
>  {
>      DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +    CPURISCVState *env = cpu->env_ptr;
>  
>      ctx->pc_succ_insn = ctx->base.pc_first;
>      ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
>      ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
> +    ctx->misa = env->misa;
>      ctx->frm = -1;  /* unknown rounding mode */
>  }
>  
> @@ -1880,14 +1887,13 @@ static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
>      return true;
>  }
>  
> -
>  static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
>  {
>      DisasContext *ctx = container_of(dcbase, DisasContext, base);
>      CPURISCVState *env = cpu->env_ptr;
>  
>      ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
> -    decode_opc(env, ctx);
> +    decode_opc(ctx);
>      ctx->base.pc_next = ctx->pc_succ_insn;
>  
>      if (ctx->base.is_jmp == DISAS_NEXT) {
> 

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

* Re: [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree Michael Clark
@ 2018-05-23 12:45   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:45 UTC (permalink / raw)
  To: Michael Clark, qemu-devel; +Cc: patches

On 05/22/2018 09:15 PM, Michael Clark wrote:

With your Signed-off-by:
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/riscv/sifive_u.c | 4 +++-
>  hw/riscv/spike.c    | 6 ++++--
>  hw/riscv/virt.c     | 4 +++-
>  3 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 326b0f434cff..02721d43c474 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -206,7 +206,9 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
>  
>      qemu_fdt_add_subnode(fdt, "/chosen");
>      qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
> -    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    if (cmdline) {
> +        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    }
>      g_free(nodename);
>  }
>  
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index f94e2b670799..5dd7d28aed4e 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -156,8 +156,10 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
>      g_free(cells);
>      g_free(nodename);
>  
> -    qemu_fdt_add_subnode(fdt, "/chosen");
> -    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    if (cmdline) {
> +        qemu_fdt_add_subnode(fdt, "/chosen");
> +        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    }
>   }
>  
>  static void spike_v1_10_0_board_init(MachineState *machine)
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 321fa6e8122a..c889aa3cd269 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -253,7 +253,9 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
>  
>      qemu_fdt_add_subnode(fdt, "/chosen");
>      qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
> -    qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    if (cmdline) {
> +        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> +    }
>      g_free(nodename);
>  
>      return fdt;
> 

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

* Re: [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload Michael Clark
@ 2018-05-23 12:49   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-05-23 12:49 UTC (permalink / raw)
  To: Michael Clark, qemu-devel; +Cc: patches, Alistair Francis, Palmer Dabbelt

On 05/22/2018 09:15 PM, Michael Clark wrote:
> Support for separate firmware and kernel payload is added
> by updating BBL to read optional preloaded kernel address
> attributes from device-tree using a similar mechanism to
> that used to pass init ramdisk addresses to linux kernel.
> 
>     chosen {
>         riscv,kernel-start = <0x00000000 0x80200000>;
>         riscv,kernel-end = <0x00000000 0x80590634>;
>     };
> 
> These attributes are added by QEMU and read by BBL when combining
> -bios <firmware-image> and -kernel <kernel-image> options. e.g.
> 
> $ qemu-system-riscv64 -machine virt -bios bbl -kernel vmlinux
> 
> With this change, bbl can be compiled without --with-payload
> and the dummy payload alignment is altered to make the memory
> footprint of the firmware-only bbl smaller. The dummy payload
> message is updated to indicate the alternative load method.
> 
> This load method could also be supported by a first stage boot
> loader that reads seperate firmware and kernel from SPI flash.
> The main advantage of this new mechanism is that it eases kernel
> development by avoiding the riscv-pk packaging step after kernel
> builds, makes building per repository artefacts for CI simpler,
> and mimics bootloaders on other platforms that can load a kernel
> image file directly. Ultimately BBL should use an SPI driver to
> load the kernel image however this mechanism supports use cases
> such such as QEMU's -bios, -kernel and -initrd options following
> examples from other platforms that pass kernel entry to firmware
> via device-tree.
> 
> The board is also changed to use the firmware address from the
> loaded firmware or combined firmware+kernel. This is normally
> equal to the DRAM base address of 0x8000_0000, however now it
> is possible to boot firmware at different load addresses because
> the reset code jumps to the actual firmware entry address.
> 
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> ---
>  hw/riscv/Makefile.objs  |   1 +
>  hw/riscv/boot.c         | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/riscv/virt.c         |  67 +++----------------

This patch would be easier to review split in 2, one dumb moving out to
separate and another with the interesting changes.

>  include/hw/riscv/boot.h |  30 +++++++++
>  4 files changed, 213 insertions(+), 57 deletions(-)
>  create mode 100644 hw/riscv/boot.c
>  create mode 100644 include/hw/riscv/boot.h
> 
> diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
> index 1dde01d39dcc..d36b004ab0f9 100644
> --- a/hw/riscv/Makefile.objs
> +++ b/hw/riscv/Makefile.objs
> @@ -1,3 +1,4 @@
> +obj-y += boot.o
>  obj-y += riscv_htif.o
>  obj-y += riscv_hart.o
>  obj-y += sifive_e.o
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> new file mode 100644
> index 000000000000..cf4e5d594638
> --- /dev/null
> +++ b/hw/riscv/boot.c
> @@ -0,0 +1,172 @@
> +/*
> + * QEMU RISCV firmware and kernel loader
> + *
> + * Copyright (c) 2017-2018 SiFive, Inc.
> + *
> + * Holds the state of a heterogenous array of RISC-V harts
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "qemu/error-report.h"
> +#include "hw/loader.h"
> +#include "hw/boards.h"
> +#include "sysemu/device_tree.h"
> +#include "elf.h"
> +#include "hw/riscv/boot.h"
> +
> +#define RISCV_BOOT_DEBUG 0
> +
> +#define boot_debug(fs, ...) \
> +    if (RISCV_BOOT_DEBUG) { \
> +        fprintf(stderr, "boot: %s: "fs, __func__, ##__VA_ARGS__); \
> +    }
> +
> +static uint64_t kernel_offset;
> +
> +static uint64_t kernel_translate(void *opaque, uint64_t addr)
> +{
> +    /* mask kernel virtual address and offset by load address */
> +    if (kernel_offset) {
> +        return (addr & 0x7fffffff) + kernel_offset;
> +    } else {
> +        return addr;
> +    }
> +}
> +
> +hwaddr riscv_load_firmware(const char *filename)
> +{
> +    uint64_t firmware_entry, firmware_start, firmware_end;
> +
> +    if (load_elf(filename, NULL, NULL,
> +                 &firmware_entry, &firmware_start, &firmware_end,
> +                 0, EM_RISCV, 1, 0) < 0) {
> +        error_report("riscv_boot: could not load firmware '%s'", filename);
> +        exit(1);
> +    }
> +
> +    /* align kernel load address to the megapage after the firmware */
> +#if defined(TARGET_RISCV32)
> +    kernel_offset = (firmware_end + 0x3fffff) & ~0x3fffff;
> +#else
> +    kernel_offset = (firmware_end + 0x1fffff) & ~0x1fffff;
> +#endif
> +
> +    boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
> +               "end=0x" TARGET_FMT_plx " kernel_offset=0x" TARGET_FMT_plx "\n",
> +               firmware_entry, firmware_start, firmware_end, kernel_offset);
> +
> +    return firmware_entry;
> +}
> +
> +hwaddr riscv_load_kernel(const char *filename, void *fdt)
> +{
> +    uint64_t kernel_entry, kernel_start, kernel_end;
> +
> +    if (load_elf(filename, kernel_translate, NULL,
> +                 &kernel_entry, &kernel_start, &kernel_end,
> +                 0, EM_RISCV, 1, 0) < 0) {
> +        error_report("riscv_boot: could not load kernel '%s'", filename);
> +        exit(1);
> +    }
> +
> +    boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
> +               "end=0x" TARGET_FMT_plx "\n", kernel_entry, kernel_start,
> +               kernel_end);
> +
> +    /*
> +     * pass kernel load address via device-tree to firmware
> +     *
> +     * BBL reads the kernel address from device-tree
> +     */
> +    if (fdt) {
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-end",
> +                               kernel_end >> 32, kernel_end);
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-start",
> +                               kernel_start >> 32, kernel_start);
> +    }
> +
> +    return kernel_entry;
> +}
> +
> +void riscv_load_initrd(const char *filename, uint64_t mem_size,
> +                       hwaddr firmware_entry, void *fdt)
> +{
> +    uint64_t start, size;
> +
> +    /* We want to put the initrd far enough into RAM that when the
> +     * kernel is uncompressed it will not clobber the initrd. However
> +     * on boards without much RAM we must ensure that we still leave
> +     * enough room for a decent sized initrd, and on boards with large
> +     * amounts of RAM we must avoid the initrd being so far up in RAM
> +     * that it is outside lowmem and inaccessible to the kernel.
> +     * So for boards with less  than 256MB of RAM we put the initrd
> +     * halfway into RAM, and for boards with 256MB of RAM or more we put
> +     * the initrd at 128MB.
> +     */
> +    start = firmware_entry + MIN(mem_size / 2, 128 * 1024 * 1024);
> +
> +    size = load_ramdisk(filename, start, mem_size - start);
> +    if (size == -1) {
> +        size = load_image_targphys(filename, start, mem_size - start);
> +        if (size == -1) {
> +            error_report("riscv_boot: could not load ramdisk '%s'", filename);
> +            exit(1);
> +        }
> +    }
> +
> +    boot_debug("start=0x" TARGET_FMT_plx " end=0x" TARGET_FMT_plx "\n",
> +               start, start + size);
> +
> +    /*
> +     * pass initrd load address via device-tree to kernel
> +     *
> +     * linux-kernel reads the initrd address from device-tree
> +     */
> +    if (fdt) {
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-end",
> +                               (start + size) >> 32, start + size);
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-start",
> +                               start >> 32, start);
> +    }
> +}
> +
> +hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt)
> +{
> +    hwaddr firmware_entry = 0;
> +
> +    /* load firmware e.g. -bios bbl */
> +    if (machine->firmware) {
> +        firmware_entry = riscv_load_firmware(machine->firmware);
> +    }
> +
> +    /* load combined bbl+kernel or separate kernel */
> +    if (machine->kernel_filename) {
> +        if (machine->firmware) {
> +            /* load separate bios and kernel e.g. -bios bbl -kernel vmlinux */
> +            riscv_load_kernel(machine->kernel_filename, fdt);
> +        } else {
> +            /* load traditional combined bbl+kernel e.g. -kernel bbl_vmlimux */
> +            firmware_entry = riscv_load_kernel(machine->kernel_filename, NULL);
> +        }
> +        if (machine->initrd_filename) {
> +            /* load separate initrd */
> +            riscv_load_initrd(machine->initrd_filename, machine->ram_size,
> +                              firmware_entry, fdt);
> +        }
> +    }
> +
> +    return firmware_entry;
> +}
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index c889aa3cd269..984ddf0635fd 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -33,6 +33,7 @@
>  #include "hw/riscv/sifive_plic.h"
>  #include "hw/riscv/sifive_clint.h"
>  #include "hw/riscv/sifive_test.h"
> +#include "hw/riscv/boot.h"
>  #include "hw/riscv/virt.h"
>  #include "chardev/char.h"
>  #include "sysemu/arch_init.h"
> @@ -56,47 +57,6 @@ static const struct MemmapEntry {
>      [VIRT_DRAM] =     { 0x80000000,        0x0 },
>  };
>  
> -static uint64_t load_kernel(const char *kernel_filename)
> -{
> -    uint64_t kernel_entry, kernel_high;
> -
> -    if (load_elf(kernel_filename, NULL, NULL,
> -                 &kernel_entry, NULL, &kernel_high,
> -                 0, EM_RISCV, 1, 0) < 0) {
> -        error_report("qemu: could not load kernel '%s'", kernel_filename);
> -        exit(1);
> -    }
> -    return kernel_entry;
> -}
> -
> -static hwaddr load_initrd(const char *filename, uint64_t mem_size,
> -                          uint64_t kernel_entry, hwaddr *start)
> -{
> -    int size;
> -
> -    /* We want to put the initrd far enough into RAM that when the
> -     * kernel is uncompressed it will not clobber the initrd. However
> -     * on boards without much RAM we must ensure that we still leave
> -     * enough room for a decent sized initrd, and on boards with large
> -     * amounts of RAM we must avoid the initrd being so far up in RAM
> -     * that it is outside lowmem and inaccessible to the kernel.
> -     * So for boards with less  than 256MB of RAM we put the initrd
> -     * halfway into RAM, and for boards with 256MB of RAM or more we put
> -     * the initrd at 128MB.
> -     */
> -    *start = kernel_entry + MIN(mem_size / 2, 128 * 1024 * 1024);
> -
> -    size = load_ramdisk(filename, *start, mem_size - *start);
> -    if (size == -1) {
> -        size = load_image_targphys(filename, *start, mem_size - *start);
> -        if (size == -1) {
> -            error_report("qemu: could not load ramdisk '%s'", filename);
> -            exit(1);
> -        }
> -    }
> -    return *start + size;
> -}
> -
>  static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
>      uint64_t mem_size, const char *cmdline)
>  {
> @@ -273,6 +233,7 @@ static void riscv_virt_board_init(MachineState *machine)
>      size_t plic_hart_config_len;
>      int i;
>      void *fdt;
> +    hwaddr firmware_entry;
>  
>      /* Initialize SOC */
>      object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> @@ -300,20 +261,12 @@ static void riscv_virt_board_init(MachineState *machine)
>      memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
>                                  mask_rom);
>  
> -    if (machine->kernel_filename) {
> -        uint64_t kernel_entry = load_kernel(machine->kernel_filename);
> -
> -        if (machine->initrd_filename) {
> -            hwaddr start;
> -            hwaddr end = load_initrd(machine->initrd_filename,
> -                                     machine->ram_size, kernel_entry,
> -                                     &start);
> -            qemu_fdt_setprop_cell(fdt, "/chosen",
> -                                  "linux,initrd-start", start);
> -            qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> -                                  end);
> -        }
> -    }
> +    /*
> +     * combined firmware and kernel: -kernel bbl_vmlimux
> +     * separate firmware and kernel: -bios bbl -kernel vmlinux
> +     * firmware, kernel and ramdisk: -bios bbl -kernel vmlinux -initrd initramfs
> +     */
> +    firmware_entry = riscv_load_firmware_kernel_initrd(machine, fdt);
>  
>      /* reset vector */
>      uint32_t reset_vec[8] = {
> @@ -327,8 +280,8 @@ static void riscv_virt_board_init(MachineState *machine)
>  #endif
>          0x00028067,                  /*     jr     t0 */
>          0x00000000,
> -        memmap[VIRT_DRAM].base,      /* start: .dword memmap[VIRT_DRAM].base */
> -        0x00000000,
> +        firmware_entry,              /* .word firmware_entry */
> +        firmware_entry >> 32,
>                                       /* dtb: */
>      };
>  
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> new file mode 100644
> index 000000000000..aa30bf1c45b2
> --- /dev/null
> +++ b/include/hw/riscv/boot.h
> @@ -0,0 +1,30 @@
> +/*
> + * QEMU RISCV firmware and kernel loader interface
> + *
> + * Copyright (c) 2017-2018 SiFive, Inc.
> + *
> + * Holds the state of a heterogenous array of RISC-V harts
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef HW_RISCV_BOOT_H
> +#define HW_RISCV_BOOT_H
> +
> +hwaddr riscv_load_firmware(const char *filename);
> +hwaddr riscv_load_kernel(const char *filename, void *fdt);
> +void riscv_load_initrd(const char *filename, uint64_t mem_size,
> +                       hwaddr firmware_entry, void *fdt);
> +hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt);
> +
> +#endif
> 

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

* Re: [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance Michael Clark
@ 2018-05-23 22:31   ` Michael Clark
  0 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-23 22:31 UTC (permalink / raw)
  To: QEMU Developers, Philippe Mathieu-Daudé,
	Alistair Francis, Richard Henderson
  Cc: RISC-V Patches, Michael Clark, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt

Hi Phil, Alastair, Richard, et al...

Apologies if I'm slow to respond to your other review emails. I'm going to
go through all of them and address each of them one by one.

Currently, I want to either get some MMU tests from the verification team
or separately write tests for the newly added comments in the page walker.

1). +            /* Invalid PTE */
2). +            /* Inner PTE, continue walking */
3). +            /* Reserved leaf PTE flags: PTE_W */
4). +            /* Reserved leaf PTE flags: PTE_W + PTE_X */
5). +            /* User PTE flags when not U mode and mstatus.SUM is not
set,
6). +            /* Supervisor PTE flags when not S mode */
7). +            /* Misasligned PPN */
8). +            /* Read access check failed */
9). +            /* Write access check failed */
10). +            /* Fetch access check failed */
11).             /* if necessary, set accessed and dirty bits. */

That's why I might be slow to respond to the other emails but I will get to
them in due course.

SiFive has internal verification tests which require RTL test harness.
Currently, the open source MMU tests need expanding. It might be better
that we expand the latter as it will be helpful for other implementations
to test their page walkers (hardware and emulators alike):

- https://github.com/riscv/riscv-tests/tree/master/isa/rv64si/

I can then compare master vs this patch. I think master may fail Misasligned
PPN. I may just test critical function such as U-mode can't access U=0.
That's pretty easy as linux-kernel has a shared kernel address space and
riscv-linux doesn't yet have ASLR so I can just try to deref a kernel
address in userspace. In fact we still need to implement kernel memory
protection for riscv-linux i.e. .rodata +R, .text +RX and .data +RW (W^X)
before we add ASLR. The linux kernel port is indeed quite new but this
patch does not regress any user-facing functionality.

One of the goals with this patch is to make the logical clauses and
comments match the English text in the RISC-V Privileged ISA v1.10 with
respect to the MMU.

Michael.

On Wed, May 23, 2018 at 12:14 PM, Michael Clark <mjc@sifive.com> wrote:

> - Inline PTE_TABLE check for better readability
> - Change access checks from ternary operator to if
> - Improve readibility of User page U mode and SUM test
> - Disallow non U mode from fetching from User pages
> - Add reserved PTE flag check: W or W|X
> - Add misaligned PPN check
> - Set READ protection for PTE X flag and mstatus.mxr
> - Use memory_region_is_ram in pte update
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/cpu_bits.h |  2 --
>  target/riscv/helper.c   | 64 ++++++++++++++++++++++++++++++
> ++++---------------
>  2 files changed, 45 insertions(+), 21 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 64aa097181fa..12b4757088f4 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -407,5 +407,3 @@
>  #define PTE_SOFT  0x300 /* Reserved for Software */
>
>  #define PTE_PPN_SHIFT 10
> -
> -#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) ==
> PTE_V)
> diff --git a/target/riscv/helper.c b/target/riscv/helper.c
> index 95889f23b94d..3b57e1360549 100644
> --- a/target/riscv/helper.c
> +++ b/target/riscv/helper.c
> @@ -185,16 +185,39 @@ restart:
>  #endif
>          target_ulong ppn = pte >> PTE_PPN_SHIFT;
>
> -        if (PTE_TABLE(pte)) { /* next level of page table */
> +        if (!(pte & PTE_V)) {
> +            /* Invalid PTE */
> +            return TRANSLATE_FAIL;
> +        } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
> +            /* Inner PTE, continue walking */
>              base = ppn << PGSHIFT;
> -        } else if ((pte & PTE_U) ? (mode == PRV_S) && !sum : !(mode ==
> PRV_S)) {
> -            break;
> -        } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
> -            break;
> -        } else if (access_type == MMU_INST_FETCH ? !(pte & PTE_X) :
> -                  access_type == MMU_DATA_LOAD ?  !(pte & PTE_R) &&
> -                  !(mxr && (pte & PTE_X)) : !((pte & PTE_R) && (pte &
> PTE_W))) {
> -            break;
> +        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
> +            /* Reserved leaf PTE flags: PTE_W */
> +            return TRANSLATE_FAIL;
> +        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
> +            /* Reserved leaf PTE flags: PTE_W + PTE_X */
> +            return TRANSLATE_FAIL;
> +        } else if ((pte & PTE_U) && ((mode != PRV_U) &&
> +                   (!sum || access_type == MMU_INST_FETCH))) {
> +            /* User PTE flags when not U mode and mstatus.SUM is not set,
> +               or the access type is an instruction fetch */
> +            return TRANSLATE_FAIL;
> +        } else if (!(pte & PTE_U) && (mode != PRV_S)) {
> +            /* Supervisor PTE flags when not S mode */
> +            return TRANSLATE_FAIL;
> +        } else if (ppn & ((1ULL << ptshift) - 1)) {
> +            /* Misasligned PPN */
> +            return TRANSLATE_FAIL;
> +        } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
> +                   ((pte & PTE_X) && mxr))) {
> +            /* Read access check failed */
> +            return TRANSLATE_FAIL;
> +        } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
> +            /* Write access check failed */
> +            return TRANSLATE_FAIL;
> +        } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
> +            /* Fetch access check failed */
> +            return TRANSLATE_FAIL;
>          } else {
>              /* if necessary, set accessed and dirty bits. */
>              target_ulong updated_pte = pte | PTE_A |
> @@ -202,16 +225,19 @@ restart:
>
>              /* Page table updates need to be atomic with MTTCG enabled */
>              if (updated_pte != pte) {
> -                /* if accessed or dirty bits need updating, and the PTE is
> -                 * in RAM, then we do so atomically with a compare and
> swap.
> -                 * if the PTE is in IO space, then it can't be updated.
> -                 * if the PTE changed, then we must re-walk the page table
> -                   as the PTE is no longer valid */
> +                /*
> +                 * - if accessed or dirty bits need updating, and the PTE
> is
> +                 *   in RAM, then we do so atomically with a compare and
> swap.
> +                 * - if the PTE is in IO space or ROM, then it can't be
> updated
> +                 *   and we return TRANSLATE_FAIL.
> +                 * - if the PTE changed by the time we went to update it,
> then
> +                 *   it is no longer valid and we must re-walk the page
> table.
> +                 */
>                  MemoryRegion *mr;
>                  hwaddr l = sizeof(target_ulong), addr1;
>                  mr = address_space_translate(cs->as, pte_addr,
>                      &addr1, &l, false);
> -                if (memory_access_is_direct(mr, true)) {
> +                if (memory_region_is_ram(mr)) {
>                      target_ulong *pte_pa =
>                          qemu_map_ram_ptr(mr->ram_block, addr1);
>  #if TCG_OVERSIZED_GUEST
> @@ -239,15 +265,15 @@ restart:
>              target_ulong vpn = addr >> PGSHIFT;
>              *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
>
> -            if ((pte & PTE_R)) {
> +            /* set permissions on the TLB entry */
> +            if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
>                  *prot |= PAGE_READ;
>              }
>              if ((pte & PTE_X)) {
>                  *prot |= PAGE_EXEC;
>              }
> -           /* only add write permission on stores or if the page
> -              is already dirty, so that we don't miss further
> -              page table walks to update the dirty bit */
> +            /* 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))) {
>                  *prot |= PAGE_WRITE;
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs Michael Clark
@ 2018-05-23 23:55   ` Alistair Francis
  2018-05-25 15:19   ` Richard Henderson
  1 sibling, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-23 23:55 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:14 PM, Michael Clark <mjc@sifive.com> wrote:
> Change the API of riscv_set_local_interrupt to take a
> write mask and value to allow setting and clearing of
> multiple local interrupts atomically in a single call.
> Rename the new function to riscv_cpu_update_mip.
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_clint.c  |  8 ++++----
>  hw/riscv/sifive_plic.c   |  4 ++--
>  target/riscv/cpu.h       | 22 +++++++++++++---------
>  target/riscv/op_helper.c | 24 +++++++++++++++---------
>  4 files changed, 34 insertions(+), 24 deletions(-)
>
> diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
> index 7cc606e06546..0d2fd52487e6 100644
> --- a/hw/riscv/sifive_clint.c
> +++ b/hw/riscv/sifive_clint.c
> @@ -47,12 +47,12 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
>      if (cpu->env.timecmp <= rtc_r) {
>          /* if we're setting an MTIMECMP value in the "past",
>             immediately raise the timer interrupt */
> -        riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
> +        riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
>          return;
>      }
>
>      /* otherwise, set up the future timer interrupt */
> -    riscv_set_local_interrupt(cpu, MIP_MTIP, 0);
> +    riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
>      diff = cpu->env.timecmp - rtc_r;
>      /* back to ns (note args switched in muldiv64) */
>      next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> @@ -67,7 +67,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
>  static void sifive_clint_timer_cb(void *opaque)
>  {
>      RISCVCPU *cpu = opaque;
> -    riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
> +    riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
>  }
>
>  /* CPU wants to read rtc or timecmp register */
> @@ -132,7 +132,7 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
>          if (!env) {
>              error_report("clint: invalid timecmp hartid: %zu", hartid);
>          } else if ((addr & 0x3) == 0) {
> -            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MSIP, value != 0);
> +            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MSIP, BOOL_TO_MASK(value));
>          } else {
>              error_report("clint: invalid sip write: %08x", (uint32_t)addr);
>          }
> diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
> index 1af23c76e603..b267ff88902d 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -142,10 +142,10 @@ static void sifive_plic_update(SiFivePLICState *plic)
>          int level = sifive_plic_irqs_pending(plic, addrid);
>          switch (mode) {
>          case PLICMode_M:
> -            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
> +            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
>              break;
>          case PLICMode_S:
> -            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_SEIP, level);
> +            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level));
>              break;
>          default:
>              break;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index e0608e6d5f08..c5d485769cde 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -126,13 +126,18 @@ struct CPURISCVState {
>
>      target_ulong mhartid;
>      target_ulong mstatus;
> +
>      /*
>       * CAUTION! Unlike the rest of this struct, mip is accessed asynchonously
> -     * by I/O threads and other vCPUs, so hold the iothread mutex before
> -     * operating on it.  CPU_INTERRUPT_HARD should be in effect iff this is
> -     * non-zero.  Use riscv_cpu_set_local_interrupt.
> +     * by I/O threads. It should be read with atomic_read. It should be updated
> +     * using riscv_cpu_update_mip with the iothread mutex held. The iothread
> +     * mutex must be held because mip must be consistent with the CPU inturrept
> +     * state. riscv_cpu_update_mip calls cpu_interrupt or cpu_reset_interrupt
> +     * wuth the invariant that CPU_INTERRUPT_HARD is set iff mip is non-zero.
> +     * mip is 32-bits to allow atomic_read on 32-bit hosts.
>       */
> -    uint32_t mip;        /* allow atomic_read for >= 32-bit hosts */
> +    uint32_t mip;
> +
>      target_ulong mie;
>      target_ulong mideleg;
>
> @@ -247,7 +252,6 @@ void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>                                      uintptr_t retaddr);
>  int riscv_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
>                                int rw, int mmu_idx);
> -
>  char *riscv_isa_string(RISCVCPU *cpu);
>  void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>
> @@ -256,6 +260,10 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  #define cpu_list riscv_cpu_list
>  #define cpu_mmu_index riscv_cpu_mmu_index
>
> +#ifndef CONFIG_USER_ONLY
> +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 */
> +#endif
>  void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
>
>  void riscv_translate_init(void);
> @@ -286,10 +294,6 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
>          target_ulong csrno);
>  target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno);
>
> -#ifndef CONFIG_USER_ONLY
> -void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value);
> -#endif
> -
>  #include "exec/cpu-all.h"
>
>  #endif /* RISCV_CPU_H */
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 3abf52453cfc..5a02795bf931 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -171,10 +171,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
>           */
>          qemu_mutex_lock_iothread();
>          RISCVCPU *cpu = riscv_env_get_cpu(env);
> -        riscv_set_local_interrupt(cpu, MIP_SSIP,
> -                                  (val_to_write & MIP_SSIP) != 0);
> -        riscv_set_local_interrupt(cpu, MIP_STIP,
> -                                  (val_to_write & MIP_STIP) != 0);
> +        riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
> +                                  (val_to_write & (MIP_SSIP | MIP_STIP)));
>          /*
>           * csrs, csrc on mip.SEIP is not decomposable into separate read and
>           * write steps, so a different implementation is needed
> @@ -655,16 +653,24 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  #ifndef CONFIG_USER_ONLY
>
>  /* iothread_mutex must be held */
> -void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value)
> +uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
>  {
> -    target_ulong old_mip = cpu->env.mip;
> -    cpu->env.mip = (old_mip & ~mask) | (value ? mask : 0);
> +    CPURISCVState *env = &cpu->env;
> +    uint32_t old, new, cmp = atomic_read(&env->mip);
>
> -    if (cpu->env.mip && !old_mip) {
> +    do {
> +        old = cmp;
> +        new = (old & ~mask) | (value & mask);
> +        cmp = atomic_cmpxchg(&env->mip, old, new);
> +    } while (old != cmp);
> +
> +    if (new && !old) {
>          cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    } else if (!cpu->env.mip && old_mip) {
> +    } else if (!new && old) {
>          cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
>      }
> +
> +    return old;
>  }
>
>  void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config
  2018-05-23 12:40   ` Philippe Mathieu-Daudé
@ 2018-05-24 22:43     ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-24 22:43 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Michael Clark, qemu-devel@nongnu.org Developers,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	Sagar Karandikar, patches

On Wed, May 23, 2018 at 5:40 AM, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> On 05/22/2018 09:15 PM, Michael Clark wrote:
>> Cc: Palmer Dabbelt <palmer@sifive.com>
>> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
>> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> Cc: Alistair Francis <Alistair.Francis@wdc.com>
>> Signed-off-by: Michael Clark <mjc@sifive.com>
>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

>
>> ---
>>  hw/riscv/virt.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>> index ad03113e0f72..321fa6e8122a 100644
>> --- a/hw/riscv/virt.c
>> +++ b/hw/riscv/virt.c
>> @@ -385,6 +385,8 @@ static void riscv_virt_board_init(MachineState *machine)
>>      serial_mm_init(system_memory, memmap[VIRT_UART0].base,
>>          0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
>>          serial_hd(0), DEVICE_LITTLE_ENDIAN);
>> +
>> +    g_free(plic_hart_config);
>>  }
>>
>>  static void riscv_virt_board_machine_init(MachineClass *mc)
>>
>

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

* Re: [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints Michael Clark
@ 2018-05-24 22:45   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-24 22:45 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:15 PM, Michael Clark <mjc@sifive.com> wrote:
> Remove machine generated constraints that are not
> referenced by the pseudo-instruction constraints.
>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  disas/riscv.c | 138 ----------------------------------------------------------
>  1 file changed, 138 deletions(-)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index 7fd1019623ee..27546dd7902c 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -87,33 +87,10 @@ typedef enum {
>
>  typedef enum {
>      rvc_end,
> -    rvc_simm_6,
> -    rvc_imm_6,
> -    rvc_imm_7,
> -    rvc_imm_8,
> -    rvc_imm_9,
> -    rvc_imm_10,
> -    rvc_imm_12,
> -    rvc_imm_18,
> -    rvc_imm_nz,
> -    rvc_imm_x2,
> -    rvc_imm_x4,
> -    rvc_imm_x8,
> -    rvc_imm_x16,
> -    rvc_rd_b3,
> -    rvc_rs1_b3,
> -    rvc_rs2_b3,
> -    rvc_rd_eq_rs1,
>      rvc_rd_eq_ra,
> -    rvc_rd_eq_sp,
>      rvc_rd_eq_x0,
> -    rvc_rs1_eq_sp,
>      rvc_rs1_eq_x0,
>      rvc_rs2_eq_x0,
> -    rvc_rd_ne_x0_x2,
> -    rvc_rd_ne_x0,
> -    rvc_rs1_ne_x0,
> -    rvc_rs2_ne_x0,
>      rvc_rs2_eq_rs1,
>      rvc_rs1_eq_ra,
>      rvc_imm_eq_zero,
> @@ -2522,111 +2499,16 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
>      uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
>      while (*c != rvc_end) {
>          switch (*c) {
> -        case rvc_simm_6:
> -            if (!(imm >= -32 && imm < 32)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_6:
> -            if (!(imm <= 63)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_7:
> -            if (!(imm <= 127)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_8:
> -            if (!(imm <= 255)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_9:
> -            if (!(imm <= 511)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_10:
> -            if (!(imm <= 1023)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_12:
> -            if (!(imm <= 4095)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_18:
> -            if (!(imm <= 262143)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_nz:
> -            if (!(imm != 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_x2:
> -            if (!((imm & 0b1) == 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_x4:
> -            if (!((imm & 0b11) == 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_x8:
> -            if (!((imm & 0b111) == 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_imm_x16:
> -            if (!((imm & 0b1111) == 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rd_b3:
> -            if (!(rd  >= 8 && rd  <= 15)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rs1_b3:
> -            if (!(rs1 >= 8 && rs1 <= 15)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rs2_b3:
> -            if (!(rs2 >= 8 && rs2 <= 15)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rd_eq_rs1:
> -            if (!(rd == rs1)) {
> -                return false;
> -            }
> -            break;
>          case rvc_rd_eq_ra:
>              if (!(rd == 1)) {
>                  return false;
>              }
>              break;
> -        case rvc_rd_eq_sp:
> -            if (!(rd == 2)) {
> -                return false;
> -            }
> -            break;
>          case rvc_rd_eq_x0:
>              if (!(rd == 0)) {
>                  return false;
>              }
>              break;
> -        case rvc_rs1_eq_sp:
> -            if (!(rs1 == 2)) {
> -                return false;
> -            }
> -            break;
>          case rvc_rs1_eq_x0:
>              if (!(rs1 == 0)) {
>                  return false;
> @@ -2637,26 +2519,6 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
>                  return false;
>              }
>              break;
> -        case rvc_rd_ne_x0_x2:
> -            if (!(rd != 0 && rd != 2)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rd_ne_x0:
> -            if (!(rd != 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rs1_ne_x0:
> -            if (!(rs1 != 0)) {
> -                return false;
> -            }
> -            break;
> -        case rvc_rs2_ne_x0:
> -            if (!(rs2 != 0)) {
> -                return false;
> -            }
> -            break;
>          case rvc_rs2_eq_rs1:
>              if (!(rs2 == rs1)) {
>                  return false;
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging
  2018-05-23 12:33   ` Philippe Mathieu-Daudé
@ 2018-05-24 22:47     ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-24 22:47 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Michael Clark, qemu-devel@nongnu.org Developers,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	Sagar Karandikar, patches

On Wed, May 23, 2018 at 5:33 AM, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> Hi Michael,
>
> On 05/22/2018 09:15 PM, Michael Clark wrote:
>> Add carriage return that was erroneously removed
>> when converting to qemu_log. Change hard coded
>> core number to the actual hartid.
>
> I think it makes more sens to move this patch before your 6/30 "Move
> non-ops from op_helper to cpu_helper".
>
>>
>> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
>> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> Cc: Palmer Dabbelt <palmer@sifive.com>
>> Cc: Alistair Francis <Alistair.Francis@wdc.com>
>> Signed-off-by: Michael Clark <mjc@sifive.com>
>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

>
>> ---
>>  target/riscv/cpu_helper.c | 18 ++++++++++--------
>>  1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> index bc15e19022cc..69592c037042 100644
>> --- a/target/riscv/cpu_helper.c
>> +++ b/target/riscv/cpu_helper.c
>> @@ -446,11 +446,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>>      if (RISCV_DEBUG_INTERRUPT) {
>>          int log_cause = cs->exception_index & RISCV_EXCP_INT_MASK;
>>          if (cs->exception_index & RISCV_EXCP_INT_FLAG) {
>> -            qemu_log_mask(LOG_TRACE, "core   0: trap %s, epc 0x" TARGET_FMT_lx,
>> -                riscv_intr_names[log_cause], env->pc);
>> +            qemu_log_mask(LOG_TRACE, "core "
>> +                TARGET_FMT_ld ": trap %s, epc 0x" TARGET_FMT_lx "\n",
>> +                env->mhartid, riscv_intr_names[log_cause], env->pc);
>>          } else {
>> -            qemu_log_mask(LOG_TRACE, "core   0: intr %s, epc 0x" TARGET_FMT_lx,
>> -                riscv_excp_names[log_cause], env->pc);
>> +            qemu_log_mask(LOG_TRACE, "core "
>> +                TARGET_FMT_ld ": intr %s, epc 0x" TARGET_FMT_lx "\n",
>> +                env->mhartid, riscv_excp_names[log_cause], env->pc);
>>          }
>>      }
>>
>> @@ -512,8 +514,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>>
>>          if (hasbadaddr) {
>>              if (RISCV_DEBUG_INTERRUPT) {
>> -                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
>> -                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
>> +                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
>> +                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
>>              }
>>              env->sbadaddr = env->badaddr;
>>          } else {
>> @@ -537,8 +539,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>>
>>          if (hasbadaddr) {
>>              if (RISCV_DEBUG_INTERRUPT) {
>> -                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld
>> -                    ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
>> +                qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
>> +                    TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
>>              }
>>              env->mbadaddr = env->badaddr;
>>          } else {
>>
>

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

* Re: [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines
  2018-05-23  6:44   ` Laurent Vivier
@ 2018-05-25  7:17     ` Michael Clark
  0 siblings, 0 replies; 61+ messages in thread
From: Michael Clark @ 2018-05-25  7:17 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: QEMU Developers, RISC-V Patches, Michael Tokarev,
	Richard Henderson, Alistair Francis

On Wed, May 23, 2018 at 6:44 PM, Laurent Vivier <laurent@vivier.eu> wrote:

> Le 23/05/2018 à 02:15, Michael Clark a écrit :
> > Refer to the RISC-V PSABI specification for details:
> >
> > - https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
> >
> > Cc: Michael Tokarev <mjt@tls.msk.ru>
> > Cc: Laurent Vivier <laurent@vivier.eu>
> > Cc: Richard Henderson <richard.henderson@linaro.org>
> > Cc: Alistair Francis <Alistair.Francis@wdc.com>
> > Signed-off-by: Michael Clark <mjc@sifive.com>
> > ---
> >  include/elf.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/include/elf.h b/include/elf.h
> > index 934dbbd6b3ae..d363ba85a688 100644
> > --- a/include/elf.h
> > +++ b/include/elf.h
> > @@ -1285,6 +1285,14 @@ typedef struct {
> >  #define R_IA64_DTPREL64LSB   0xb7    /* @dtprel(sym + add), data8 LSB */
> >  #define R_IA64_LTOFF_DTPREL22        0xba    /* @ltoff(@dtprel(s+a)),
> imm22 */
> >
> > +/* RISC-V specific definitions.  */
> > +#define EF_RISCV_RVC 0x0001
> > +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
> > +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
> > +#define EF_RISCV_FLOAT_ABI_QUAD (0x0006
>                                    ^
> Typo here -------------------------|
>

Thanks! My mistake.

The original patch had only EF_RISCV_RVE, which is the define we need for a
subsequent patch, however I decided to add the remaining flags from the
spec and indeed there was a paren in the spec.

I'll respin this as a separate patch.

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

* Re: [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
@ 2018-05-25 15:07   ` Richard Henderson
  0 siblings, 0 replies; 61+ messages in thread
From: Richard Henderson @ 2018-05-25 15:07 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 05:14 PM, Michael Clark wrote:
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> ---
>  target/riscv/cpu.h | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

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

* Re: [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
@ 2018-05-25 15:15   ` Richard Henderson
  0 siblings, 0 replies; 61+ messages in thread
From: Richard Henderson @ 2018-05-25 15:15 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 05:14 PM, Michael Clark wrote:
> This commit is intended to improve readability.
> There is no change to the logic.
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  target/riscv/helper.c | 34 ++++++++++++----------------------
>  1 file changed, 12 insertions(+), 22 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

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

* Re: [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs Michael Clark
  2018-05-23 23:55   ` Alistair Francis
@ 2018-05-25 15:19   ` Richard Henderson
  1 sibling, 0 replies; 61+ messages in thread
From: Richard Henderson @ 2018-05-25 15:19 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 05:14 PM, Michael Clark wrote:
> Change the API of riscv_set_local_interrupt to take a
> write mask and value to allow setting and clearing of
> multiple local interrupts atomically in a single call.
> Rename the new function to riscv_cpu_update_mip.
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

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

* Re: [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
  2018-05-23 12:23   ` Philippe Mathieu-Daudé
@ 2018-05-25 15:20   ` Richard Henderson
  1 sibling, 0 replies; 61+ messages in thread
From: Richard Henderson @ 2018-05-25 15:20 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 05:14 PM, Michael Clark wrote:
> This patch makes op_helper.c contain only instruction
> operation helpers used by translate.c and moves any
> unrelated cpu helpers into cpu_helper.c. No logic is
> changed by this patch.
> 
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

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

* Re: [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support Michael Clark
@ 2018-05-25 18:53   ` Richard Henderson
  0 siblings, 0 replies; 61+ messages in thread
From: Richard Henderson @ 2018-05-25 18:53 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 05/22/2018 05:15 PM, Michael Clark wrote:
> +    /* Suppress 'C' if next instruction is not aligned
> +       TODO: this should check next_pc */
> +    if ((val & RVC) && (GETPC() & ~3) != 0) {
> +        val &= ~RVC;
> +    }

This is checking the host PC, which is useless.

Isn't this backward anyway?  Why would *setting* C require an aligned address?
Surely it's *clearing* C that would require an aligned address.

You can read the guest PC of the current instruction by doing

  cpu_restore_state(cs, GETPC(), false);
  xxx = env->pc;

In order to get the next pc, I guess you'd just need to add 4, since all of the
csr insns are not in the compact encoding space?

Alternately, to save the not insignificant amount of work that
cpu_restore_state does, and since all of the csr insns end the TB anyway, you
could move

    tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);

before the call to helper_csr*.  If an exception is raised by the helper, this
store to PC will be overwritten by the existing cpu_restore_state in
do_raise_exception_err so that the correct PC value is seen on entry to
do_interrupt.


r~

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

* Re: [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads Michael Clark
@ 2018-05-25 22:38   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-25 22:38 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:15 PM, Michael Clark <mjc@sifive.com> wrote:
> The address calculation for the pending bitfield had
> a copy paste bug. This bug went unnoticed because the Linux
> PLIC driver does not read the pending bitfield, rather it
> reads pending interrupt numbers from the claim register
> and writes acknowledgements back to the claim register.
>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Reported-by: Vincent Siles <vincent.siles@ens-lyon.org>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_plic.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
> index 28e28d932f7c..b81d29faff99 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -215,7 +215,7 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
>      } else if (addr >= plic->pending_base && /* 1 bit per source */
>                 addr < plic->pending_base + (plic->num_sources >> 3))
>      {
> -        uint32_t word = (addr - plic->priority_base) >> 2;
> +        uint32_t word = (addr - plic->pending_base) >> 2;
>          if (RISCV_DEBUG_PLIC) {
>              qemu_log("plic: read pending: word=%d value=%d\n",
>                  word, plic->pending[word]);
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes Michael Clark
@ 2018-05-25 22:40   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-25 22:40 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:15 PM, Michael Clark <mjc@sifive.com> wrote:
> A missing shift made updates to the low order bits
> of timecmp erroneously copy the old low order bits
> into the high order bits of the 64-bit timecmp
> register. Add the missing shift and rename timecmp
> local variables to timecmp_hi and timecmp_lo.
>
> This bug didn't show up as the low order bits are
> usually written first followed by the high order
> bits meaning the high order bits contained an invalid
> value between the timecmp_lo and timecmp_hi update.
>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Co-Authored-by: Johannes Haring <johannes.haring@gmx.net>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_clint.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
> index 0d2fd52487e6..d4c159e93736 100644
> --- a/hw/riscv/sifive_clint.c
> +++ b/hw/riscv/sifive_clint.c
> @@ -146,15 +146,15 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
>              error_report("clint: invalid timecmp hartid: %zu", hartid);
>          } else if ((addr & 0x7) == 0) {
>              /* timecmp_lo */
> -            uint64_t timecmp = env->timecmp;
> +            uint64_t timecmp_hi = env->timecmp >> 32;
>              sifive_clint_write_timecmp(RISCV_CPU(cpu),
> -                timecmp << 32 | (value & 0xFFFFFFFF));
> +                timecmp_hi << 32 | (value & 0xFFFFFFFF));
>              return;
>          } else if ((addr & 0x7) == 4) {
>              /* timecmp_hi */
> -            uint64_t timecmp = env->timecmp;
> +            uint64_t timecmp_lo = env->timecmp;
>              sifive_clint_write_timecmp(RISCV_CPU(cpu),
> -                value << 32 | (timecmp & 0xFFFFFFFF));
> +                value << 32 | (timecmp_lo & 0xFFFFFFFF));
>          } else {
>              error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
>          }
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
@ 2018-05-29 23:32   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:32 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:14 PM, Michael Clark <mjc@sifive.com> wrote:
> The PLIC previously used a mutex to protect against concurrent
> access to the claimed and pending bitfields. Instead of using
> a mutex, we update the bitfields using atomic_cmpxchg.
>
> Rename sifive_plic_num_irqs_pending to sifive_plic_irqs_pending
> and add an early out if any interrupts are pending as the
> count of pending interrupts is not used.
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_plic.c         | 49 +++++++++++++++++++-----------------------
>  include/hw/riscv/sifive_plic.h |  1 -
>  2 files changed, 22 insertions(+), 28 deletions(-)
>
> diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
> index 874de2ebaf77..1af23c76e603 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -81,36 +81,32 @@ static void sifive_plic_print_state(SiFivePLICState *plic)
>      }
>  }
>
> -static
> -void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
> +static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
>  {
> -    qemu_mutex_lock(&plic->lock);
> -    uint32_t word = irq >> 5;
> -    if (pending) {
> -        plic->pending[word] |= (1 << (irq & 31));
> -    } else {
> -        plic->pending[word] &= ~(1 << (irq & 31));
> -    }
> -    qemu_mutex_unlock(&plic->lock);
> +    uint32_t old, new, cmp = atomic_read(a);
> +
> +    do {
> +        old = cmp;
> +        new = (old & ~mask) | (value & mask);
> +        cmp = atomic_cmpxchg(a, old, new);
> +    } while (old != cmp);
> +
> +    return old;
>  }
>
> -static
> -void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
> +static void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool level)
>  {
> -    qemu_mutex_lock(&plic->lock);
> -    uint32_t word = irq >> 5;
> -    if (claimed) {
> -        plic->claimed[word] |= (1 << (irq & 31));
> -    } else {
> -        plic->claimed[word] &= ~(1 << (irq & 31));
> -    }
> -    qemu_mutex_unlock(&plic->lock);
> +    atomic_set_masked(&plic->pending[irq >> 5], 1 << (irq & 31), -!!level);
>  }
>
> -static
> -int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
> +static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level)
>  {
> -    int i, j, count = 0;
> +    atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level);
> +}
> +
> +static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
> +{
> +    int i, j;
>      for (i = 0; i < plic->bitfield_words; i++) {
>          uint32_t pending_enabled_not_claimed =
>              (plic->pending[i] & ~plic->claimed[i]) &
> @@ -123,11 +119,11 @@ int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
>              uint32_t prio = plic->source_priority[irq];
>              int enabled = pending_enabled_not_claimed & (1 << j);
>              if (enabled && prio > plic->target_priority[addrid]) {
> -                count++;
> +                return 1;
>              }
>          }
>      }
> -    return count;
> +    return 0;
>  }
>
>  static void sifive_plic_update(SiFivePLICState *plic)
> @@ -143,7 +139,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
>          if (!env) {
>              continue;
>          }
> -        int level = sifive_plic_num_irqs_pending(plic, addrid) > 0;
> +        int level = sifive_plic_irqs_pending(plic, addrid);
>          switch (mode) {
>          case PLICMode_M:
>              riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
> @@ -440,7 +436,6 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
>      memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
>                            TYPE_SIFIVE_PLIC, plic->aperture_size);
>      parse_hart_config(plic);
> -    qemu_mutex_init(&plic->lock);
>      plic->bitfield_words = (plic->num_sources + 31) >> 5;
>      plic->source_priority = g_new0(uint32_t, plic->num_sources);
>      plic->target_priority = g_new(uint32_t, plic->num_addrs);
> diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
> index 11a5a98df1f9..ff09a288261e 100644
> --- a/include/hw/riscv/sifive_plic.h
> +++ b/include/hw/riscv/sifive_plic.h
> @@ -55,7 +55,6 @@ typedef struct SiFivePLICState {
>      uint32_t *pending;
>      uint32_t *claimed;
>      uint32_t *enable;
> -    QemuMutex lock;
>      qemu_irq *irqs;
>
>      /* config */
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
@ 2018-05-29 23:34   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:34 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:14 PM, Michael Clark <mjc@sifive.com> wrote:
> Use the new CSR read/modify/write interface to implement
> atomic updates to mip/sip.
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair


> ---
>  target/riscv/csr.c | 56 +++++++++++++++++++++++++++---------------------------
>  1 file changed, 28 insertions(+), 28 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index e08f3523d854..631a5ff9f7d8 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -493,25 +493,31 @@ static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
>      return 0;
>  }
>
> -static int read_mip(CPURISCVState *env, int csrno, target_ulong *val)
> -{
> -    *val = atomic_read(&env->mip);
> -    return 0;
> -}
> -
> -static int write_mip(CPURISCVState *env, int csrno, target_ulong val)
> +static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> +                   target_ulong new_value, target_ulong write_mask)
>  {
>      RISCVCPU *cpu = riscv_env_get_cpu(env);
> +    target_ulong mask = write_mask & delegable_ints;
> +    uint32_t old_mip;
> +
> +    /* We can't allow the supervisor to control SEIP as this would allow the
> +     * supervisor to clear a pending external interrupt which will result in
> +     * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
> +     * hardware controlled when a PLIC is attached. This should be an option
> +     * for CPUs with software-delegated Supervisor External Interrupts. */
> +    mask &= ~MIP_SEIP;
> +
> +    if (mask) {
> +        qemu_mutex_lock_iothread();
> +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> +        qemu_mutex_unlock_iothread();
> +    } else {
> +        old_mip = atomic_read(&env->mip);
> +    }
>
> -    /*
> -     * csrs, csrc on mip.SEIP is not decomposable into separate read and
> -     * write steps, so a different implementation is needed
> -     */
> -
> -    qemu_mutex_lock_iothread();
> -    riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP,
> -                         (val & (MIP_SSIP | MIP_STIP)));
> -    qemu_mutex_unlock_iothread();
> +    if (ret_value) {
> +        *ret_value = old_mip;
> +    }
>
>      return 0;
>  }
> @@ -631,17 +637,11 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
>      return 0;
>  }
>
> -static int read_sip(CPURISCVState *env, int csrno, target_ulong *val)
> -{
> -    *val = atomic_read(&env->mip) & env->mideleg;
> -    return 0;
> -}
> -
> -static int write_sip(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)
>  {
> -    target_ulong newval = (atomic_read(&env->mip) & ~env->mideleg)
> -                          | (val & env->mideleg);
> -    return write_mip(env, CSR_MIP, newval);
> +    return rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
> +                   write_mask & env->mideleg);
>  }
>
>  /* Supervisor Protection and Translation */
> @@ -823,7 +823,7 @@ static const riscv_csr_operations csr_ops[0xfff] = {
>      [CSR_MEPC] =                { read_mepc,        write_mepc        },
>      [CSR_MCAUSE] =              { read_mcause,      write_mcause      },
>      [CSR_MBADADDR] =            { read_mbadaddr,    write_mbadaddr    },
> -    [CSR_MIP] =                 { read_mip,         write_mip         },
> +    [CSR_MIP] =                 { NULL,     NULL,     rmw_mip         },
>
>      /* Supervisor Trap Setup */
>      [CSR_SSTATUS] =             { read_sstatus,     write_sstatus     },
> @@ -836,7 +836,7 @@ static const riscv_csr_operations csr_ops[0xfff] = {
>      [CSR_SEPC] =                { read_sepc,        write_sepc        },
>      [CSR_SCAUSE] =              { read_scause,      write_scause      },
>      [CSR_SBADADDR] =            { read_sbadaddr,    write_sbadaddr    },
> -    [CSR_SIP] =                 { read_sip,         write_sip         },
> +    [CSR_SIP] =                 { NULL,     NULL,     rmw_sip         },
>
>      /* Supervisor Protection and Translation */
>      [CSR_SATP] =                { read_satp,        write_satp        },
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty Michael Clark
@ 2018-05-29 23:38   ` Alistair Francis
  0 siblings, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:38 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Richard Henderson,
	Alistair Francis, patches

On Tue, May 22, 2018 at 5:14 PM, Michael Clark <mjc@sifive.com> wrote:
> From: Richard Henderson <richard.henderson@linaro.org>
>
> Modifed from Richard Henderson's patch [1] to integrate
> with the new control and status register implementation.
>
> [1] https://lists.nongnu.org/archive/html/qemu-devel/2018-03/msg07034.html
>
> Note: the f* CSRs already mark mstatus.FS dirty using
> env->mstatus |= mstatus.FS so the bug in the first
> spin of this patch has been fixed in a prior commit.
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Michael Clark <mjc@sifive.com>

It sounds like this should still have Richard's SOB line.

Once that is fixed:

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

>
> Co-authored-by: Richard Henderson <richard.henderson@linaro.org>
> Co-authored-by: Michael Clark <mjc@sifive.com>
> ---
>  target/riscv/csr.c       | 12 ------------
>  target/riscv/translate.c | 40 +++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 39 insertions(+), 13 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 0e6c0c365154..b4452388ff02 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -325,18 +325,6 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
>
>      mstatus = (mstatus & ~mask) | (val & mask);
>
> -    /* Note: this is a workaround for an issue where mstatus.FS
> -       does not report dirty after floating point operations
> -       that modify floating point state. This workaround is
> -       technically compliant with the RISC-V Privileged
> -       specification as it is legal to return only off, or dirty.
> -       at the expense of extra floating point save/restore. */
> -
> -    /* FP is always dirty or off */
> -    if (mstatus & MSTATUS_FS) {
> -        mstatus |= MSTATUS_FS;
> -    }
> -
>      int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
>                  ((mstatus & MSTATUS_XS) == MSTATUS_XS);
>      mstatus = set_field(mstatus, MSTATUS_SD, dirty);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 466b9551cbd9..a980611eb611 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -651,6 +651,31 @@ static void gen_store(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
>      tcg_temp_free(dat);
>  }
>
> +#ifndef CONFIG_USER_ONLY
> +/* The states of mstatus_fs are:
> + * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
> + * We will have already diagnosed disabled state,
> + * and need to turn initial/clean into dirty.
> + */
> +static void mark_fs_dirty(DisasContext *ctx)
> +{
> +    TCGv tmp;
> +    if (ctx->mstatus_fs == MSTATUS_FS) {
> +        return;
> +    }
> +    /* Remember the state change for the rest of the TB.  */
> +    ctx->mstatus_fs = MSTATUS_FS;
> +
> +    tmp = tcg_temp_new();
> +    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));
> +    tcg_temp_free(tmp);
> +}
> +#else
> +static inline void mark_fs_dirty(DisasContext *ctx) { }
> +#endif
> +
>  static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
>          int rs1, target_long imm)
>  {
> @@ -679,6 +704,8 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
>          break;
>      }
>      tcg_temp_free(t0);
> +
> +    mark_fs_dirty(ctx);
>  }
>
>  static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
> @@ -944,6 +971,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>                           int rs1, int rs2, int rm)
>  {
>      TCGv t0 = NULL;
> +    bool fp_output = true;
>
>      if (ctx->mstatus_fs == 0) {
>          goto do_illegal;
> @@ -1006,6 +1034,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          }
>          gen_set_gpr(rd, t0);
>          tcg_temp_free(t0);
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FCVT_W_S:
> @@ -1035,6 +1064,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          }
>          gen_set_gpr(rd, t0);
>          tcg_temp_free(t0);
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FCVT_S_W:
> @@ -1085,6 +1115,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          }
>          gen_set_gpr(rd, t0);
>          tcg_temp_free(t0);
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FMV_S_X:
> @@ -1177,6 +1208,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          }
>          gen_set_gpr(rd, t0);
>          tcg_temp_free(t0);
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FCVT_W_D:
> @@ -1206,6 +1238,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          }
>          gen_set_gpr(rd, t0);
>          tcg_temp_free(t0);
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FCVT_D_W:
> @@ -1253,6 +1286,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>          default:
>              goto do_illegal;
>          }
> +        fp_output = false;
>          break;
>
>      case OPC_RISC_FMV_D_X:
> @@ -1269,7 +1303,11 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>              tcg_temp_free(t0);
>          }
>          gen_exception_illegal(ctx);
> -        break;
> +        return;
> +    }
> +
> +    if (fp_output) {
> +        mark_fs_dirty(ctx);
>      }
>  }
>
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags
  2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
  2018-05-23 12:25   ` Philippe Mathieu-Daudé
@ 2018-05-29 23:40   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:40 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Richard Henderson,
	Alistair Francis, patches

On Tue, May 22, 2018 at 5:14 PM, Michael Clark <mjc@sifive.com> wrote:
> From: Richard Henderson <richard.henderson@linaro.org>
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Reviewed-by: Michael Clark <mjc@sifive.com>

Shouldn't this also have Richard's SOB line?

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair


> ---
>  target/riscv/cpu.h       |  6 +++---
>  target/riscv/translate.c | 10 +++++-----
>  2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 3a3d91447736..242a8fcbe180 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -276,8 +276,8 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
>  target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
>  void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
>
> -#define TB_FLAGS_MMU_MASK  3
> -#define TB_FLAGS_FP_ENABLE MSTATUS_FS
> +#define TB_FLAGS_MMU_MASK   3
> +#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
>
>  static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>                                          target_ulong *cs_base, uint32_t *flags)
> @@ -285,7 +285,7 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      *pc = env->pc;
>      *cs_base = 0;
>  #ifdef CONFIG_USER_ONLY
> -    *flags = TB_FLAGS_FP_ENABLE;
> +    *flags = TB_FLAGS_MSTATUS_FS;
>  #else
>      *flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
>  #endif
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index ee2bbc55b051..466b9551cbd9 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -44,7 +44,7 @@ typedef struct DisasContext {
>      /* pc_succ_insn points to the instruction following base.pc_next */
>      target_ulong pc_succ_insn;
>      uint32_t opcode;
> -    uint32_t flags;
> +    uint32_t mstatus_fs;
>      uint32_t mem_idx;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
> @@ -656,7 +656,7 @@ static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
>  {
>      TCGv t0;
>
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          gen_exception_illegal(ctx);
>          return;
>      }
> @@ -686,7 +686,7 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
>  {
>      TCGv t0;
>
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          gen_exception_illegal(ctx);
>          return;
>      }
> @@ -945,7 +945,7 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
>  {
>      TCGv t0 = NULL;
>
> -    if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
> +    if (ctx->mstatus_fs == 0) {
>          goto do_illegal;
>      }
>
> @@ -1810,8 +1810,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      DisasContext *ctx = container_of(dcbase, DisasContext, base);
>
>      ctx->pc_succ_insn = ctx->base.pc_first;
> -    ctx->flags = ctx->base.tb->flags;
>      ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
> +    ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
>      ctx->frm = -1;  /* unknown rounding mode */
>  }
>
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
  2018-05-23 12:36   ` Philippe Mathieu-Daudé
@ 2018-05-29 23:43   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:43 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:15 PM, Michael Clark <mjc@sifive.com> wrote:
> * Add riscv prefix to raise_exception function
> * Add riscv prefix to CSR read/write functions
> * Add riscv prefix to signal handler function
> * Add riscv prefix to get fflags function
> * Remove redundant declaration of riscv_cpu_init
>   and rename cpu_riscv_init to riscv_cpu_init
> * rename riscv_set_mode to riscv_cpu_set_mode
>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  linux-user/riscv/signal.c |  4 ++--
>  target/riscv/cpu.h        | 21 ++++++++++-----------
>  target/riscv/cpu_helper.c | 10 +++++-----
>  target/riscv/csr.c        |  8 ++++----
>  target/riscv/fpu_helper.c |  6 +++---
>  target/riscv/op_helper.c  | 28 ++++++++++++++--------------
>  6 files changed, 38 insertions(+), 39 deletions(-)
>
> diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
> index ef599e319a10..f03bc7212b49 100644
> --- a/linux-user/riscv/signal.c
> +++ b/linux-user/riscv/signal.c
> @@ -84,7 +84,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
>          __put_user(env->fpr[i], &sc->fpr[i]);
>      }
>
> -    uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
> +    uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
>      __put_user(fcsr, &sc->fcsr);
>  }
>
> @@ -160,7 +160,7 @@ static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
>
>      uint32_t fcsr;
>      __get_user(fcsr, &sc->fcsr);
> -    csr_write_helper(env, fcsr, CSR_FCSR);
> +    riscv_csr_write(env, CSR_FCSR, fcsr);
>  }
>
>  static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 1ade90d23bbc..d6bb3136db18 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -257,7 +257,7 @@ char *riscv_isa_string(RISCVCPU *cpu);
>  void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>
>  #define cpu_init(cpu_model) cpu_generic_init(TYPE_RISCV_CPU, cpu_model)
> -#define cpu_signal_handler cpu_riscv_signal_handler
> +#define cpu_signal_handler riscv_cpu_signal_handler
>  #define cpu_list riscv_cpu_list
>  #define cpu_mmu_index riscv_cpu_mmu_index
>
> @@ -265,16 +265,15 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  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 */
>  #endif
> -void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
>
>  void riscv_translate_init(void);
> -RISCVCPU *cpu_riscv_init(const char *cpu_model);
> -int cpu_riscv_signal_handler(int host_signum, void *pinfo, void *puc);
> -void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
> -                                          uint32_t exception, uintptr_t pc);
> +int riscv_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
> +void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
> +                                         uint32_t exception, uintptr_t pc);
>
> -target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
> -void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>
>  #define TB_FLAGS_MMU_MASK   3
>  #define TB_FLAGS_MSTATUS_FS MSTATUS_FS
> @@ -294,13 +293,13 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>  int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
>                  target_ulong new_value, target_ulong write_mask);
>
> -static inline void csr_write_helper(CPURISCVState *env, target_ulong val,
> -                                    int csrno)
> +static inline void riscv_csr_write(CPURISCVState *env, int csrno,
> +                                   target_ulong val)
>  {
>      riscv_csrrw(env, csrno, NULL, val, -1);
>  }
>
> -static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
> +static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
>  {
>      target_ulong val = 0;
>      riscv_csrrw(env, csrno, &val, 0, 0);
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 69592c037042..b4bbf7a9fa0a 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -93,7 +93,7 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
>      return old;
>  }
>
> -void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
>  {
>      if (newpriv > PRV_M) {
>          g_assert_not_reached();
> @@ -366,7 +366,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>          g_assert_not_reached();
>      }
>      env->badaddr = addr;
> -    do_raise_exception_err(env, cs->exception_index, retaddr);
> +    riscv_raise_exception(env, cs->exception_index, retaddr);
>  }
>
>  /* called by qemu's softmmu to fill the qemu tlb */
> @@ -378,7 +378,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
>      if (ret == TRANSLATE_FAIL) {
>          RISCVCPU *cpu = RISCV_CPU(cs);
>          CPURISCVState *env = &cpu->env;
> -        do_raise_exception_err(env, cs->exception_index, retaddr);
> +        riscv_raise_exception(env, cs->exception_index, retaddr);
>      }
>  }
>
> @@ -530,7 +530,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          s = set_field(s, MSTATUS_SPP, env->priv);
>          s = set_field(s, MSTATUS_SIE, 0);
>          env->mstatus = s;
> -        riscv_set_mode(env, PRV_S);
> +        riscv_cpu_set_mode(env, PRV_S);
>      } else {
>          /* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
>          env->pc = env->mtvec;
> @@ -555,7 +555,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>          s = set_field(s, MSTATUS_MPP, env->priv);
>          s = set_field(s, MSTATUS_MIE, 0);
>          env->mstatus = s;
> -        riscv_set_mode(env, PRV_M);
> +        riscv_cpu_set_mode(env, PRV_M);
>      }
>      /* TODO yield load reservation  */
>  #endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 0f886e04b130..45e33d876034 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -95,7 +95,7 @@ static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
>          return -1;
>      }
>  #endif
> -    *val = cpu_riscv_get_fflags(env);
> +    *val = riscv_cpu_get_fflags(env);
>      return 0;
>  }
>
> @@ -107,7 +107,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
>      }
>      env->mstatus |= MSTATUS_FS;
>  #endif
> -    cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
> +    riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
>      return 0;
>  }
>
> @@ -141,7 +141,7 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
>          return -1;
>      }
>  #endif
> -    *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
> +    *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
>          | (env->frm << FSR_RD_SHIFT);
>      return 0;
>  }
> @@ -155,7 +155,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
>      env->mstatus |= MSTATUS_FS;
>  #endif
>      env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
> -    cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
> +    riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
>      return 0;
>  }
>
> diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
> index fdb87d8d82cb..1452a153f261 100644
> --- a/target/riscv/fpu_helper.c
> +++ b/target/riscv/fpu_helper.c
> @@ -23,7 +23,7 @@
>  #include "exec/exec-all.h"
>  #include "exec/helper-proto.h"
>
> -target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
>  {
>      int soft = get_float_exception_flags(&env->fp_status);
>      target_ulong hard = 0;
> @@ -37,7 +37,7 @@ target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
>      return hard;
>  }
>
> -void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong hard)
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
>  {
>      int soft = 0;
>
> @@ -74,7 +74,7 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
>          softrm = float_round_ties_away;
>          break;
>      default:
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>
>      set_float_rounding_mode(softrm, &env->fp_status);
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 77c79ba36e0b..b7dc18a41e21 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -25,7 +25,7 @@
>  #include "exec/helper-proto.h"
>
>  /* Exceptions processing helpers */
> -void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
> +void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
>                                            uint32_t exception, uintptr_t pc)
>  {
>      CPUState *cs = CPU(riscv_env_get_cpu(env));
> @@ -36,7 +36,7 @@ void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
>
>  void helper_raise_exception(CPURISCVState *env, uint32_t exception)
>  {
> -    do_raise_exception_err(env, exception, 0);
> +    riscv_raise_exception(env, exception, 0);
>  }
>
>  target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
> @@ -44,7 +44,7 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, src, -1) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -54,7 +54,7 @@ target_ulong helper_csrrs(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -64,7 +64,7 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  {
>      target_ulong val = 0;
>      if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>      return val;
>  }
> @@ -74,17 +74,17 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
>  target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  {
>      if (!(env->priv >= PRV_S)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>
>      target_ulong retpc = env->sepc;
>      if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> -        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>
>      if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
>          get_field(env->mstatus, MSTATUS_TSR)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>
>      target_ulong mstatus = env->mstatus;
> @@ -95,7 +95,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          get_field(mstatus, MSTATUS_SPIE));
>      mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
> -    riscv_set_mode(env, prev_priv);
> +    riscv_cpu_set_mode(env, prev_priv);
>      env->mstatus = mstatus;
>
>      return retpc;
> @@ -104,12 +104,12 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>  {
>      if (!(env->priv >= PRV_M)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      }
>
>      target_ulong retpc = env->mepc;
>      if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> -        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
>      }
>
>      target_ulong mstatus = env->mstatus;
> @@ -120,7 +120,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
>          get_field(mstatus, MSTATUS_MPIE));
>      mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
>      mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
> -    riscv_set_mode(env, prev_priv);
> +    riscv_cpu_set_mode(env, prev_priv);
>      env->mstatus = mstatus;
>
>      return retpc;
> @@ -133,7 +133,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)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          cs->halted = 1;
>          cs->exception_index = EXCP_HLT;
> @@ -148,7 +148,7 @@ void helper_tlb_flush(CPURISCVState *env)
>      if (env->priv == PRV_S &&
>          env->priv_ver >= PRIV_VERSION_1_10_0 &&
>          get_field(env->mstatus, MSTATUS_TVM)) {
> -        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
>      } else {
>          tlb_flush(cs);
>      }
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
  2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC Michael Clark
  2018-05-23 12:37   ` Philippe Mathieu-Daudé
@ 2018-05-29 23:47   ` Alistair Francis
  1 sibling, 0 replies; 61+ messages in thread
From: Alistair Francis @ 2018-05-29 23:47 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis, patches

On Tue, May 22, 2018 at 5:15 PM, Michael Clark <mjc@sifive.com> wrote:
> The mode variable only uses the lower 4-bits (M,H,S,U) so
> replace the GCC specific __builtin_popcount with ctpop8.
>
> Cc: Palmer Dabbelt <palmer@sifive.com>
> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Cc: Alistair Francis <Alistair.Francis@wdc.com>
> Signed-off-by: Michael Clark <mjc@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_plic.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
> index b267ff88902d..dc6f4924e282 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -383,7 +383,7 @@ static void parse_hart_config(SiFivePLICState *plic)
>      p = plic->hart_config;
>      while ((c = *p++)) {
>          if (c == ',') {
> -            addrid += __builtin_popcount(modes);
> +            addrid += ctpop8(modes);
>              modes = 0;
>              hartid++;
>          } else {
> @@ -397,7 +397,7 @@ static void parse_hart_config(SiFivePLICState *plic)
>          }
>      }
>      if (modes) {
> -        addrid += __builtin_popcount(modes);
> +        addrid += ctpop8(modes);
>      }
>      hartid++;
>
> --
> 2.7.0
>
>

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

end of thread, other threads:[~2018-05-29 23:48 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-23  0:14 [Qemu-devel] [PATCH v1 00/30] QEMU 2.13 RISC-V updates Michael Clark
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 01/30] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
2018-05-25 15:07   ` Richard Henderson
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 02/30] RISC-V: Improve page table walker spec compliance Michael Clark
2018-05-23 22:31   ` Michael Clark
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 03/30] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
2018-05-29 23:32   ` Alistair Francis
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 04/30] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
2018-05-25 15:15   ` Richard Henderson
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 05/30] RISC-V: Allow setting and clearing multiple irqs Michael Clark
2018-05-23 23:55   ` Alistair Francis
2018-05-25 15:19   ` Richard Henderson
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 06/30] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
2018-05-23 12:23   ` Philippe Mathieu-Daudé
2018-05-25 15:20   ` Richard Henderson
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 07/30] RISC-V: Update CSR and interrupt definitions Michael Clark
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 08/30] RISC-V: Implement modular CSR helper interface Michael Clark
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 09/30] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
2018-05-29 23:34   ` Alistair Francis
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 10/30] RISC-V: Implement existential predicates for CSRs Michael Clark
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 11/30] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
2018-05-23 12:25   ` Philippe Mathieu-Daudé
2018-05-29 23:40   ` Alistair Francis
2018-05-23  0:14 ` [Qemu-devel] [PATCH v1 12/30] RISC-V: Mark mstatus.fs dirty Michael Clark
2018-05-29 23:38   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 13/30] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
2018-05-23 12:26   ` Philippe Mathieu-Daudé
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 14/30] RISC-V: Add public API for the CSR dispatch table Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 15/30] RISC-V: Add hartid and \n to interrupt logging Michael Clark
2018-05-23 12:33   ` Philippe Mathieu-Daudé
2018-05-24 22:47     ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 16/30] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
2018-05-23 12:36   ` Philippe Mathieu-Daudé
2018-05-29 23:43   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 17/30] RISC-V: Replace __builtin_popcount with ctpop8 in PLIC Michael Clark
2018-05-23 12:37   ` Philippe Mathieu-Daudé
2018-05-29 23:47   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 18/30] RISC-V: Add missing free for plic_hart_config Michael Clark
2018-05-23 12:40   ` Philippe Mathieu-Daudé
2018-05-24 22:43     ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 19/30] RISC-V: Allow interrupt controllers to claim interrupts Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 20/30] RISC-V: Add misa to DisasContext Michael Clark
2018-05-23 12:42   ` Philippe Mathieu-Daudé
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 21/30] RISC-V: Add misa.MAFD checks to translate Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 22/30] RISC-V: Add misa runtime write support Michael Clark
2018-05-25 18:53   ` Richard Henderson
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 23/30] RISC-V: Fix CLINT timecmp low 32-bit writes Michael Clark
2018-05-25 22:40   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 24/30] RISC-V: Fix PLIC pending bitfield reads Michael Clark
2018-05-25 22:38   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 25/30] RISC-V: Enable second UART on sifive_e and sifive_u Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 26/30] RISC-V: Remove unnecessary disassembler constraints Michael Clark
2018-05-24 22:45   ` Alistair Francis
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 27/30] elf: Add RISC-V PSABI ELF header defines Michael Clark
2018-05-23  6:44   ` Laurent Vivier
2018-05-25  7:17     ` Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 28/30] RISC-V: linux-user support for RVE ABI Michael Clark
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 29/30] RISC-V: Don't add NULL bootargs to device-tree Michael Clark
2018-05-23 12:45   ` Philippe Mathieu-Daudé
2018-05-23  0:15 ` [Qemu-devel] [PATCH v1 30/30] RISC-V: Support separate firmware and kernel payload Michael Clark
2018-05-23 12:49   ` Philippe Mathieu-Daudé

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.