All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
@ 2018-04-25 23:45 Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values Michael Clark
                   ` (35 more replies)
  0 siblings, 36 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, Richard Henderson,
	Peter Maydell

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 focuses on
correct modelling of Privileged ISA v1.10. Earlier versions
of the code had many unimplemented warnings in the control
and status register code. The version submitted upstream
replaced calls to exit with illegal instruction traps. The
changes in this series focus on implementing correct
behaviour, which in some cases is to ignore writes instead
of trapping, and in other cases traps are generated based
on the presence of CPU features or register settings such
as misa.S and mstatus.TSR/TW/TVM. Several other bugs in
the RISC-V QEMU issue tracker are addresssed.

The branch for this patch series can be found here:

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

The RISC-V QEMU issues that are not yet resolved upstream:

- https://github.com/riscv/riscv-qemu/issues

Summary of changes

* Implemented TSR, TW and TVM for privileged ISA v1.10
* Update floating-point to correctly mark mstatus.FS dirty.
* Implements WARL behavior for CSRs that don't support writes
  * Past behavior of raising traps was non-conformant
    with the RISC-V Privileged ISA Specition v1.10.
* Sets mtval/stval to zero on exceptions without addresses
  * Past behavior of leaving the last value was non-conformant
    with the RISC-V Privileged ISA Specition v1.10. mtval/stval
    must be set on all exceptions; to zero if not supported.
* 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%.
* Honour privileged ISA v1.10 counter enable CSRs.
* 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 .
* Make ROMs read-only and implement device-tree size checks
  * Uses memory_region_init_rom and rom_add_blob_fixed_as
* Adds hexidecimal instruction bytes to disassembly output.
* Several code cleanups
  * Replacing hard-coded constants with enums
  * Dead-code elimination

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): pending
* riscv-tests: pass
* checkpatch: pass

Changelog

v8

* Use riscv prefix consistently on all cpu helpers
* Add hartid and \n to qemu_log in interrupt logging
* Add missing return statement in gdbstub.c
* Implemented TSR, TW and TVM for privileged ISA v1.10
* Merged Richard Henderson's mstatus.fs dirty fix
* Dropped mstatus.FS workaround
* Implemented traps for s* CSR access on CPUs without S mode
* Implemented traps for pmp* CSR access for CPUs without PMP
* Made local interrupt delivery use atomic updates
* Implemented modular CSR interface supporting atomic accesses
* Implemented privileged ISA v1.10 counter enable CSRs
* Fixed mask for sstatus.mxr field when priv ISA <= v1.9.1
* Fixed User/Supervisor access bug in page table walker refactor
* Updated physical address bits to match the priv ISA specification
* Use memory_region_init_rom and rom_add_blob_fixed_as for mask roms

v7

* Fix typo in mstatus.FS workaround comment
* Remove privilege mode from mstatus.mxr page protection check
* Shift class initialization boilerplate patch hunk to correct patch
* Fix typo in include instruction hex in disassembly commit message

v6

* Added workaround for critical mstatus.FS MTTCG bug
* Added fix for incorrect disassembly of addiw

v5

* Dropped fix for memory allocation bug in riscv_isa_string
* Dropped Hold rcu_read_lock when accessing memory

v4

* Added fix for memory allocation bug in riscv_isa_string
* Trivial fix to remove erroneous comment from translate.c

v3

* Refactor rcu_read_lock in PTE update to use single unlock
* Make mstatus.mxr take effect regardless of privilege mode
* Remove unnecessary class init from riscv_hart
* Set mtval/stval to zero on exceptions without addresses

v2

* Remove unused class boilerplate retains qom parent_obj
* Convert cpu definition towards future model
* Honor mstatus.mxr flag in page table walker

v1

* Initial post merge cleanup patch series

Michael Clark (33):
  RISC-V: Replace hardcoded constants with enum values
  RISC-V: Make virt board description match spike
  RISC-V: Use ROM base address and size from memmap
  RISC-V: Remove identity_translate from load_elf
  RISC-V: Remove unused class definitions
  RISC-V: Include instruction hex in disassembly
  RISC-V: Make some header guards more specific
  RISC-V: Make virt header comment title consistent
  RISC-V: Remove EM_RISCV ELF_MACHINE indirection
  RISC-V: Remove erroneous comment from translate.c
  RISC-V: Mark ROM read-only after copying in code
  RISC-V: Update address bits to support sv39 and sv48
  RISC-V: Improve page table walker spec compliance
  RISC-V: Update E order and I extension order
  RISC-V: Hardwire satp to 0 for no-mmu case
  RISC-V: Make mtvec/stvec ignore vectored traps
  RISC-V: No traps on writes to misa,minstret,mcycle
  RISC-V: Clear mtval/stval on exceptions without info
  RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
  RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
  RISC-V: Add mcycle/minstret support for -icount auto
  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

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

 disas/riscv.c                           |  39 +-
 hw/riscv/riscv_hart.c                   |   6 -
 hw/riscv/sifive_clint.c                 |  17 +-
 hw/riscv/sifive_e.c                     |  54 +-
 hw/riscv/sifive_plic.c                  |  40 +-
 hw/riscv/sifive_u.c                     |  86 ++--
 hw/riscv/spike.c                        |  99 ++--
 hw/riscv/virt.c                         |  80 +--
 include/hw/riscv/sifive_clint.h         |   4 +
 include/hw/riscv/sifive_e.h             |   5 -
 include/hw/riscv/sifive_plic.h          |   1 -
 include/hw/riscv/sifive_u.h             |   9 +-
 include/hw/riscv/spike.h                |  15 +-
 include/hw/riscv/virt.h                 |  13 +-
 linux-user/signal.c                     |   4 +-
 target/riscv/Makefile.objs              |   2 +-
 target/riscv/cpu.c                      |   8 +-
 target/riscv/cpu.h                      |  84 +--
 target/riscv/cpu_bits.h                 | 690 +++++++++++++------------
 target/riscv/{helper.c => cpu_helper.c} | 173 ++++---
 target/riscv/csr.c                      | 871 ++++++++++++++++++++++++++++++++
 target/riscv/fpu_helper.c               |   6 +-
 target/riscv/gdbstub.c                  |  10 +-
 target/riscv/op_helper.c                | 613 ++--------------------
 target/riscv/translate.c                |  53 +-
 25 files changed, 1700 insertions(+), 1282 deletions(-)
 rename target/riscv/{helper.c => cpu_helper.c} (73%)
 create mode 100644 target/riscv/csr.c

-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 16:37   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 02/35] RISC-V: Make virt board description match spike Michael Clark
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

The RISC-V device-tree code has a number of hard-coded
constants and this change moves them into header enums.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/sifive_clint.c         | 9 +++------
 hw/riscv/sifive_u.c             | 6 ++++--
 hw/riscv/spike.c                | 6 ++++--
 hw/riscv/virt.c                 | 6 ++++--
 include/hw/riscv/sifive_clint.h | 4 ++++
 include/hw/riscv/sifive_u.h     | 4 ++++
 include/hw/riscv/spike.h        | 4 ++++
 include/hw/riscv/virt.h         | 4 ++++
 8 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 4893453..7cc606e 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/riscv/sifive_clint.c
@@ -26,13 +26,10 @@
 #include "hw/riscv/sifive_clint.h"
 #include "qemu/timer.h"
 
-/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */
-#define TIMER_FREQ (10 * 1000 * 1000)
-
 static uint64_t cpu_riscv_read_rtc(void)
 {
-    return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
-                    NANOSECONDS_PER_SECOND);
+    return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+        SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);
 }
 
 /*
@@ -59,7 +56,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
     diff = cpu->env.timecmp - rtc_r;
     /* back to ns (note args switched in muldiv64) */
     next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-        muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ);
+        muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ);
     timer_mod(cpu->env.timer, next);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 1c2deef..f3f7615 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -122,7 +122,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
     g_free(nodename);
 
     qemu_fdt_add_subnode(fdt, "/cpus");
-    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
+    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
+        SIFIVE_CLINT_TIMEBASE_FREQ);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
 
@@ -131,7 +132,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
         char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
         char *isa = riscv_isa_string(&s->soc.harts[cpu]);
         qemu_fdt_add_subnode(fdt, nodename);
-        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 1000000000);
+        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
+                              SIFIVE_U_CLOCK_FREQ);
         qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
         qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
         qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 2d1f114..4c233ec 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -115,7 +115,8 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
     g_free(nodename);
 
     qemu_fdt_add_subnode(fdt, "/cpus");
-    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
+    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
+        SIFIVE_CLINT_TIMEBASE_FREQ);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
 
@@ -124,7 +125,8 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
         char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
         char *isa = riscv_isa_string(&s->soc.harts[cpu]);
         qemu_fdt_add_subnode(fdt, nodename);
-        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 1000000000);
+        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
+                              SPIKE_CLOCK_FREQ);
         qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
         qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
         qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e2c214e..86a86c9 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -145,7 +145,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
     g_free(nodename);
 
     qemu_fdt_add_subnode(fdt, "/cpus");
-    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
+    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
+                          SIFIVE_CLINT_TIMEBASE_FREQ);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
     qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
 
@@ -155,7 +156,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
         char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
         char *isa = riscv_isa_string(&s->soc.harts[cpu]);
         qemu_fdt_add_subnode(fdt, nodename);
-        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 1000000000);
+        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
+                              VIRT_CLOCK_FREQ);
         qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
         qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
         qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h
index aaa2a58..e2865be 100644
--- a/include/hw/riscv/sifive_clint.h
+++ b/include/hw/riscv/sifive_clint.h
@@ -47,4 +47,8 @@ enum {
     SIFIVE_TIME_BASE    = 0xBFF8
 };
 
+enum {
+    SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
+};
+
 #endif
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 662e8a1..be38aa0 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -50,6 +50,10 @@ enum {
     SIFIVE_U_UART1_IRQ = 4
 };
 
+enum {
+    SIFIVE_U_CLOCK_FREQ = 1000000000
+};
+
 #define SIFIVE_U_PLIC_HART_CONFIG "MS"
 #define SIFIVE_U_PLIC_NUM_SOURCES 127
 #define SIFIVE_U_PLIC_NUM_PRIORITIES 7
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index cb55a14..d85a64e 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -42,6 +42,10 @@ enum {
     SPIKE_DRAM
 };
 
+enum {
+    SPIKE_CLOCK_FREQ = 1000000000
+};
+
 #if defined(TARGET_RISCV32)
 #define SPIKE_V1_09_1_CPU TYPE_RISCV_CPU_RV32GCSU_V1_09_1
 #define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_RV32GCSU_V1_10_0
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 7525647..2fbe808 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -55,6 +55,10 @@ enum {
     VIRTIO_NDEV = 10
 };
 
+enum {
+    VIRT_CLOCK_FREQ = 1000000000
+};
+
 #define VIRT_PLIC_HART_CONFIG "MS"
 #define VIRT_PLIC_NUM_SOURCES 127
 #define VIRT_PLIC_NUM_PRIORITIES 7
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 02/35] RISC-V: Make virt board description match spike
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 03/35] RISC-V: Use ROM base address and size from memmap Michael Clark
                   ` (33 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

This makes 'qemu-system-riscv64 -machine help' output more tidy
and consistent.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/virt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 86a86c9..dc74fd6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -407,7 +407,7 @@ static const TypeInfo riscv_virt_board_device = {
 
 static void riscv_virt_board_machine_init(MachineClass *mc)
 {
-    mc->desc = "RISC-V VirtIO Board (Privileged spec v1.10)";
+    mc->desc = "RISC-V VirtIO Board (Privileged ISA v1.10)";
     mc->init = riscv_virt_board_init;
     mc->max_cpus = 8; /* hardcoded limit in BBL */
 }
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 03/35] RISC-V: Use ROM base address and size from memmap
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 02/35] RISC-V: Make virt board description match spike Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 04/35] RISC-V: Remove identity_translate from load_elf Michael Clark
                   ` (32 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

Another case of replacing hard coded constants, this time
referring to the definition in the virt machine's memmap.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/virt.c         | 4 ++--
 include/hw/riscv/virt.h | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index dc74fd6..ac0106e 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -341,11 +341,11 @@ static void riscv_virt_board_init(MachineState *machine)
     };
 
     /* copy in the reset vector */
-    copy_le32_to_phys(ROM_BASE, reset_vec, sizeof(reset_vec));
+    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec, sizeof(reset_vec));
 
     /* copy in the device tree */
     qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
-    cpu_physical_memory_write(ROM_BASE + sizeof(reset_vec),
+    cpu_physical_memory_write(memmap[VIRT_MROM].base + sizeof(reset_vec),
         s->fdt, s->fdt_size);
 
     /* create PLIC hart topology configuration string */
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 2fbe808..655e85d 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -23,8 +23,6 @@
 #define VIRT(obj) \
     OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
 
-enum { ROM_BASE = 0x1000 };
-
 typedef struct {
     /*< private >*/
     SysBusDevice parent_obj;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 04/35] RISC-V: Remove identity_translate from load_elf
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (2 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 03/35] RISC-V: Use ROM base address and size from memmap Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 05/35] RISC-V: Remove unused class definitions Michael Clark
                   ` (31 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

When load_elf is called with NULL as an argument to the
address translate callback, it does an identity translation.
This commit removes the redundant identity_translate callback.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/sifive_e.c | 7 +------
 hw/riscv/sifive_u.c | 7 +------
 hw/riscv/spike.c    | 7 +------
 hw/riscv/virt.c     | 7 +------
 4 files changed, 4 insertions(+), 24 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 19eca36..09c9d49 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -82,16 +82,11 @@ static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
     }
 }
 
-static uint64_t identity_translate(void *opaque, uint64_t addr)
-{
-    return addr;
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
 
-    if (load_elf(kernel_filename, identity_translate, NULL,
+    if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
                  0, ELF_MACHINE, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index f3f7615..6116c38 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -68,16 +68,11 @@ static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
     }
 }
 
-static uint64_t identity_translate(void *opaque, uint64_t addr)
-{
-    return addr;
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
 
-    if (load_elf(kernel_filename, identity_translate, NULL,
+    if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
                  0, ELF_MACHINE, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 4c233ec..7710333 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -59,16 +59,11 @@ static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
     }
 }
 
-static uint64_t identity_translate(void *opaque, uint64_t addr)
-{
-    return addr;
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
 
-    if (load_elf_ram_sym(kernel_filename, identity_translate, NULL,
+    if (load_elf_ram_sym(kernel_filename, NULL, NULL,
             &kernel_entry, NULL, &kernel_high, 0, ELF_MACHINE, 1, 0,
             NULL, true, htif_symbol_callback) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ac0106e..6311675 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -62,16 +62,11 @@ static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
     }
 }
 
-static uint64_t identity_translate(void *opaque, uint64_t addr)
-{
-    return addr;
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
 
-    if (load_elf(kernel_filename, identity_translate, NULL,
+    if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
                  0, ELF_MACHINE, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 05/35] RISC-V: Remove unused class definitions
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (3 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 04/35] RISC-V: Remove identity_translate from load_elf Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly Michael Clark
                   ` (30 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

Removes a whole lot of unnecessary boilerplate code. Machines
don't need to be objects. The expansion of the SOC object model
for the RISC-V machines will happen in the future as SiFive
plans to add their FE310 and FU540 SOCs to QEMU. However, it
seems that this present boilerplate is complete unnecessary.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/riscv_hart.c       |  6 ------
 hw/riscv/sifive_e.c         | 25 -------------------------
 hw/riscv/sifive_u.c         | 25 -------------------------
 hw/riscv/spike.c            | 20 --------------------
 hw/riscv/virt.c             | 25 -------------------------
 include/hw/riscv/sifive_e.h |  5 -----
 include/hw/riscv/sifive_u.h |  5 -----
 include/hw/riscv/spike.h    |  7 -------
 include/hw/riscv/virt.h     |  5 -----
 9 files changed, 123 deletions(-)

diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 14e3c18..75ba7ed 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -68,16 +68,10 @@ static void riscv_harts_class_init(ObjectClass *klass, void *data)
     dc->realize = riscv_harts_realize;
 }
 
-static void riscv_harts_init(Object *obj)
-{
-    /* RISCVHartArrayState *s = SIFIVE_COREPLEX(obj); */
-}
-
 static const TypeInfo riscv_harts_info = {
     .name          = TYPE_RISCV_HART_ARRAY,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(RISCVHartArrayState),
-    .instance_init = riscv_harts_init,
     .class_init    = riscv_harts_class_init,
 };
 
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 09c9d49..4872b68 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -194,24 +194,6 @@ static void riscv_sifive_e_init(MachineState *machine)
     }
 }
 
-static int riscv_sifive_e_sysbus_device_init(SysBusDevice *sysbusdev)
-{
-    return 0;
-}
-
-static void riscv_sifive_e_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    k->init = riscv_sifive_e_sysbus_device_init;
-}
-
-static const TypeInfo riscv_sifive_e_device = {
-    .name          = TYPE_SIFIVE_E,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SiFiveEState),
-    .class_init    = riscv_sifive_e_class_init,
-};
-
 static void riscv_sifive_e_machine_init(MachineClass *mc)
 {
     mc->desc = "RISC-V Board compatible with SiFive E SDK";
@@ -220,10 +202,3 @@ static void riscv_sifive_e_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init)
-
-static void riscv_sifive_e_register_types(void)
-{
-    type_register_static(&riscv_sifive_e_device);
-}
-
-type_init(riscv_sifive_e_register_types);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 6116c38..2412b5d 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -301,31 +301,6 @@ static void riscv_sifive_u_init(MachineState *machine)
         SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
 }
 
-static int riscv_sifive_u_sysbus_device_init(SysBusDevice *sysbusdev)
-{
-    return 0;
-}
-
-static void riscv_sifive_u_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    k->init = riscv_sifive_u_sysbus_device_init;
-}
-
-static const TypeInfo riscv_sifive_u_device = {
-    .name          = TYPE_SIFIVE_U,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SiFiveUState),
-    .class_init    = riscv_sifive_u_class_init,
-};
-
-static void riscv_sifive_u_register_types(void)
-{
-    type_register_static(&riscv_sifive_u_device);
-}
-
-type_init(riscv_sifive_u_register_types);
-
 static void riscv_sifive_u_machine_init(MachineClass *mc)
 {
     mc->desc = "RISC-V Board compatible with SiFive U SDK";
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 7710333..f370f12 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -334,18 +334,6 @@ static void spike_v1_09_1_board_init(MachineState *machine)
         smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
 }
 
-static const TypeInfo spike_v_1_09_1_device = {
-    .name          = TYPE_RISCV_SPIKE_V1_09_1_BOARD,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpikeState),
-};
-
-static const TypeInfo spike_v_1_10_0_device = {
-    .name          = TYPE_RISCV_SPIKE_V1_10_0_BOARD,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpikeState),
-};
-
 static void spike_v1_09_1_machine_init(MachineClass *mc)
 {
     mc->desc = "RISC-V Spike Board (Privileged ISA v1.9.1)";
@@ -363,11 +351,3 @@ static void spike_v1_10_0_machine_init(MachineClass *mc)
 
 DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init)
 DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init)
-
-static void riscv_spike_board_register_types(void)
-{
-    type_register_static(&spike_v_1_09_1_device);
-    type_register_static(&spike_v_1_10_0_device);
-}
-
-type_init(riscv_spike_board_register_types);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 6311675..782996c 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -382,24 +382,6 @@ static void riscv_virt_board_init(MachineState *machine)
         serial_hds[0], DEVICE_LITTLE_ENDIAN);
 }
 
-static int riscv_virt_board_sysbus_device_init(SysBusDevice *sysbusdev)
-{
-    return 0;
-}
-
-static void riscv_virt_board_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    k->init = riscv_virt_board_sysbus_device_init;
-}
-
-static const TypeInfo riscv_virt_board_device = {
-    .name          = TYPE_RISCV_VIRT_BOARD,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(RISCVVirtState),
-    .class_init    = riscv_virt_board_class_init,
-};
-
 static void riscv_virt_board_machine_init(MachineClass *mc)
 {
     mc->desc = "RISC-V VirtIO Board (Privileged ISA v1.10)";
@@ -408,10 +390,3 @@ static void riscv_virt_board_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE("virt", riscv_virt_board_machine_init)
-
-static void riscv_virt_board_register_types(void)
-{
-    type_register_static(&riscv_virt_board_device);
-}
-
-type_init(riscv_virt_board_register_types);
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
index 0aebc57..12ad6d2 100644
--- a/include/hw/riscv/sifive_e.h
+++ b/include/hw/riscv/sifive_e.h
@@ -19,11 +19,6 @@
 #ifndef HW_SIFIVE_E_H
 #define HW_SIFIVE_E_H
 
-#define TYPE_SIFIVE_E "riscv.sifive_e"
-
-#define SIFIVE_E(obj) \
-    OBJECT_CHECK(SiFiveEState, (obj), TYPE_SIFIVE_E)
-
 typedef struct SiFiveEState {
     /*< private >*/
     SysBusDevice parent_obj;
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index be38aa0..94a3905 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -19,11 +19,6 @@
 #ifndef HW_SIFIVE_U_H
 #define HW_SIFIVE_U_H
 
-#define TYPE_SIFIVE_U "riscv.sifive_u"
-
-#define SIFIVE_U(obj) \
-    OBJECT_CHECK(SiFiveUState, (obj), TYPE_SIFIVE_U)
-
 typedef struct SiFiveUState {
     /*< private >*/
     SysBusDevice parent_obj;
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index d85a64e..8410430 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -19,12 +19,6 @@
 #ifndef HW_SPIKE_H
 #define HW_SPIKE_H
 
-#define TYPE_RISCV_SPIKE_V1_09_1_BOARD "riscv.spike_v1_9_1"
-#define TYPE_RISCV_SPIKE_V1_10_0_BOARD "riscv.spike_v1_10"
-
-#define SPIKE(obj) \
-    OBJECT_CHECK(SpikeState, (obj), TYPE_RISCV_SPIKE_BOARD)
-
 typedef struct {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -35,7 +29,6 @@ typedef struct {
     int fdt_size;
 } SpikeState;
 
-
 enum {
     SPIKE_MROM,
     SPIKE_CLINT,
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 655e85d..b91a412 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -19,10 +19,6 @@
 #ifndef HW_VIRT_H
 #define HW_VIRT_H
 
-#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
-#define VIRT(obj) \
-    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
-
 typedef struct {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -45,7 +41,6 @@ enum {
     VIRT_DRAM
 };
 
-
 enum {
     UART0_IRQ = 10,
     VIRTIO_IRQ = 1, /* 1 to 8 */
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (4 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 05/35] RISC-V: Remove unused class definitions Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:05   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific Michael Clark
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

This was added to help debug issues using -d in_asm. It is
useful to see the instruction bytes, as one can detect if
one is trying to execute ASCII or device-tree magic.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 disas/riscv.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index 74ad16e..2cecf0d 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2769,25 +2769,6 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
     char tmp[64];
     const char *fmt;
 
-    if (dec->op == rv_op_illegal) {
-        size_t len = inst_length(dec->inst);
-        switch (len) {
-        case 2:
-            snprintf(buf, buflen, "(0x%04" PRIx64 ")", dec->inst);
-            break;
-        case 4:
-            snprintf(buf, buflen, "(0x%08" PRIx64 ")", dec->inst);
-            break;
-        case 6:
-            snprintf(buf, buflen, "(0x%012" PRIx64 ")", dec->inst);
-            break;
-        default:
-            snprintf(buf, buflen, "(0x%016" PRIx64 ")", dec->inst);
-            break;
-        }
-        return;
-    }
-
     fmt = opcode_data[dec->op].format;
     while (*fmt) {
         switch (*fmt) {
@@ -3004,6 +2985,11 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst)
     format_inst(buf, buflen, 16, &dec);
 }
 
+#define INST_FMT_2 "%04" PRIx64 "              "
+#define INST_FMT_4 "%08" PRIx64 "          "
+#define INST_FMT_6 "%012" PRIx64 "      "
+#define INST_FMT_8 "%016" PRIx64 "  "
+
 static int
 print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
 {
@@ -3031,6 +3017,21 @@ print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
         }
     }
 
+    switch (len) {
+    case 2:
+        (*info->fprintf_func)(info->stream, INST_FMT_2, inst);
+        break;
+    case 4:
+        (*info->fprintf_func)(info->stream, INST_FMT_4, inst);
+        break;
+    case 6:
+        (*info->fprintf_func)(info->stream, INST_FMT_6, inst);
+        break;
+    default:
+        (*info->fprintf_func)(info->stream, INST_FMT_8, inst);
+        break;
+    }
+
     disasm_inst(buf, sizeof(buf), isa, memaddr, inst);
     (*info->fprintf_func)(info->stream, "%s", buf);
 
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (5 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 16:43   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent Michael Clark
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/riscv/spike.h | 4 ++--
 include/hw/riscv/virt.h  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index 8410430..641b70d 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -16,8 +16,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef HW_SPIKE_H
-#define HW_SPIKE_H
+#ifndef HW_RISCV_SPIKE_H
+#define HW_RISCV_SPIKE_H
 
 typedef struct {
     /*< private >*/
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index b91a412..3a4f23e 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -16,8 +16,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef HW_VIRT_H
-#define HW_VIRT_H
+#ifndef HW_RISCV_VIRT_H
+#define HW_RISCV_VIRT_H
 
 typedef struct {
     /*< private >*/
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (6 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 16:42   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection Michael Clark
                   ` (27 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/riscv/virt.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 3a4f23e..91163d6 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -1,5 +1,5 @@
 /*
- * SiFive VirtIO Board
+ * QEMU RISC-V VirtIO machine interface
  *
  * Copyright (c) 2017 SiFive, Inc.
  *
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (7 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 16:42   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c Michael Clark
                   ` (26 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt

Pointless indirection. Other ports use EM_ constants directly.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/riscv/sifive_e.c | 2 +-
 hw/riscv/sifive_u.c | 2 +-
 hw/riscv/spike.c    | 2 +-
 hw/riscv/virt.c     | 2 +-
 target/riscv/cpu.h  | 1 -
 5 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 4872b68..39e4cb4 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -88,7 +88,7 @@ static uint64_t load_kernel(const char *kernel_filename)
 
     if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
-                 0, ELF_MACHINE, 1, 0) < 0) {
+                 0, EM_RISCV, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
         exit(1);
     }
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 2412b5d..115618b 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -74,7 +74,7 @@ static uint64_t load_kernel(const char *kernel_filename)
 
     if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
-                 0, ELF_MACHINE, 1, 0) < 0) {
+                 0, EM_RISCV, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
         exit(1);
     }
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index f370f12..3f6bd0a 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -64,7 +64,7 @@ static uint64_t load_kernel(const char *kernel_filename)
     uint64_t kernel_entry, kernel_high;
 
     if (load_elf_ram_sym(kernel_filename, NULL, NULL,
-            &kernel_entry, NULL, &kernel_high, 0, ELF_MACHINE, 1, 0,
+            &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0,
             NULL, true, htif_symbol_callback) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
         exit(1);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 782996c..090befe 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -68,7 +68,7 @@ static uint64_t load_kernel(const char *kernel_filename)
 
     if (load_elf(kernel_filename, NULL, NULL,
                  &kernel_entry, NULL, &kernel_high,
-                 0, ELF_MACHINE, 1, 0) < 0) {
+                 0, EM_RISCV, 1, 0) < 0) {
         error_report("qemu: could not load kernel '%s'", kernel_filename);
         exit(1);
     }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 41e06ac..9871e6f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -34,7 +34,6 @@
 
 #define TCG_GUEST_DEFAULT_MO 0
 
-#define ELF_MACHINE EM_RISCV
 #define CPUArchState struct CPURISCVState
 
 #include "qemu-common.h"
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (8 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:51   ` [Qemu-devel] [patches] " Palmer Dabbelt
  2018-04-26 16:48   ` [Qemu-devel] " Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code Michael Clark
                   ` (25 subsequent siblings)
  35 siblings, 2 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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: Michael Clark <mjc@sifive.com>
---
 target/riscv/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 808eab7..c3a029a 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -280,7 +280,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
         tcg_gen_andi_tl(source2, source2, 0x1F);
         tcg_gen_sar_tl(source1, source1, source2);
         break;
-        /* fall through to SRA */
 #endif
     case OPC_RISC_SRA:
         tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (9 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 16:48   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 12/35] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

The sifive_u machine already marks its ROM readonly. This fixes
the remaining boards. This commit also makes all boards use
mask_rom as the variable name for the ROM. This change also
makes space for the maximum device tree size size and adds
an explicit bounds check and error message.

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_e.c     | 20 +++++++---------
 hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
 hw/riscv/spike.c        | 64 ++++++++++++++++++++++++++++---------------------
 hw/riscv/virt.c         | 38 +++++++++++++++--------------
 include/hw/riscv/virt.h |  4 ++++
 5 files changed, 93 insertions(+), 79 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 39e4cb4..0c8b8e9 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -74,14 +74,6 @@ static const struct MemmapEntry {
     [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
 };
 
-static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
-{
-    int i;
-    for (i = 0; i < (len >> 2); i++) {
-        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
-    }
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
@@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState *machine)
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
     MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
     MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
+    int i;
 
     /* Initialize SOC */
     object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState *machine)
         memmap[SIFIVE_E_DTIM].base, main_mem);
 
     /* Mask ROM */
-    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
+    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
         memmap[SIFIVE_E_MROM].size, &error_fatal);
     memory_region_add_subregion(sys_mem,
         memmap[SIFIVE_E_MROM].base, mask_rom);
@@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState *machine)
         0x00028067,        /* 0x1004: jr      t0 */
     };
 
-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec, sizeof(reset_vec));
-    memory_region_set_readonly(mask_rom, true);
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[SIFIVE_E_MROM].base, &address_space_memory);
 
     if (machine->kernel_filename) {
         load_kernel(machine->kernel_filename);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 115618b..11ba4c3 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -52,7 +52,7 @@ static const struct MemmapEntry {
     hwaddr size;
 } sifive_u_memmap[] = {
     [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
-    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
+    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
     [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
     [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
     [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
@@ -60,14 +60,6 @@ static const struct MemmapEntry {
     [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
 };
 
-static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
-{
-    int i;
-    for (i = 0; i < (len >> 2); i++) {
-        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
-    }
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
@@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState *machine)
     const struct MemmapEntry *memmap = sifive_u_memmap;
 
     SiFiveUState *s = g_new0(SiFiveUState, 1);
-    MemoryRegion *sys_memory = get_system_memory();
+    MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+    int i;
 
     /* Initialize SOC */
     object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState *machine)
     /* register RAM */
     memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
                            machine->ram_size, &error_fatal);
-    memory_region_add_subregion(sys_memory, memmap[SIFIVE_U_DRAM].base,
+    memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base,
         main_mem);
 
     /* create device tree */
     create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
 
     /* boot rom */
-    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
-                           memmap[SIFIVE_U_MROM].base, &error_fatal);
-    memory_region_set_readonly(boot_rom, true);
-    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
+    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
+                           memmap[SIFIVE_U_MROM].size, &error_fatal);
+    memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
+                                mask_rom);
 
     if (machine->kernel_filename) {
         load_kernel(machine->kernel_filename);
@@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState *machine)
                                        /* dtb: */
     };
 
-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec, sizeof(reset_vec));
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[SIFIVE_U_MROM].base, &address_space_memory);
 
     /* copy in the device tree */
+    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
+        error_report("qemu: not enough space to store device-tree");
+        exit(1);
+    }
     qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
-    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
-        sizeof(reset_vec), s->fdt, s->fdt_size);
+    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
+                          memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
+                          &address_space_memory);
 
     /* MMIO */
     s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
@@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState *machine)
         SIFIVE_U_PLIC_CONTEXT_BASE,
         SIFIVE_U_PLIC_CONTEXT_STRIDE,
         memmap[SIFIVE_U_PLIC].size);
-    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
+    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
         serial_hds[0], SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
-    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
+    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
         serial_hds[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,
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 3f6bd0a..d1dbe6b 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -46,19 +46,11 @@ static const struct MemmapEntry {
     hwaddr base;
     hwaddr size;
 } spike_memmap[] = {
-    [SPIKE_MROM] =     {     0x1000,     0x2000 },
+    [SPIKE_MROM] =     {     0x1000,    0x11000 },
     [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
     [SPIKE_DRAM] =     { 0x80000000,        0x0 },
 };
 
-static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
-{
-    int i;
-    for (i = 0; i < (len >> 2); i++) {
-        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
-    }
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
@@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(MachineState *machine)
     SpikeState *s = g_new0(SpikeState, 1);
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+    int i;
 
     /* Initialize SOC */
     object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(MachineState *machine)
     create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
 
     /* boot rom */
-    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
-                           s->fdt_size + 0x2000, &error_fatal);
-    memory_region_add_subregion(system_memory, 0x0, boot_rom);
+    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
+                           memmap[SPIKE_MROM].size, &error_fatal);
+    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
+                                mask_rom);
 
     if (machine->kernel_filename) {
         load_kernel(machine->kernel_filename);
@@ -221,16 +215,25 @@ static void spike_v1_10_0_board_init(MachineState *machine)
                                      /* dtb: */
     };
 
-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec));
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[SPIKE_MROM].base, &address_space_memory);
 
     /* copy in the device tree */
+    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
+        error_report("qemu: not enough space to store device-tree");
+        exit(1);
+    }
     qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
-    cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec),
-        s->fdt, s->fdt_size);
+    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
+                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
+                          &address_space_memory);
 
     /* initialize HTIF using symbols found in load_kernel */
-    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hds[0]);
+    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hds[0]);
 
     /* Core Local Interruptor (timer and IPI) */
     sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
@@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(MachineState *machine)
     SpikeState *s = g_new0(SpikeState, 1);
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+    int i;
 
     /* Initialize SOC */
     object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(MachineState *machine)
         main_mem);
 
     /* boot rom */
-    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
-                           0x40000, &error_fatal);
-    memory_region_add_subregion(system_memory, 0x0, boot_rom);
+    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
+                           memmap[SPIKE_MROM].size, &error_fatal);
+    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
+                                mask_rom);
 
     if (machine->kernel_filename) {
         load_kernel(machine->kernel_filename);
@@ -319,15 +324,20 @@ static void spike_v1_09_1_board_init(MachineState *machine)
     g_free(isa);
     size_t config_string_len = strlen(config_string);
 
-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec));
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[SPIKE_MROM].base, &address_space_memory);
 
     /* copy in the config string */
-    cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec),
-        config_string, config_string_len);
+    rom_add_blob_fixed_as("mrom.reset", config_string, config_string_len,
+                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
+                          &address_space_memory);
 
     /* initialize HTIF using symbols found in load_kernel */
-    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hds[0]);
+    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hds[0]);
 
     /* Core Local Interruptor (timer and IPI) */
     sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 090befe..20c509d 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -45,8 +45,8 @@ static const struct MemmapEntry {
     hwaddr size;
 } virt_memmap[] = {
     [VIRT_DEBUG] =    {        0x0,      0x100 },
-    [VIRT_MROM] =     {     0x1000,     0x2000 },
-    [VIRT_TEST] =     {     0x4000,     0x1000 },
+    [VIRT_MROM] =     {     0x1000,    0x11000 },
+    [VIRT_TEST] =     {   0x100000,     0x1000 },
     [VIRT_CLINT] =    {  0x2000000,    0x10000 },
     [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
     [VIRT_UART0] =    { 0x10000000,      0x100 },
@@ -54,14 +54,6 @@ static const struct MemmapEntry {
     [VIRT_DRAM] =     { 0x80000000,        0x0 },
 };
 
-static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
-{
-    int i;
-    for (i = 0; i < (len >> 2); i++) {
-        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
-    }
-}
-
 static uint64_t load_kernel(const char *kernel_filename)
 {
     uint64_t kernel_entry, kernel_high;
@@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState *machine)
     RISCVVirtState *s = g_new0(RISCVVirtState, 1);
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
     char *plic_hart_config;
     size_t plic_hart_config_len;
     int i;
@@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState *machine)
     fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
 
     /* boot rom */
-    memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom",
-                           s->fdt_size + 0x2000, &error_fatal);
-    memory_region_add_subregion(system_memory, 0x0, boot_rom);
+    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
+                           memmap[VIRT_MROM].size, &error_fatal);
+    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);
@@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState *machine)
                                      /* dtb: */
     };
 
-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec, sizeof(reset_vec));
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[VIRT_MROM].base, &address_space_memory);
 
     /* copy in the device tree */
+    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
+        error_report("qemu: not enough space to store device-tree");
+        exit(1);
+    }
     qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
-    cpu_physical_memory_write(memmap[VIRT_MROM].base + sizeof(reset_vec),
-        s->fdt, s->fdt_size);
+    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
+                          memmap[VIRT_MROM].base + sizeof(reset_vec),
+                          &address_space_memory);
 
     /* create PLIC hart topology configuration string */
     plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus;
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 91163d6..6f2668e 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -19,6 +19,10 @@
 #ifndef HW_RISCV_VIRT_H
 #define HW_RISCV_VIRT_H
 
+#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
+#define VIRT(obj) \
+    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
+
 typedef struct {
     /*< private >*/
     SysBusDevice parent_obj;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 12/35] RISC-V: Update address bits to support sv39 and sv48
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (10 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance Michael Clark
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 9871e6f..f3f131b 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (11 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 12/35] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 20:49   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order Michael Clark
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 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 64aa097..12b4757 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 02cbcea..459fc97 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (12 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:11   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case Michael Clark
                   ` (21 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Section 22.8 Subset Naming Convention of the RISC-V ISA Specification
defines the canonical order for extensions in the ISA string. It is
silent on the position of the E extension however E is a substitute
for I so it must come early in the extension list order. A comment
is added to state E and I are mutually exclusive, as the E extension
will be added to the RISC-V port in the future.

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 | 2 +-
 target/riscv/cpu.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5a527fb..4e5a56d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -26,7 +26,7 @@
 
 /* RISC-V CPU definitions */
 
-static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG";
+static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
 
 const char * const riscv_int_regnames[] = {
   "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f3f131b..890cd96 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -71,6 +71,7 @@
 #define RV(x) ((target_ulong)1 << (x - 'A'))
 
 #define RVI RV('I')
+#define RVE RV('E') /* E and I are mutually exclusive */
 #define RVM RV('M')
 #define RVA RV('A')
 #define RVF RV('F')
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (13 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:21   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps Michael Clark
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

satp is WARL so it should not trap on illegal writes, rather
it can be hardwired to zero and silently ignore illegal writes.

It seems the RISC-V WARL behaviour is preferred to having to
trap overhead versus simply reading back the value and checking
if the write took (saves hundreds of cycles and more complex
trap handling code).

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/op_helper.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 7c6068b..101dac1 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -255,7 +255,7 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
     }
     case CSR_SATP: /* CSR_SPTBR */ {
         if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
-            goto do_illegal;
+            break;
         }
         if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr))
         {
@@ -465,7 +465,10 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
         return env->scounteren;
     case CSR_SCAUSE:
         return env->scause;
-    case CSR_SPTBR:
+    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 {
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (14 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:27   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 17/35] RISC-V: No traps on writes to misa, minstret, mcycle Michael Clark
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Vectored traps for asynchrounous interrupts are optional.
The mtvec/stvec mode field is WARL and hence does not trap
if an illegal value is written. Illegal values are ignored.

Later we can add RISCV_FEATURE_VECTORED_TRAPS however
until then the correct behavior for WARL (Write Any, Read
Legal) fields is to drop writes to unsupported bits.

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/op_helper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 101dac1..828f20c 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -276,11 +276,10 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         env->sepc = val_to_write;
         break;
     case CSR_STVEC:
-        if (val_to_write & 1) {
-            qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported");
-            goto do_illegal;
+        /* we do not support vectored traps for asynchrounous interrupts */
+        if ((val_to_write & 3) == 0) {
+            env->stvec = val_to_write >> 2 << 2;
         }
-        env->stvec = val_to_write >> 2 << 2;
         break;
     case CSR_SCOUNTEREN:
         env->scounteren = val_to_write;
@@ -298,11 +297,10 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         env->mepc = val_to_write;
         break;
     case CSR_MTVEC:
-        if (val_to_write & 1) {
-            qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported");
-            goto do_illegal;
+        /* we do not support vectored traps for asynchrounous interrupts */
+        if ((val_to_write & 3) == 0) {
+            env->mtvec = val_to_write >> 2 << 2;
         }
-        env->mtvec = val_to_write >> 2 << 2;
         break;
     case CSR_MCOUNTEREN:
         env->mcounteren = val_to_write;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 17/35] RISC-V: No traps on writes to misa, minstret, mcycle
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (15 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info Michael Clark
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

These fields are marked WARL (Write Any Values, Reads
Legal Values) in the RISC-V Privileged Architecture
Specification so instead of raising exceptions,
illegal writes are silently dropped.

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/op_helper.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 828f20c..b81b9b6 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -213,17 +213,19 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         break;
     }
     case CSR_MINSTRET:
-        qemu_log_mask(LOG_UNIMP, "CSR_MINSTRET: write not implemented");
-        goto do_illegal;
+        /* minstret is WARL so unsupported writes are ignored */
+        break;
     case CSR_MCYCLE:
-        qemu_log_mask(LOG_UNIMP, "CSR_MCYCLE: write not implemented");
-        goto do_illegal;
+        /* mcycle is WARL so unsupported writes are ignored */
+        break;
+#if defined(TARGET_RISCV32)
     case CSR_MINSTRETH:
-        qemu_log_mask(LOG_UNIMP, "CSR_MINSTRETH: write not implemented");
-        goto do_illegal;
+        /* minstreth is WARL so unsupported writes are ignored */
+        break;
     case CSR_MCYCLEH:
-        qemu_log_mask(LOG_UNIMP, "CSR_MCYCLEH: write not implemented");
-        goto do_illegal;
+        /* mcycleh is WARL so unsupported writes are ignored */
+        break;
+#endif
     case CSR_MUCOUNTEREN:
         env->mucounteren = val_to_write;
         break;
@@ -314,10 +316,9 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
     case CSR_MBADADDR:
         env->mbadaddr = val_to_write;
         break;
-    case CSR_MISA: {
-        qemu_log_mask(LOG_UNIMP, "CSR_MISA: misa writes not supported");
-        goto do_illegal;
-    }
+    case CSR_MISA:
+        /* misa is WARL so unsupported writes are ignored */
+        break;
     case CSR_PMPCFG0:
     case CSR_PMPCFG1:
     case CSR_PMPCFG2:
@@ -342,7 +343,6 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
     case CSR_PMPADDR15:
        pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write);
        break;
-    do_illegal:
 #endif
     default:
         do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (16 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 17/35] RISC-V: No traps on writes to misa, minstret, mcycle Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:36   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10 Michael Clark
                   ` (17 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

mtval/stval must be set on all exceptions but zero is
a legal value if there is no exception specific info.
Placing the instruction bytes for illegal instruction
exceptions in mtval/stval is an optional feature and
is currently not supported by QEMU RISC-V.

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/helper.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/target/riscv/helper.c b/target/riscv/helper.c
index 459fc97..3b57e13 100644
--- a/target/riscv/helper.c
+++ b/target/riscv/helper.c
@@ -492,6 +492,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                     ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
             }
             env->sbadaddr = env->badaddr;
+        } else {
+            /* otherwise we must clear sbadaddr/stval
+             * todo: support populating stval on illegal instructions */
+            env->sbadaddr = 0;
         }
 
         target_ulong s = env->mstatus;
@@ -513,6 +517,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                     ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
             }
             env->mbadaddr = env->badaddr;
+        } else {
+            /* otherwise we must clear mbadaddr/mtval
+             * todo: support populating mtval on illegal instructions */
+            env->mbadaddr = 0;
         }
 
         target_ulong s = env->mstatus;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (17 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 20:02   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 20/35] RISC-V: Use [ms]counteren CSRs " Michael Clark
                   ` (16 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

The mstatus.MXR alias in sstatus should only be writable
by S-mode if the privileged ISA version >= v1.10. Also MXR
was masked in sstatus CSR read but not sstatus CSR writes.
Now we correctly mask sstatus.mxr in both read and write.

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/op_helper.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index b81b9b6..88c263a 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -236,7 +236,10 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         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_MXR | SSTATUS_SD;
+            | 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;
@@ -439,7 +442,7 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
     case CSR_SSTATUS: {
         target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
             | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
-            | SSTATUS_SUM |  SSTATUS_SD;
+            | SSTATUS_SUM | SSTATUS_SD;
         if (env->priv_ver >= PRIV_VERSION_1_10_0) {
             mask |= SSTATUS_MXR;
         }
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 20/35] RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (18 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10 Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto Michael Clark
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Privileged ISA v1.9.1 defines mscounteren and mucounteren:

* mscounteren contains a mask of counters available to S-mode
* mucounteren contains a mask of counters available to U-mode

Privileged ISA v1.10 defines mcounteren and scounteren:

* mcounteren contains a mask of counters available to S-mode
* scounteren contains a mask of counters available to U-mode

mcounteren and scounteren CSR registers were implemented
however they were not honoured for counter accesses when
the privilege ISA was >= v1.10. This fix solves the issue
by coalescing the counter enable registers. In addition
the code now  generates illegal instruction exceptions
for accesses to the counter enabled registers depending
on the privileged ISA version.

- Coalesce mscounteren and mcounteren into one variable
- Coalesce mucounteren and scounteren into one variable
- Makes mcounteren and scounteren CSR accesses generate
  illegal instructions when the privileged ISA <= v1.9.1
- Makes mscounteren and mucounteren CSR accesses generate
  illegal instructions when the privileged 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>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 target/riscv/cpu.h       |  6 ++---
 target/riscv/op_helper.c | 63 +++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 890cd96..e0608e6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -151,10 +151,8 @@ struct CPURISCVState {
     target_ulong mcause;
     target_ulong mtval;  /* since: priv-1.10.0 */
 
-    uint32_t mucounteren;
-    uint32_t mscounteren;
-    target_ulong scounteren; /* since: priv-1.10.0 */
-    target_ulong mcounteren; /* since: priv-1.10.0 */
+    target_ulong scounteren;
+    target_ulong mcounteren;
 
     target_ulong sscratch;
     target_ulong mscratch;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 88c263a..2daf07c 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -227,11 +227,19 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         break;
 #endif
     case CSR_MUCOUNTEREN:
-        env->mucounteren = val_to_write;
-        break;
+        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+            env->scounteren = val_to_write;
+            break;
+        } else {
+            goto do_illegal;
+        }
     case CSR_MSCOUNTEREN:
-        env->mscounteren = val_to_write;
-        break;
+        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
@@ -287,8 +295,12 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         }
         break;
     case CSR_SCOUNTEREN:
-        env->scounteren = val_to_write;
-        break;
+        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;
@@ -308,8 +320,12 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
         }
         break;
     case CSR_MCOUNTEREN:
-        env->mcounteren = val_to_write;
-        break;
+        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;
@@ -347,6 +363,9 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
        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());
     }
@@ -360,8 +379,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
 target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
 {
 #ifndef CONFIG_USER_ONLY
-    target_ulong ctr_en = env->priv == PRV_U ? env->mucounteren :
-                   env->priv == PRV_S ? env->mscounteren : -1U;
+    target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
+                          env->priv == PRV_S ? env->mcounteren : -1U;
 #else
     target_ulong ctr_en = -1;
 #endif
@@ -436,9 +455,17 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
 #endif
         break;
     case CSR_MUCOUNTEREN:
-        return env->mucounteren;
+        if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+            return env->scounteren;
+        } else {
+            break; /* illegal instruction */
+        }
     case CSR_MSCOUNTEREN:
-        return env->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
@@ -463,7 +490,11 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
     case CSR_STVEC:
         return env->stvec;
     case CSR_SCOUNTEREN:
-        return env->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 */
@@ -508,7 +539,11 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
     case CSR_MTVEC:
         return env->mtvec;
     case CSR_MCOUNTEREN:
-        return env->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:
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (19 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 20/35] RISC-V: Use [ms]counteren CSRs " Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 20:05   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
                   ` (14 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Clark, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis

Previously the mycycle/minstret CSRs and rdcycle/rdinstret
psuedo instructions would return the time as a proxy for an
increasing instruction counter in the absence of having a
precise instruction count. If QEMU is invoked with -icount,
the mcycle/minstret CSRs and rdcycle/rdinstret psuedo
instructions will return the instruction count.

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/op_helper.c | 24 ++++++++++++++++++++----
 target/riscv/translate.c |  2 ++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 2daf07c..7d3f1ee 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -433,25 +433,41 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
     case CSR_INSTRET:
     case CSR_CYCLE:
         if (ctr_ok) {
-            return cpu_get_host_ticks();
+            if (use_icount) {
+                return cpu_get_icount();
+            } else {
+                return cpu_get_host_ticks();
+            }
         }
         break;
 #if defined(TARGET_RISCV32)
     case CSR_INSTRETH:
     case CSR_CYCLEH:
         if (ctr_ok) {
-            return cpu_get_host_ticks() >> 32;
+            if (use_icount) {
+                return cpu_get_icount() >> 32;
+            } else {
+                return cpu_get_host_ticks() >> 32;
+            }
         }
         break;
 #endif
 #ifndef CONFIG_USER_ONLY
     case CSR_MINSTRET:
     case CSR_MCYCLE:
-        return cpu_get_host_ticks();
+        if (use_icount) {
+            return cpu_get_icount();
+        } else {
+            return cpu_get_host_ticks();
+        }
     case CSR_MINSTRETH:
     case CSR_MCYCLEH:
 #if defined(TARGET_RISCV32)
-        return cpu_get_host_ticks() >> 32;
+        if (use_icount) {
+            return cpu_get_icount() >> 32;
+        } else {
+            return cpu_get_host_ticks() >> 32;
+        }
 #endif
         break;
     case CSR_MUCOUNTEREN:
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c3a029a..c0e6a04 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1390,6 +1390,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
         break;
     default:
         tcg_gen_movi_tl(imm_rs1, rs1);
+        gen_io_start();
         switch (opc) {
         case OPC_RISC_CSRRW:
             gen_helper_csrrw(dest, cpu_env, source1, csr_store);
@@ -1413,6 +1414,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
             gen_exception_illegal(ctx);
             return;
         }
+        gen_io_end();
         gen_set_gpr(rd, dest);
         /* end tb since we may be changing priv modes, to get mmu_index right */
         tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (20 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-27  0:14   ` Richard Henderson
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
                   ` (13 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 hw/riscv/sifive_plic.c         | 36 +++++++++++++++---------------------
 include/hw/riscv/sifive_plic.h |  1 -
 2 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 874de2e..04e39e4 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -84,33 +84,28 @@ static void sifive_plic_print_state(SiFivePLICState *plic)
 static
 void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
 {
-    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;
+    do {
+        old = atomic_read(&plic->pending[word]);
+        new = (old & ~(1 << (irq & 31))) | (-!!pending & (1 << (irq & 31)));
+    } while (atomic_cmpxchg(&plic->pending[word], old, new) != old);
 }
 
 static
 void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
 {
-    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);
+    uint32_t old, new;
+    do {
+        old = atomic_read(&plic->claimed[word]);
+        new = (old & ~(1 << (irq & 31))) | (-!!claimed & (1 << (irq & 31)));
+    } while (atomic_cmpxchg(&plic->claimed[word], old, new) != old);
 }
 
-static
-int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
 {
-    int i, j, count = 0;
+    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 +118,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 +138,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 +435,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 11a5a98..ff09a28 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (21 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-27 22:33   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs Michael Clark
                   ` (12 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 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 3b57e13..47d116e 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (22 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 20:54   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
                   ` (11 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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       |  8 +++-----
 target/riscv/op_helper.c | 23 ++++++++++++++---------
 4 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 7cc606e..909929b 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, -1);
         return;
     }
 
     /* otherwise, set up the future timer interrupt */
-    riscv_set_local_interrupt(cpu, MIP_MTIP, 0);
+    riscv_cpu_update_mip(cpu, MIP_MTIP, 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, -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, -!!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 04e39e4..fa0298d 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -141,10 +141,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, -!!level);
             break;
         case PLICMode_S:
-            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_SEIP, level);
+            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, -!!level);
             break;
         default:
             break;
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e0608e6..5ac1482 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -247,7 +247,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 +255,9 @@ 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);
+#endif
 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
 
 void riscv_translate_init(void);
@@ -286,10 +288,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 7d3f1ee..2a7f045 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
@@ -643,16 +641,23 @@ 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_mip, new_mip;
 
-    if (cpu->env.mip && !old_mip) {
+    do {
+        old_mip = atomic_read(&env->mip);
+        new_mip = (old_mip & ~mask) | (value & mask);
+    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
+
+    if (new_mip && !old_mip) {
         cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    } else if (!cpu->env.mip && old_mip) {
+    } else if (!new_mip && old_mip) {
         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
     }
+
+    return old_mip;
 }
 
 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (23 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26 17:42   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions Michael Clark
                   ` (10 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 target/riscv/Makefile.objs              |  2 +-
 target/riscv/{helper.c => cpu_helper.c} | 34 ++++++++++++++++++++++++++++++++-
 target/riscv/op_helper.c                | 33 --------------------------------
 3 files changed, 34 insertions(+), 35 deletions(-)
 rename target/riscv/{helper.c => cpu_helper.c} (95%)

diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index abd0a7c..fcc5d34 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 47d116e..fb3f7ef 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,38 @@ 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_mip, new_mip;
+
+    do {
+        old_mip = atomic_read(&env->mip);
+        new_mip = (old_mip & ~mask) | (value & mask);
+    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
+
+    if (new_mip && !old_mip) {
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+    } else if (!new_mip && old_mip) {
+        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+    }
+
+    return old_mip;
+}
+
+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 2a7f045..4b4d62b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -640,38 +640,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_mip, new_mip;
-
-    do {
-        old_mip = atomic_read(&env->mip);
-        new_mip = (old_mip & ~mask) | (value & mask);
-    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
-
-    if (new_mip && !old_mip) {
-        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    } else if (!new_mip && old_mip) {
-        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-    }
-
-    return old_mip;
-}
-
-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)) {
@@ -722,7 +690,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (24 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 20:56   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 27/35] RISC-V: Implement modular CSR helper interface Michael Clark
                   ` (9 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 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 12b4757..878de62 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 4b4d62b..9375331 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 27/35] RISC-V: Implement modular CSR helper interface
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (25 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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         | 853 +++++++++++++++++++++++++++++++++++++++++++++
 target/riscv/gdbstub.c     |  10 +-
 target/riscv/op_helper.c   | 599 +------------------------------
 6 files changed, 894 insertions(+), 592 deletions(-)
 create mode 100644 target/riscv/csr.c

diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index fcc5d34..4072abe 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 5ac1482..dc79f7c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -284,9 +284,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 fb3f7ef..2937da0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -525,7 +525,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 */
@@ -550,7 +550,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 0000000..a424867
--- /dev/null
+++ b/target/riscv/csr.c
@@ -0,0 +1,853 @@
+/*
+ * 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)
+{
+    /* we do not support vectored traps for asynchrounous interrupts */
+    if ((val & 3) == 0) {
+        env->mtvec = val >> 2 << 2;
+    }
+    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)
+{
+    /* we do not support vectored traps for asynchrounous interrupts */
+    if ((val & 3) == 0) {
+        env->stvec = val >> 2 << 2;
+    }
+    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 4f919b6..3cabb21 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 9375331..81bd1a7 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,570 +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:
-        /* we do not support vectored traps for asynchrounous interrupts */
-        if ((val_to_write & 3) == 0) {
-            env->stvec = val_to_write >> 2 << 2;
-        }
-        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:
-        /* we do not support vectored traps for asynchrounous interrupts */
-        if ((val_to_write & 3) == 0) {
-            env->mtvec = val_to_write >> 2 << 2;
-        }
-        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 (use_icount) {
-                return cpu_get_icount();
-            } else {
-                return cpu_get_host_ticks();
-            }
-        }
-        break;
-#if defined(TARGET_RISCV32)
-    case CSR_INSTRETH:
-    case CSR_CYCLEH:
-        if (ctr_ok) {
-            if (use_icount) {
-                return cpu_get_icount() >> 32;
-            } else {
-                return cpu_get_host_ticks() >> 32;
-            }
-        }
-        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
@@ -660,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;
 }
@@ -685,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (26 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 27/35] RISC-V: Implement modular CSR helper interface Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 21:11   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs Michael Clark
                   ` (7 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 a424867..c704545 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -491,25 +491,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;
 }
@@ -627,17 +633,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 */
@@ -819,7 +819,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     },
@@ -832,7 +832,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (27 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 21:21   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
                   ` (6 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 4e5a56d..26741d0 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 dc79f7c..3fed92d 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 2937da0..5d33f7b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -403,7 +403,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 c704545..ecf74a0 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;
@@ -726,6 +741,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);
@@ -765,89 +785,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (28 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 21:22   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 31/35] RISC-V: Mark mstatus.fs dirty Michael Clark
                   ` (5 subsequent siblings)
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>
---
 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 3fed92d..6fb0014 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -270,8 +270,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)
@@ -279,7 +279,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 c0e6a04..4180c42 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -43,7 +43,7 @@ typedef struct DisasContext {
     target_ulong pc;
     target_ulong next_pc;
     uint32_t opcode;
-    uint32_t flags;
+    uint32_t mstatus_fs;
     uint32_t mem_idx;
     int singlestep_enabled;
     int bstate;
@@ -664,7 +664,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;
     }
@@ -694,7 +694,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;
     }
@@ -985,7 +985,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;
     }
 
@@ -1863,8 +1863,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
-    ctx.flags = tb->flags;
     ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK;
+    ctx.mstatus_fs = tb->flags & TB_FLAGS_MSTATUS_FS;
     ctx.frm = -1;  /* unknown rounding mode */
 
     num_insns = 0;
-- 
2.7.0

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

* [Qemu-devel] [PATCH v8 31/35] RISC-V: Mark mstatus.fs dirty
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (29 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 32/35] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
                   ` (4 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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>

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 ecf74a0..e005285 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 4180c42..442c8cd 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -659,6 +659,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)
 {
@@ -687,6 +712,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,
@@ -984,6 +1011,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;
@@ -1046,6 +1074,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:
@@ -1075,6 +1104,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:
@@ -1125,6 +1155,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:
@@ -1217,6 +1248,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:
@@ -1246,6 +1278,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:
@@ -1293,6 +1326,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:
@@ -1309,7 +1343,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 32/35] RISC-V: Implement mstatus.TSR/TW/TVM
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (30 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 31/35] RISC-V: Mark mstatus.fs dirty Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 33/35] RISC-V: Add public API for the CSR dispatch table Michael Clark
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 e005285..da66908 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 */
@@ -650,7 +651,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;
     }
@@ -671,8 +676,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 81bd1a7..77c79ba 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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 33/35] RISC-V: Add public API for the CSR dispatch table
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (31 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 32/35] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging Michael Clark
                   ` (2 subsequent siblings)
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 6fb0014..4030530 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -301,6 +301,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 da66908..25a7e26 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)
 {
@@ -780,7 +781,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (32 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 33/35] RISC-V: Add public API for the CSR dispatch table Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-05-03 21:25   ` Alistair Francis
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 35/35] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
  2018-04-26  1:42 ` [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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 5d33f7b..a45885f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -445,11 +445,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);
         }
     }
 
@@ -511,8 +513,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 {
@@ -536,8 +538,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 related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH v8 35/35] RISC-V: Use riscv prefix consistently on cpu helpers
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (33 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging Michael Clark
@ 2018-04-25 23:45 ` Michael Clark
  2018-04-26  1:42 ` [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
  35 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-25 23:45 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/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/signal.c b/linux-user/signal.c
index b283270..29c577e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -6737,7 +6737,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);
 }
 
@@ -6819,7 +6819,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 4030530..93d308a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -252,23 +252,22 @@ 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
 
 #ifndef CONFIG_USER_ONLY
 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t 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
@@ -288,13 +287,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 a45885f..ba3e981 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -92,7 +92,7 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
     return old_mip;
 }
 
-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();
@@ -365,7 +365,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 */
@@ -377,7 +377,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);
     }
 }
 
@@ -529,7 +529,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;
@@ -554,7 +554,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 25a7e26..06e3af3 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 abbadea..f9ed997 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 77c79ba..b7dc18a 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 related	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [patches] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c Michael Clark
@ 2018-04-25 23:51   ` Palmer Dabbelt
  2018-04-26 16:48   ` [Qemu-devel] " Alistair Francis
  1 sibling, 0 replies; 76+ messages in thread
From: Palmer Dabbelt @ 2018-04-25 23:51 UTC (permalink / raw)
  Cc: qemu-devel, patches, Michael Clark, sagark, kbastian, Alistair.Francis

On Wed, 25 Apr 2018 16:45:13 PDT (-0700), 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: Michael Clark <mjc@sifive.com>
> ---
>  target/riscv/translate.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 808eab7..c3a029a 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -280,7 +280,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
>          tcg_gen_andi_tl(source2, source2, 0x1F);
>          tcg_gen_sar_tl(source1, source1, source2);
>          break;
> -        /* fall through to SRA */
>  #endif
>      case OPC_RISC_SRA:
>          tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);

Reviewed-by: Palmer Dabbelt <palmer@sifive.com>

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
                   ` (34 preceding siblings ...)
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 35/35] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
@ 2018-04-26  1:42 ` Michael Clark
  2018-04-26  2:01   ` Michael Clark
  35 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-26  1:42 UTC (permalink / raw)
  To: QEMU Developers
  Cc: RISC-V Patches, Michael Clark, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	Richard Henderson, Peter Maydell, Su Hang, Matthew Suozzo

Hi All,

As a first-time QEMU contributor, it was quite a challenge to get an entire
port accepted upstream into QEMU. As folk who have followed the progress of
the port will know; at moments my nerves got the better of me as we
approached soft-freeze. In any case, I'd like to thank everyone who helped
out with feedback and reviews.

We now have quite a bit of RISC-V specific code targetting QEMU 2.13 and
are starting to plan development for QEMU 2.14. And when I say RISC-V, I
mean it, as this series focuses on spec conformance. We would like to be to
get a little more SiFive code in QEMU 2.14 including a better model of HiFive1
and HiFive Unleashed with the addition of more SiFive devices.

Here are some of the future plans that we would like help with:

- Add Cadence Ethernet to SiFive U for which there is already an emulation
in QEMU.
 - This requires a device-tree dump from the HiFive Unleashed board
- Improve emulation accuracy of the SiFiveUART,
  - Need to add fifos and full RX/TX watemark interrupt support
  - Good documentation exists in the FE310G000 manual.
  - https://www.sifive.com/documentation/chips/freedom-e310-g000-manual/
- Implement GPIOs e.g. SiFiveGPIO
  - Good documentation for the SiFive GPIO exists in the FE310 manual
  - We would like to be able to playback VCD files (timestamp, pin) for
GPIO inputs
  - Potentially more advanced features where inputs are time synced or
state based on GPIO outputs
  - The intended application is interrupt controller and interrupt service
routine test cases.
- Implement Watchdog e.g. SiFiveWatchdog
  - Good documentation for the SiFive Watchdog exists in the FE310 manual
- Add an option for Xilinx PCI to the sifive_u board (Freedom Unleashed can
by run on FPGA using Xilinx PCI)
  - The RTL for the Freedom on VC707 is here:
https://github.com/sifive/freedom/
- Change virt board to use the generic Linux based GPIO reset of power-off
device-tree nodes
- Add GPEX PCI host to the virt board so that we can use VirtIO PCI
- Improve the SOC object model for the RISC-V boards, with consideration of
the RISC-V ecosystem in general
  - We are trying to make the core generic so that any vendor can implement
custom CSRs
  - The SiFive E and SiFive U are generic boards that are intended to
emulate SiFive Core IP so should be configurable
  - We could add HiFive1 and HiFiveUnleashed boards but at the moment SiFive
 E and SiFive U are binary compatible
  - i.e. this would ideally be implemented as subclassing a generic
heterogenous RISC-V Core Complex
- Add support for dynamic misa register changes and more spec conformance
details
  - Requires a clean way to 'predicate' illegal instructions based on
presence of ISA extensions in translate.c
  - i.e. we don't what to add a who lot of if (!riscv_has_feature(ctx,
RVF)) ... raise exception
  - A metadata approach might be better so it can be handled generically.
Need to study decode tree.
- Implement a prototype of the RISC-V Hypervisor specification as outlined
in Privileged ISA v1.11
- Get our growing manual testing scenarios documented and then automated to
add to CI
- Lots more... this is just what comes to mind...

Assuming the same development timeframe for QEMU 2.13, I guess we have 4-6
weeks to get our pending patches reviewed.

As for the future plans, I guess given the time it takes for reviews that
we would most likely target future development towards QEMU 2.14... master
and the riscv.org trees are now somewhat different so if other major
development is done in-tree then we'll need to port this to the new
baseline in the riscv.org tree.

If you are on the 'cc you've indicated interest in helping out with the
RISC-V or I'm thanking you on behalf of everyone involved in RISC-V and
QEMU with respect to past help with the port.

I hope that we can conduct more development upstream and I encourage folk
to review the code in this patch series.... time permitting. We have 4-6
weeks based on my experience with the last cycle.

FYI - I wrote a little about getting the RISC-V QEMU port upstream:

- https://www.sifive.com/blog/2018/04/25/risc-v-qemu-part-2-
the-risc-v-qemu-port-is-upstream/

Thanks and Regards,
Michael

On Thu, Apr 26, 2018 at 11:45 AM, Michael Clark <mjc@sifive.com> wrote:

> 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 focuses on
> correct modelling of Privileged ISA v1.10. Earlier versions
> of the code had many unimplemented warnings in the control
> and status register code. The version submitted upstream
> replaced calls to exit with illegal instruction traps. The
> changes in this series focus on implementing correct
> behaviour, which in some cases is to ignore writes instead
> of trapping, and in other cases traps are generated based
> on the presence of CPU features or register settings such
> as misa.S and mstatus.TSR/TW/TVM. Several other bugs in
> the RISC-V QEMU issue tracker are addresssed.
>
> The branch for this patch series can be found here:
>
> - https://github.com/riscv/riscv-qemu/commits/qemu-2.13-for-upstream
>
> The RISC-V QEMU issues that are not yet resolved upstream:
>
> - https://github.com/riscv/riscv-qemu/issues
>
> Summary of changes
>
> * Implemented TSR, TW and TVM for privileged ISA v1.10
> * Update floating-point to correctly mark mstatus.FS dirty.
> * Implements WARL behavior for CSRs that don't support writes
>   * Past behavior of raising traps was non-conformant
>     with the RISC-V Privileged ISA Specition v1.10.
> * Sets mtval/stval to zero on exceptions without addresses
>   * Past behavior of leaving the last value was non-conformant
>     with the RISC-V Privileged ISA Specition v1.10. mtval/stval
>     must be set on all exceptions; to zero if not supported.
> * 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%.
> * Honour privileged ISA v1.10 counter enable CSRs.
> * 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 .
> * Make ROMs read-only and implement device-tree size checks
>   * Uses memory_region_init_rom and rom_add_blob_fixed_as
> * Adds hexidecimal instruction bytes to disassembly output.
> * Several code cleanups
>   * Replacing hard-coded constants with enums
>   * Dead-code elimination
>
> 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): pending
> * riscv-tests: pass
> * checkpatch: pass
>
> Changelog
>
> v8
>
> * Use riscv prefix consistently on all cpu helpers
> * Add hartid and \n to qemu_log in interrupt logging
> * Add missing return statement in gdbstub.c
> * Implemented TSR, TW and TVM for privileged ISA v1.10
> * Merged Richard Henderson's mstatus.fs dirty fix
> * Dropped mstatus.FS workaround
> * Implemented traps for s* CSR access on CPUs without S mode
> * Implemented traps for pmp* CSR access for CPUs without PMP
> * Made local interrupt delivery use atomic updates
> * Implemented modular CSR interface supporting atomic accesses
> * Implemented privileged ISA v1.10 counter enable CSRs
> * Fixed mask for sstatus.mxr field when priv ISA <= v1.9.1
> * Fixed User/Supervisor access bug in page table walker refactor
> * Updated physical address bits to match the priv ISA specification
> * Use memory_region_init_rom and rom_add_blob_fixed_as for mask roms
>
> v7
>
> * Fix typo in mstatus.FS workaround comment
> * Remove privilege mode from mstatus.mxr page protection check
> * Shift class initialization boilerplate patch hunk to correct patch
> * Fix typo in include instruction hex in disassembly commit message
>
> v6
>
> * Added workaround for critical mstatus.FS MTTCG bug
> * Added fix for incorrect disassembly of addiw
>
> v5
>
> * Dropped fix for memory allocation bug in riscv_isa_string
> * Dropped Hold rcu_read_lock when accessing memory
>
> v4
>
> * Added fix for memory allocation bug in riscv_isa_string
> * Trivial fix to remove erroneous comment from translate.c
>
> v3
>
> * Refactor rcu_read_lock in PTE update to use single unlock
> * Make mstatus.mxr take effect regardless of privilege mode
> * Remove unnecessary class init from riscv_hart
> * Set mtval/stval to zero on exceptions without addresses
>
> v2
>
> * Remove unused class boilerplate retains qom parent_obj
> * Convert cpu definition towards future model
> * Honor mstatus.mxr flag in page table walker
>
> v1
>
> * Initial post merge cleanup patch series
>
> Michael Clark (33):
>   RISC-V: Replace hardcoded constants with enum values
>   RISC-V: Make virt board description match spike
>   RISC-V: Use ROM base address and size from memmap
>   RISC-V: Remove identity_translate from load_elf
>   RISC-V: Remove unused class definitions
>   RISC-V: Include instruction hex in disassembly
>   RISC-V: Make some header guards more specific
>   RISC-V: Make virt header comment title consistent
>   RISC-V: Remove EM_RISCV ELF_MACHINE indirection
>   RISC-V: Remove erroneous comment from translate.c
>   RISC-V: Mark ROM read-only after copying in code
>   RISC-V: Update address bits to support sv39 and sv48
>   RISC-V: Improve page table walker spec compliance
>   RISC-V: Update E order and I extension order
>   RISC-V: Hardwire satp to 0 for no-mmu case
>   RISC-V: Make mtvec/stvec ignore vectored traps
>   RISC-V: No traps on writes to misa,minstret,mcycle
>   RISC-V: Clear mtval/stval on exceptions without info
>   RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
>   RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
>   RISC-V: Add mcycle/minstret support for -icount auto
>   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
>
> Richard Henderson (2):
>   RISC-V: Split out mstatus_fs from tb_flags
>   RISC-V: Mark mstatus.fs dirty
>
>  disas/riscv.c                           |  39 +-
>  hw/riscv/riscv_hart.c                   |   6 -
>  hw/riscv/sifive_clint.c                 |  17 +-
>  hw/riscv/sifive_e.c                     |  54 +-
>  hw/riscv/sifive_plic.c                  |  40 +-
>  hw/riscv/sifive_u.c                     |  86 ++--
>  hw/riscv/spike.c                        |  99 ++--
>  hw/riscv/virt.c                         |  80 +--
>  include/hw/riscv/sifive_clint.h         |   4 +
>  include/hw/riscv/sifive_e.h             |   5 -
>  include/hw/riscv/sifive_plic.h          |   1 -
>  include/hw/riscv/sifive_u.h             |   9 +-
>  include/hw/riscv/spike.h                |  15 +-
>  include/hw/riscv/virt.h                 |  13 +-
>  linux-user/signal.c                     |   4 +-
>  target/riscv/Makefile.objs              |   2 +-
>  target/riscv/cpu.c                      |   8 +-
>  target/riscv/cpu.h                      |  84 +--
>  target/riscv/cpu_bits.h                 | 690 +++++++++++++------------
>  target/riscv/{helper.c => cpu_helper.c} | 173 ++++---
>  target/riscv/csr.c                      | 871
> ++++++++++++++++++++++++++++++++
>  target/riscv/fpu_helper.c               |   6 +-
>  target/riscv/gdbstub.c                  |  10 +-
>  target/riscv/op_helper.c                | 613 ++--------------------
>  target/riscv/translate.c                |  53 +-
>  25 files changed, 1700 insertions(+), 1282 deletions(-)
>  rename target/riscv/{helper.c => cpu_helper.c} (73%)
>  create mode 100644 target/riscv/csr.c
>
> --
> 2.7.0
>
>

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-26  1:42 ` [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
@ 2018-04-26  2:01   ` Michael Clark
  2018-04-26 18:22     ` Alistair Francis
  0 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-26  2:01 UTC (permalink / raw)
  To: QEMU Developers
  Cc: RISC-V Patches, Michael Clark, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	Richard Henderson, Peter Maydell, Su Hang, Matthew Suozzo,
	Emilio G. Cota

One last quick note.

We are tracking RISC-V QEMU issues in the riscv.org repo:

- https://github.com/riscv/riscv-qemu/issues

We have tagged issues that are resolved in the 'qemu-2.13-for-upstream'
branch (this branch can be rebased if we re-spin)

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

And we can now maintain a stable backport branch based on a major QEMU
release (where we plan to avoid rebasing)

- https://github.com/riscv/riscv-qemu/tree/riscv-qemu-2.12

We can make a PR for the first 9 patches as they are already reviewed,
however, the with this series is to gather review for the new baseline we
have in the riscv repo.

Note: the only conflicts in the current series we are likely to have are
Emilio's changes to translate.c, and I'm happy if those changes go in first
and we can rebase against them. The changes in the riscv repo are currently
all restricted to target/riscv and hw/riscv so there is little risk of
disruption to QEMU outside of the RISC-V ecosystem.

We haven't gone and implemented anything like generic bswap functions
generated using TCG, if TCG_TARGET_HAS_bswapnn_imm is not implemented by
the target, or TCG generated setcond2 and brcond2 so that large guest
support on 32-bit is transparent for targets that don't override the
defaults, so no worries about regressing the core. Yet... :-D

Michael.

On Thu, Apr 26, 2018 at 1:42 PM, Michael Clark <mjc@sifive.com> wrote:

> Hi All,
>
> As a first-time QEMU contributor, it was quite a challenge to get an
> entire port accepted upstream into QEMU. As folk who have followed the
> progress of the port will know; at moments my nerves got the better of me
> as we approached soft-freeze. In any case, I'd like to thank everyone who
> helped out with feedback and reviews.
>
> We now have quite a bit of RISC-V specific code targetting QEMU 2.13 and
> are starting to plan development for QEMU 2.14. And when I say RISC-V, I
> mean it, as this series focuses on spec conformance. We would like to be to
> get a little more SiFive code in QEMU 2.14 including a better model of HiFive1
> and HiFive Unleashed with the addition of more SiFive devices.
>
> Here are some of the future plans that we would like help with:
>
> - Add Cadence Ethernet to SiFive U for which there is already an emulation
> in QEMU.
>  - This requires a device-tree dump from the HiFive Unleashed board
> - Improve emulation accuracy of the SiFiveUART,
>   - Need to add fifos and full RX/TX watemark interrupt support
>   - Good documentation exists in the FE310G000 manual.
>   - https://www.sifive.com/documentation/chips/freedom-e310-g000-manual/
> - Implement GPIOs e.g. SiFiveGPIO
>   - Good documentation for the SiFive GPIO exists in the FE310 manual
>   - We would like to be able to playback VCD files (timestamp, pin) for
> GPIO inputs
>   - Potentially more advanced features where inputs are time synced or
> state based on GPIO outputs
>   - The intended application is interrupt controller and interrupt service
> routine test cases.
> - Implement Watchdog e.g. SiFiveWatchdog
>   - Good documentation for the SiFive Watchdog exists in the FE310 manual
> - Add an option for Xilinx PCI to the sifive_u board (Freedom Unleashed
> can by run on FPGA using Xilinx PCI)
>   - The RTL for the Freedom on VC707 is here: https://github.com/
> sifive/freedom/
> - Change virt board to use the generic Linux based GPIO reset of
> power-off device-tree nodes
> - Add GPEX PCI host to the virt board so that we can use VirtIO PCI
> - Improve the SOC object model for the RISC-V boards, with consideration
> of the RISC-V ecosystem in general
>   - We are trying to make the core generic so that any vendor can
> implement custom CSRs
>   - The SiFive E and SiFive U are generic boards that are intended to
> emulate SiFive Core IP so should be configurable
>   - We could add HiFive1 and HiFiveUnleashed boards but at the moment
> SiFive E and SiFive U are binary compatible
>   - i.e. this would ideally be implemented as subclassing a generic
> heterogenous RISC-V Core Complex
> - Add support for dynamic misa register changes and more spec conformance
> details
>   - Requires a clean way to 'predicate' illegal instructions based on
> presence of ISA extensions in translate.c
>   - i.e. we don't what to add a who lot of if (!riscv_has_feature(ctx,
> RVF)) ... raise exception
>   - A metadata approach might be better so it can be handled generically.
> Need to study decode tree.
> - Implement a prototype of the RISC-V Hypervisor specification as outlined
> in Privileged ISA v1.11
> - Get our growing manual testing scenarios documented and then automated
> to add to CI
> - Lots more... this is just what comes to mind...
>
> Assuming the same development timeframe for QEMU 2.13, I guess we have 4-6
> weeks to get our pending patches reviewed.
>
> As for the future plans, I guess given the time it takes for reviews that
> we would most likely target future development towards QEMU 2.14...
> master and the riscv.org trees are now somewhat different so if other
> major development is done in-tree then we'll need to port this to the new
> baseline in the riscv.org tree.
>
> If you are on the 'cc you've indicated interest in helping out with the
> RISC-V or I'm thanking you on behalf of everyone involved in RISC-V and
> QEMU with respect to past help with the port.
>
> I hope that we can conduct more development upstream and I encourage folk
> to review the code in this patch series.... time permitting. We have 4-6
> weeks based on my experience with the last cycle.
>
> FYI - I wrote a little about getting the RISC-V QEMU port upstream:
>
> - https://www.sifive.com/blog/2018/04/25/risc-v-qemu-part-2-
> the-risc-v-qemu-port-is-upstream/
>
> Thanks and Regards,
> Michael
>
> On Thu, Apr 26, 2018 at 11:45 AM, Michael Clark <mjc@sifive.com> wrote:
>
>> 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 focuses on
>> correct modelling of Privileged ISA v1.10. Earlier versions
>> of the code had many unimplemented warnings in the control
>> and status register code. The version submitted upstream
>> replaced calls to exit with illegal instruction traps. The
>> changes in this series focus on implementing correct
>> behaviour, which in some cases is to ignore writes instead
>> of trapping, and in other cases traps are generated based
>> on the presence of CPU features or register settings such
>> as misa.S and mstatus.TSR/TW/TVM. Several other bugs in
>> the RISC-V QEMU issue tracker are addresssed.
>>
>> The branch for this patch series can be found here:
>>
>> - https://github.com/riscv/riscv-qemu/commits/qemu-2.13-for-upstream
>>
>> The RISC-V QEMU issues that are not yet resolved upstream:
>>
>> - https://github.com/riscv/riscv-qemu/issues
>>
>> Summary of changes
>>
>> * Implemented TSR, TW and TVM for privileged ISA v1.10
>> * Update floating-point to correctly mark mstatus.FS dirty.
>> * Implements WARL behavior for CSRs that don't support writes
>>   * Past behavior of raising traps was non-conformant
>>     with the RISC-V Privileged ISA Specition v1.10.
>> * Sets mtval/stval to zero on exceptions without addresses
>>   * Past behavior of leaving the last value was non-conformant
>>     with the RISC-V Privileged ISA Specition v1.10. mtval/stval
>>     must be set on all exceptions; to zero if not supported.
>> * 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%.
>> * Honour privileged ISA v1.10 counter enable CSRs.
>> * 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 .
>> * Make ROMs read-only and implement device-tree size checks
>>   * Uses memory_region_init_rom and rom_add_blob_fixed_as
>> * Adds hexidecimal instruction bytes to disassembly output.
>> * Several code cleanups
>>   * Replacing hard-coded constants with enums
>>   * Dead-code elimination
>>
>> 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): pending
>> * riscv-tests: pass
>> * checkpatch: pass
>>
>> Changelog
>>
>> v8
>>
>> * Use riscv prefix consistently on all cpu helpers
>> * Add hartid and \n to qemu_log in interrupt logging
>> * Add missing return statement in gdbstub.c
>> * Implemented TSR, TW and TVM for privileged ISA v1.10
>> * Merged Richard Henderson's mstatus.fs dirty fix
>> * Dropped mstatus.FS workaround
>> * Implemented traps for s* CSR access on CPUs without S mode
>> * Implemented traps for pmp* CSR access for CPUs without PMP
>> * Made local interrupt delivery use atomic updates
>> * Implemented modular CSR interface supporting atomic accesses
>> * Implemented privileged ISA v1.10 counter enable CSRs
>> * Fixed mask for sstatus.mxr field when priv ISA <= v1.9.1
>> * Fixed User/Supervisor access bug in page table walker refactor
>> * Updated physical address bits to match the priv ISA specification
>> * Use memory_region_init_rom and rom_add_blob_fixed_as for mask roms
>>
>> v7
>>
>> * Fix typo in mstatus.FS workaround comment
>> * Remove privilege mode from mstatus.mxr page protection check
>> * Shift class initialization boilerplate patch hunk to correct patch
>> * Fix typo in include instruction hex in disassembly commit message
>>
>> v6
>>
>> * Added workaround for critical mstatus.FS MTTCG bug
>> * Added fix for incorrect disassembly of addiw
>>
>> v5
>>
>> * Dropped fix for memory allocation bug in riscv_isa_string
>> * Dropped Hold rcu_read_lock when accessing memory
>>
>> v4
>>
>> * Added fix for memory allocation bug in riscv_isa_string
>> * Trivial fix to remove erroneous comment from translate.c
>>
>> v3
>>
>> * Refactor rcu_read_lock in PTE update to use single unlock
>> * Make mstatus.mxr take effect regardless of privilege mode
>> * Remove unnecessary class init from riscv_hart
>> * Set mtval/stval to zero on exceptions without addresses
>>
>> v2
>>
>> * Remove unused class boilerplate retains qom parent_obj
>> * Convert cpu definition towards future model
>> * Honor mstatus.mxr flag in page table walker
>>
>> v1
>>
>> * Initial post merge cleanup patch series
>>
>> Michael Clark (33):
>>   RISC-V: Replace hardcoded constants with enum values
>>   RISC-V: Make virt board description match spike
>>   RISC-V: Use ROM base address and size from memmap
>>   RISC-V: Remove identity_translate from load_elf
>>   RISC-V: Remove unused class definitions
>>   RISC-V: Include instruction hex in disassembly
>>   RISC-V: Make some header guards more specific
>>   RISC-V: Make virt header comment title consistent
>>   RISC-V: Remove EM_RISCV ELF_MACHINE indirection
>>   RISC-V: Remove erroneous comment from translate.c
>>   RISC-V: Mark ROM read-only after copying in code
>>   RISC-V: Update address bits to support sv39 and sv48
>>   RISC-V: Improve page table walker spec compliance
>>   RISC-V: Update E order and I extension order
>>   RISC-V: Hardwire satp to 0 for no-mmu case
>>   RISC-V: Make mtvec/stvec ignore vectored traps
>>   RISC-V: No traps on writes to misa,minstret,mcycle
>>   RISC-V: Clear mtval/stval on exceptions without info
>>   RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
>>   RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
>>   RISC-V: Add mcycle/minstret support for -icount auto
>>   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
>>
>> Richard Henderson (2):
>>   RISC-V: Split out mstatus_fs from tb_flags
>>   RISC-V: Mark mstatus.fs dirty
>>
>>  disas/riscv.c                           |  39 +-
>>  hw/riscv/riscv_hart.c                   |   6 -
>>  hw/riscv/sifive_clint.c                 |  17 +-
>>  hw/riscv/sifive_e.c                     |  54 +-
>>  hw/riscv/sifive_plic.c                  |  40 +-
>>  hw/riscv/sifive_u.c                     |  86 ++--
>>  hw/riscv/spike.c                        |  99 ++--
>>  hw/riscv/virt.c                         |  80 +--
>>  include/hw/riscv/sifive_clint.h         |   4 +
>>  include/hw/riscv/sifive_e.h             |   5 -
>>  include/hw/riscv/sifive_plic.h          |   1 -
>>  include/hw/riscv/sifive_u.h             |   9 +-
>>  include/hw/riscv/spike.h                |  15 +-
>>  include/hw/riscv/virt.h                 |  13 +-
>>  linux-user/signal.c                     |   4 +-
>>  target/riscv/Makefile.objs              |   2 +-
>>  target/riscv/cpu.c                      |   8 +-
>>  target/riscv/cpu.h                      |  84 +--
>>  target/riscv/cpu_bits.h                 | 690 +++++++++++++------------
>>  target/riscv/{helper.c => cpu_helper.c} | 173 ++++---
>>  target/riscv/csr.c                      | 871
>> ++++++++++++++++++++++++++++++++
>>  target/riscv/fpu_helper.c               |   6 +-
>>  target/riscv/gdbstub.c                  |  10 +-
>>  target/riscv/op_helper.c                | 613 ++--------------------
>>  target/riscv/translate.c                |  53 +-
>>  25 files changed, 1700 insertions(+), 1282 deletions(-)
>>  rename target/riscv/{helper.c => cpu_helper.c} (73%)
>>  create mode 100644 target/riscv/csr.c
>>
>> --
>> 2.7.0
>>
>>
>

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

* Re: [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values Michael Clark
@ 2018-04-26 16:37   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:37 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, patches, palmer,
	Sagar Karandikar, Bastian Koppelmann

On Wed, Apr 25, 2018 at 4:47 PM Michael Clark <mjc@sifive.com> wrote:

> The RISC-V device-tree code has a number of hard-coded
> constants and this change moves them into header enums.

> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

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

Alistair

> ---
>   hw/riscv/sifive_clint.c         | 9 +++------
>   hw/riscv/sifive_u.c             | 6 ++++--
>   hw/riscv/spike.c                | 6 ++++--
>   hw/riscv/virt.c                 | 6 ++++--
>   include/hw/riscv/sifive_clint.h | 4 ++++
>   include/hw/riscv/sifive_u.h     | 4 ++++
>   include/hw/riscv/spike.h        | 4 ++++
>   include/hw/riscv/virt.h         | 4 ++++
>   8 files changed, 31 insertions(+), 12 deletions(-)

> diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
> index 4893453..7cc606e 100644
> --- a/hw/riscv/sifive_clint.c
> +++ b/hw/riscv/sifive_clint.c
> @@ -26,13 +26,10 @@
>   #include "hw/riscv/sifive_clint.h"
>   #include "qemu/timer.h"

> -/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */
> -#define TIMER_FREQ (10 * 1000 * 1000)
> -
>   static uint64_t cpu_riscv_read_rtc(void)
>   {
> -    return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
> -                    NANOSECONDS_PER_SECOND);
> +    return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
> +        SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);
>   }

>   /*
> @@ -59,7 +56,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu,
uint64_t value)
>       diff = cpu->env.timecmp - rtc_r;
>       /* back to ns (note args switched in muldiv64) */
>       next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> -        muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ);
> +        muldiv64(diff, NANOSECONDS_PER_SECOND,
SIFIVE_CLINT_TIMEBASE_FREQ);
>       timer_mod(cpu->env.timer, next);
>   }

> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 1c2deef..f3f7615 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -122,7 +122,8 @@ static void create_fdt(SiFiveUState *s, const struct
MemmapEntry *memmap,
>       g_free(nodename);

>       qemu_fdt_add_subnode(fdt, "/cpus");
> -    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
> +    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
> +        SIFIVE_CLINT_TIMEBASE_FREQ);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);

> @@ -131,7 +132,8 @@ static void create_fdt(SiFiveUState *s, const struct
MemmapEntry *memmap,
>           char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller",
cpu);
>           char *isa = riscv_isa_string(&s->soc.harts[cpu]);
>           qemu_fdt_add_subnode(fdt, nodename);
> -        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
1000000000);
> +        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
> +                              SIFIVE_U_CLOCK_FREQ);
>           qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
>           qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
>           qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index 2d1f114..4c233ec 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -115,7 +115,8 @@ static void create_fdt(SpikeState *s, const struct
MemmapEntry *memmap,
>       g_free(nodename);

>       qemu_fdt_add_subnode(fdt, "/cpus");
> -    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
> +    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
> +        SIFIVE_CLINT_TIMEBASE_FREQ);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);

> @@ -124,7 +125,8 @@ static void create_fdt(SpikeState *s, const struct
MemmapEntry *memmap,
>           char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller",
cpu);
>           char *isa = riscv_isa_string(&s->soc.harts[cpu]);
>           qemu_fdt_add_subnode(fdt, nodename);
> -        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
1000000000);
> +        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
> +                              SPIKE_CLOCK_FREQ);
>           qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
>           qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
>           qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index e2c214e..86a86c9 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -145,7 +145,8 @@ static void *create_fdt(RISCVVirtState *s, const
struct MemmapEntry *memmap,
>       g_free(nodename);

>       qemu_fdt_add_subnode(fdt, "/cpus");
> -    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000);
> +    qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
> +                          SIFIVE_CLINT_TIMEBASE_FREQ);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
>       qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);

> @@ -155,7 +156,8 @@ static void *create_fdt(RISCVVirtState *s, const
struct MemmapEntry *memmap,
>           char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller",
cpu);
>           char *isa = riscv_isa_string(&s->soc.harts[cpu]);
>           qemu_fdt_add_subnode(fdt, nodename);
> -        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
1000000000);
> +        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
> +                              VIRT_CLOCK_FREQ);
>           qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
>           qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
>           qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
> diff --git a/include/hw/riscv/sifive_clint.h
b/include/hw/riscv/sifive_clint.h
> index aaa2a58..e2865be 100644
> --- a/include/hw/riscv/sifive_clint.h
> +++ b/include/hw/riscv/sifive_clint.h
> @@ -47,4 +47,8 @@ enum {
>       SIFIVE_TIME_BASE    = 0xBFF8
>   };

> +enum {
> +    SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
> +};
> +
>   #endif
> diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
> index 662e8a1..be38aa0 100644
> --- a/include/hw/riscv/sifive_u.h
> +++ b/include/hw/riscv/sifive_u.h
> @@ -50,6 +50,10 @@ enum {
>       SIFIVE_U_UART1_IRQ = 4
>   };

> +enum {
> +    SIFIVE_U_CLOCK_FREQ = 1000000000
> +};
> +
>   #define SIFIVE_U_PLIC_HART_CONFIG "MS"
>   #define SIFIVE_U_PLIC_NUM_SOURCES 127
>   #define SIFIVE_U_PLIC_NUM_PRIORITIES 7
> diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
> index cb55a14..d85a64e 100644
> --- a/include/hw/riscv/spike.h
> +++ b/include/hw/riscv/spike.h
> @@ -42,6 +42,10 @@ enum {
>       SPIKE_DRAM
>   };

> +enum {
> +    SPIKE_CLOCK_FREQ = 1000000000
> +};
> +
>   #if defined(TARGET_RISCV32)
>   #define SPIKE_V1_09_1_CPU TYPE_RISCV_CPU_RV32GCSU_V1_09_1
>   #define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_RV32GCSU_V1_10_0
> diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> index 7525647..2fbe808 100644
> --- a/include/hw/riscv/virt.h
> +++ b/include/hw/riscv/virt.h
> @@ -55,6 +55,10 @@ enum {
>       VIRTIO_NDEV = 10
>   };

> +enum {
> +    VIRT_CLOCK_FREQ = 1000000000
> +};
> +
>   #define VIRT_PLIC_HART_CONFIG "MS"
>   #define VIRT_PLIC_NUM_SOURCES 127
>   #define VIRT_PLIC_NUM_PRIORITIES 7
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent Michael Clark
@ 2018-04-26 16:42   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:42 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, patches, palmer,
	Sagar Karandikar, Bastian Koppelmann

On Wed, Apr 25, 2018 at 4:48 PM Michael Clark <mjc@sifive.com> wrote:

> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

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

Alistair

> ---
>   include/hw/riscv/virt.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)

> diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> index 3a4f23e..91163d6 100644
> --- a/include/hw/riscv/virt.h
> +++ b/include/hw/riscv/virt.h
> @@ -1,5 +1,5 @@
>   /*
> - * SiFive VirtIO Board
> + * QEMU RISC-V VirtIO machine interface
>    *
>    * Copyright (c) 2017 SiFive, Inc.
>    *
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection Michael Clark
@ 2018-04-26 16:42   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:42 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, patches, palmer,
	Sagar Karandikar, Bastian Koppelmann

On Wed, Apr 25, 2018 at 4:51 PM Michael Clark <mjc@sifive.com> wrote:

> Pointless indirection. Other ports use EM_ constants directly.

> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

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

Alistair

> ---
>   hw/riscv/sifive_e.c | 2 +-
>   hw/riscv/sifive_u.c | 2 +-
>   hw/riscv/spike.c    | 2 +-
>   hw/riscv/virt.c     | 2 +-
>   target/riscv/cpu.h  | 1 -
>   5 files changed, 4 insertions(+), 5 deletions(-)

> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index 4872b68..39e4cb4 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -88,7 +88,7 @@ static uint64_t load_kernel(const char *kernel_filename)

>       if (load_elf(kernel_filename, NULL, NULL,
>                    &kernel_entry, NULL, &kernel_high,
> -                 0, ELF_MACHINE, 1, 0) < 0) {
> +                 0, EM_RISCV, 1, 0) < 0) {
>           error_report("qemu: could not load kernel '%s'",
kernel_filename);
>           exit(1);
>       }
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 2412b5d..115618b 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -74,7 +74,7 @@ static uint64_t load_kernel(const char *kernel_filename)

>       if (load_elf(kernel_filename, NULL, NULL,
>                    &kernel_entry, NULL, &kernel_high,
> -                 0, ELF_MACHINE, 1, 0) < 0) {
> +                 0, EM_RISCV, 1, 0) < 0) {
>           error_report("qemu: could not load kernel '%s'",
kernel_filename);
>           exit(1);
>       }
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index f370f12..3f6bd0a 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -64,7 +64,7 @@ static uint64_t load_kernel(const char *kernel_filename)
>       uint64_t kernel_entry, kernel_high;

>       if (load_elf_ram_sym(kernel_filename, NULL, NULL,
> -            &kernel_entry, NULL, &kernel_high, 0, ELF_MACHINE, 1, 0,
> +            &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0,
>               NULL, true, htif_symbol_callback) < 0) {
>           error_report("qemu: could not load kernel '%s'",
kernel_filename);
>           exit(1);
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 782996c..090befe 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -68,7 +68,7 @@ static uint64_t load_kernel(const char *kernel_filename)

>       if (load_elf(kernel_filename, NULL, NULL,
>                    &kernel_entry, NULL, &kernel_high,
> -                 0, ELF_MACHINE, 1, 0) < 0) {
> +                 0, EM_RISCV, 1, 0) < 0) {
>           error_report("qemu: could not load kernel '%s'",
kernel_filename);
>           exit(1);
>       }
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 41e06ac..9871e6f 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -34,7 +34,6 @@

>   #define TCG_GUEST_DEFAULT_MO 0

> -#define ELF_MACHINE EM_RISCV
>   #define CPUArchState struct CPURISCVState

>   #include "qemu-common.h"
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific Michael Clark
@ 2018-04-26 16:43   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:43 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, patches, palmer,
	Sagar Karandikar, Bastian Koppelmann

On Wed, Apr 25, 2018 at 4:57 PM Michael Clark <mjc@sifive.com> wrote:

> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

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

Alistair

> ---
>   include/hw/riscv/spike.h | 4 ++--
>   include/hw/riscv/virt.h  | 4 ++--
>   2 files changed, 4 insertions(+), 4 deletions(-)

> diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
> index 8410430..641b70d 100644
> --- a/include/hw/riscv/spike.h
> +++ b/include/hw/riscv/spike.h
> @@ -16,8 +16,8 @@
>    * this program.  If not, see <http://www.gnu.org/licenses/>.
>    */

> -#ifndef HW_SPIKE_H
> -#define HW_SPIKE_H
> +#ifndef HW_RISCV_SPIKE_H
> +#define HW_RISCV_SPIKE_H

>   typedef struct {
>       /*< private >*/
> diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> index b91a412..3a4f23e 100644
> --- a/include/hw/riscv/virt.h
> +++ b/include/hw/riscv/virt.h
> @@ -16,8 +16,8 @@
>    * this program.  If not, see <http://www.gnu.org/licenses/>.
>    */

> -#ifndef HW_VIRT_H
> -#define HW_VIRT_H
> +#ifndef HW_RISCV_VIRT_H
> +#define HW_RISCV_VIRT_H

>   typedef struct {
>       /*< private >*/
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code Michael Clark
@ 2018-04-26 16:48   ` Alistair Francis
  2018-04-27  5:22     ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:48 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:

> The sifive_u machine already marks its ROM readonly. This fixes
> the remaining boards. This commit also makes all boards use
> mask_rom as the variable name for the ROM. This change also
> makes space for the maximum device tree size size and adds
> an explicit bounds check and error message.

> 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_e.c     | 20 +++++++---------
>   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
>   hw/riscv/spike.c        | 64
++++++++++++++++++++++++++++---------------------
>   hw/riscv/virt.c         | 38 +++++++++++++++--------------
>   include/hw/riscv/virt.h |  4 ++++
>   5 files changed, 93 insertions(+), 79 deletions(-)

> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index 39e4cb4..0c8b8e9 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -74,14 +74,6 @@ static const struct MemmapEntry {
>       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
>   };

> -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> -{
> -    int i;
> -    for (i = 0; i < (len >> 2); i++) {
> -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> -    }
> -}
> -
>   static uint64_t load_kernel(const char *kernel_filename)
>   {
>       uint64_t kernel_entry, kernel_high;
> @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState *machine)
>       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
> +    int i;

>       /* Initialize SOC */
>       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState *machine)
>           memmap[SIFIVE_E_DTIM].base, main_mem);

>       /* Mask ROM */
> -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
> +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
>           memmap[SIFIVE_E_MROM].size, &error_fatal);
>       memory_region_add_subregion(sys_mem,
>           memmap[SIFIVE_E_MROM].base, mask_rom);
> @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
*machine)
>           0x00028067,        /* 0x1004: jr      t0 */
>       };

> -    /* copy in the reset vector */
> -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
sizeof(reset_vec));
> -    memory_region_set_readonly(mask_rom, true);
> +    /* copy in the reset vector in little_endian byte order */
> +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> +                          memmap[SIFIVE_E_MROM].base,
&address_space_memory);

>       if (machine->kernel_filename) {
>           load_kernel(machine->kernel_filename);
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 115618b..11ba4c3 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -52,7 +52,7 @@ static const struct MemmapEntry {
>       hwaddr size;
>   } sifive_u_memmap[] = {
>       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
> -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
> +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
>       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
>       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
>       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
> @@ -60,14 +60,6 @@ static const struct MemmapEntry {
>       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
>   };

> -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> -{
> -    int i;
> -    for (i = 0; i < (len >> 2); i++) {
> -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> -    }
> -}
> -
>   static uint64_t load_kernel(const char *kernel_filename)
>   {
>       uint64_t kernel_entry, kernel_high;
> @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
*machine)
>       const struct MemmapEntry *memmap = sifive_u_memmap;

>       SiFiveUState *s = g_new0(SiFiveUState, 1);
> -    MemoryRegion *sys_memory = get_system_memory();
> +    MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> +    int i;

>       /* Initialize SOC */
>       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
*machine)
>       /* register RAM */
>       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
>                              machine->ram_size, &error_fatal);
> -    memory_region_add_subregion(sys_memory, memmap[SIFIVE_U_DRAM].base,
> +    memory_region_add_subregion(system_memory,
memmap[SIFIVE_U_DRAM].base,
>           main_mem);

>       /* create device tree */
>       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);

>       /* boot rom */
> -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
> -                           memmap[SIFIVE_U_MROM].base, &error_fatal);
> -    memory_region_set_readonly(boot_rom, true);
> -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
> +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
> +                           memmap[SIFIVE_U_MROM].size, &error_fatal);
> +    memory_region_add_subregion(system_memory,
memmap[SIFIVE_U_MROM].base,
> +                                mask_rom);

>       if (machine->kernel_filename) {
>           load_kernel(machine->kernel_filename);
> @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
*machine)
>                                          /* dtb: */
>       };

> -    /* copy in the reset vector */
> -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
sizeof(reset_vec));
> +    /* copy in the reset vector in little_endian byte order */
> +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> +                          memmap[SIFIVE_U_MROM].base,
&address_space_memory);

>       /* copy in the device tree */
> +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
> +        error_report("qemu: not enough space to store device-tree");
> +        exit(1);
> +    }
>       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
> -        sizeof(reset_vec), s->fdt, s->fdt_size);
> +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> +                          memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
> +                          &address_space_memory);

>       /* MMIO */
>       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
> @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState *machine)
>           SIFIVE_U_PLIC_CONTEXT_BASE,
>           SIFIVE_U_PLIC_CONTEXT_STRIDE,
>           memmap[SIFIVE_U_PLIC].size);
> -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
> +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
>           serial_hds[0], SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
> -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
> +    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
>           serial_hds[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,
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index 3f6bd0a..d1dbe6b 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -46,19 +46,11 @@ static const struct MemmapEntry {
>       hwaddr base;
>       hwaddr size;
>   } spike_memmap[] = {
> -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
> +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
>       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
>       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
>   };

> -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> -{
> -    int i;
> -    for (i = 0; i < (len >> 2); i++) {
> -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> -    }
> -}
> -
>   static uint64_t load_kernel(const char *kernel_filename)
>   {
>       uint64_t kernel_entry, kernel_high;
> @@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(MachineState
*machine)
>       SpikeState *s = g_new0(SpikeState, 1);
>       MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> +    int i;

>       /* Initialize SOC */
>       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> @@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(MachineState
*machine)
>       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);

>       /* boot rom */
> -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> -                           s->fdt_size + 0x2000, &error_fatal);
> -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> +                           memmap[SPIKE_MROM].size, &error_fatal);
> +    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
> +                                mask_rom);

>       if (machine->kernel_filename) {
>           load_kernel(machine->kernel_filename);
> @@ -221,16 +215,25 @@ static void spike_v1_10_0_board_init(MachineState
*machine)
>                                        /* dtb: */
>       };

> -    /* copy in the reset vector */
> -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
sizeof(reset_vec));
> +    /* copy in the reset vector in little_endian byte order */
> +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> +                          memmap[SPIKE_MROM].base,
&address_space_memory);

>       /* copy in the device tree */
> +    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
> +        error_report("qemu: not enough space to store device-tree");
> +        exit(1);
> +    }
>       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
sizeof(reset_vec),
> -        s->fdt, s->fdt_size);
> +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
> +                          &address_space_memory);

>       /* initialize HTIF using symbols found in load_kernel */
> -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
serial_hds[0]);
> +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
serial_hds[0]);

>       /* Core Local Interruptor (timer and IPI) */
>       sifive_clint_create(memmap[SPIKE_CLINT].base,
memmap[SPIKE_CLINT].size,
> @@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(MachineState
*machine)
>       SpikeState *s = g_new0(SpikeState, 1);
>       MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> +    int i;

>       /* Initialize SOC */
>       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> @@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(MachineState
*machine)
>           main_mem);

>       /* boot rom */
> -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> -                           0x40000, &error_fatal);
> -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> +                           memmap[SPIKE_MROM].size, &error_fatal);
> +    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
> +                                mask_rom);

>       if (machine->kernel_filename) {
>           load_kernel(machine->kernel_filename);
> @@ -319,15 +324,20 @@ static void spike_v1_09_1_board_init(MachineState
*machine)
>       g_free(isa);
>       size_t config_string_len = strlen(config_string);

> -    /* copy in the reset vector */
> -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
sizeof(reset_vec));
> +    /* copy in the reset vector in little_endian byte order */
> +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> +                          memmap[SPIKE_MROM].base,
&address_space_memory);

>       /* copy in the config string */
> -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
sizeof(reset_vec),
> -        config_string, config_string_len);
> +    rom_add_blob_fixed_as("mrom.reset", config_string, config_string_len,
> +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
> +                          &address_space_memory);

>       /* initialize HTIF using symbols found in load_kernel */
> -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
serial_hds[0]);
> +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
serial_hds[0]);

>       /* Core Local Interruptor (timer and IPI) */
>       sifive_clint_create(memmap[SPIKE_CLINT].base,
memmap[SPIKE_CLINT].size,
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 090befe..20c509d 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -45,8 +45,8 @@ static const struct MemmapEntry {
>       hwaddr size;
>   } virt_memmap[] = {
>       [VIRT_DEBUG] =    {        0x0,      0x100 },
> -    [VIRT_MROM] =     {     0x1000,     0x2000 },
> -    [VIRT_TEST] =     {     0x4000,     0x1000 },
> +    [VIRT_MROM] =     {     0x1000,    0x11000 },
> +    [VIRT_TEST] =     {   0x100000,     0x1000 },
>       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
>       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
>       [VIRT_UART0] =    { 0x10000000,      0x100 },
> @@ -54,14 +54,6 @@ static const struct MemmapEntry {
>       [VIRT_DRAM] =     { 0x80000000,        0x0 },
>   };

> -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> -{
> -    int i;
> -    for (i = 0; i < (len >> 2); i++) {
> -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> -    }
> -}
> -
>   static uint64_t load_kernel(const char *kernel_filename)
>   {
>       uint64_t kernel_entry, kernel_high;
> @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
*machine)
>       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
>       MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>       char *plic_hart_config;
>       size_t plic_hart_config_len;
>       int i;
> @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
*machine)
>       fdt = create_fdt(s, memmap, machine->ram_size,
machine->kernel_cmdline);

>       /* boot rom */
> -    memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom",
> -                           s->fdt_size + 0x2000, &error_fatal);
> -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> +    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
> +                           memmap[VIRT_MROM].size, &error_fatal);
> +    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);
> @@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState
*machine)
>                                        /* dtb: */
>       };

> -    /* copy in the reset vector */
> -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
sizeof(reset_vec));
> +    /* copy in the reset vector in little_endian byte order */
> +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> +                          memmap[VIRT_MROM].base, &address_space_memory);

>       /* copy in the device tree */
> +    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
> +        error_report("qemu: not enough space to store device-tree");
> +        exit(1);
> +    }
>       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> -    cpu_physical_memory_write(memmap[VIRT_MROM].base + sizeof(reset_vec),
> -        s->fdt, s->fdt_size);
> +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> +                          memmap[VIRT_MROM].base + sizeof(reset_vec),
> +                          &address_space_memory);

>       /* create PLIC hart topology configuration string */
>       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
smp_cpus;
> diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> index 91163d6..6f2668e 100644
> --- a/include/hw/riscv/virt.h
> +++ b/include/hw/riscv/virt.h
> @@ -19,6 +19,10 @@
>   #ifndef HW_RISCV_VIRT_H
>   #define HW_RISCV_VIRT_H

> +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
> +#define VIRT(obj) \
> +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
> +

This should be in a seperate patch.

Alistair

>   typedef struct {
>       /*< private >*/
>       SysBusDevice parent_obj;
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c Michael Clark
  2018-04-25 23:51   ` [Qemu-devel] [patches] " Palmer Dabbelt
@ 2018-04-26 16:48   ` Alistair Francis
  1 sibling, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 16:48 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:00 PM Michael Clark <mjc@sifive.com> 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: Michael Clark <mjc@sifive.com>

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

Alistair

> ---
>   target/riscv/translate.c | 1 -
>   1 file changed, 1 deletion(-)

> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 808eab7..c3a029a 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -280,7 +280,6 @@ static void gen_arith(DisasContext *ctx, uint32_t
opc, int rd, int rs1,
>           tcg_gen_andi_tl(source2, source2, 0x1F);
>           tcg_gen_sar_tl(source1, source1, source2);
>           break;
> -        /* fall through to SRA */
>   #endif
>       case OPC_RISC_SRA:
>           tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly Michael Clark
@ 2018-04-26 17:05   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:05 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, patches, palmer,
	Sagar Karandikar, Bastian Koppelmann

On Wed, Apr 25, 2018 at 4:53 PM Michael Clark <mjc@sifive.com> wrote:

> This was added to help debug issues using -d in_asm. It is
> useful to see the instruction bytes, as one can detect if
> one is trying to execute ASCII or device-tree magic.

> Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Michael Clark <mjc@sifive.com>
> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

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

Alistair

> ---
>   disas/riscv.c | 39 ++++++++++++++++++++-------------------
>   1 file changed, 20 insertions(+), 19 deletions(-)

> diff --git a/disas/riscv.c b/disas/riscv.c
> index 74ad16e..2cecf0d 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -2769,25 +2769,6 @@ static void format_inst(char *buf, size_t buflen,
size_t tab, rv_decode *dec)
>       char tmp[64];
>       const char *fmt;

> -    if (dec->op == rv_op_illegal) {
> -        size_t len = inst_length(dec->inst);
> -        switch (len) {
> -        case 2:
> -            snprintf(buf, buflen, "(0x%04" PRIx64 ")", dec->inst);
> -            break;
> -        case 4:
> -            snprintf(buf, buflen, "(0x%08" PRIx64 ")", dec->inst);
> -            break;
> -        case 6:
> -            snprintf(buf, buflen, "(0x%012" PRIx64 ")", dec->inst);
> -            break;
> -        default:
> -            snprintf(buf, buflen, "(0x%016" PRIx64 ")", dec->inst);
> -            break;
> -        }
> -        return;
> -    }
> -
>       fmt = opcode_data[dec->op].format;
>       while (*fmt) {
>           switch (*fmt) {
> @@ -3004,6 +2985,11 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa,
uint64_t pc, rv_inst inst)
>       format_inst(buf, buflen, 16, &dec);
>   }

> +#define INST_FMT_2 "%04" PRIx64 "              "
> +#define INST_FMT_4 "%08" PRIx64 "          "
> +#define INST_FMT_6 "%012" PRIx64 "      "
> +#define INST_FMT_8 "%016" PRIx64 "  "
> +
>   static int
>   print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa
isa)
>   {
> @@ -3031,6 +3017,21 @@ print_insn_riscv(bfd_vma memaddr, struct
disassemble_info *info, rv_isa isa)
>           }
>       }

> +    switch (len) {
> +    case 2:
> +        (*info->fprintf_func)(info->stream, INST_FMT_2, inst);
> +        break;
> +    case 4:
> +        (*info->fprintf_func)(info->stream, INST_FMT_4, inst);
> +        break;
> +    case 6:
> +        (*info->fprintf_func)(info->stream, INST_FMT_6, inst);
> +        break;
> +    default:
> +        (*info->fprintf_func)(info->stream, INST_FMT_8, inst);
> +        break;
> +    }
> +
>       disasm_inst(buf, sizeof(buf), isa, memaddr, inst);
>       (*info->fprintf_func)(info->stream, "%s", buf);

> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order Michael Clark
@ 2018-04-26 17:11   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:11 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:53 PM Michael Clark <mjc@sifive.com> wrote:

> Section 22.8 Subset Naming Convention of the RISC-V ISA Specification
> defines the canonical order for extensions in the ISA string. It is
> silent on the position of the E extension however E is a substitute
> for I so it must come early in the extension list order. A comment
> is added to state E and I are mutually exclusive, as the E extension
> will be added to the RISC-V port in the future.

> 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

> ---
>   target/riscv/cpu.c | 2 +-
>   target/riscv/cpu.h | 1 +
>   2 files changed, 2 insertions(+), 1 deletion(-)

> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5a527fb..4e5a56d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -26,7 +26,7 @@

>   /* RISC-V CPU definitions */

> -static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG";
> +static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";

>   const char * const riscv_int_regnames[] = {
>     "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index f3f131b..890cd96 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -71,6 +71,7 @@
>   #define RV(x) ((target_ulong)1 << (x - 'A'))

>   #define RVI RV('I')
> +#define RVE RV('E') /* E and I are mutually exclusive */
>   #define RVM RV('M')
>   #define RVA RV('A')
>   #define RVF RV('F')
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case Michael Clark
@ 2018-04-26 17:21   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:21 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:56 PM Michael Clark <mjc@sifive.com> wrote:

> satp is WARL so it should not trap on illegal writes, rather
> it can be hardwired to zero and silently ignore illegal writes.

> It seems the RISC-V WARL behaviour is preferred to having to
> trap overhead versus simply reading back the value and checking
> if the write took (saves hundreds of cycles and more complex
> trap handling code).

> 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

> ---
>   target/riscv/op_helper.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)

> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 7c6068b..101dac1 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -255,7 +255,7 @@ void csr_write_helper(CPURISCVState *env,
target_ulong val_to_write,
>       }
>       case CSR_SATP: /* CSR_SPTBR */ {
>           if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
> -            goto do_illegal;
> +            break;
>           }
>           if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^
env->sptbr))
>           {
> @@ -465,7 +465,10 @@ target_ulong csr_read_helper(CPURISCVState *env,
target_ulong csrno)
>           return env->scounteren;
>       case CSR_SCAUSE:
>           return env->scause;
> -    case CSR_SPTBR:
> +    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 {
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps Michael Clark
@ 2018-04-26 17:27   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:27 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:08 PM Michael Clark <mjc@sifive.com> wrote:

> Vectored traps for asynchrounous interrupts are optional.
> The mtvec/stvec mode field is WARL and hence does not trap
> if an illegal value is written. Illegal values are ignored.

> Later we can add RISCV_FEATURE_VECTORED_TRAPS however
> until then the correct behavior for WARL (Write Any, Read
> Legal) fields is to drop writes to unsupported bits.

> 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/op_helper.c | 14 ++++++--------
>   1 file changed, 6 insertions(+), 8 deletions(-)

> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 101dac1..828f20c 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -276,11 +276,10 @@ void csr_write_helper(CPURISCVState *env,
target_ulong val_to_write,
>           env->sepc = val_to_write;
>           break;
>       case CSR_STVEC:
> -        if (val_to_write & 1) {
> -            qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not
supported");

Should the unimplemented log be removed?

Alistair

> -            goto do_illegal;
> +        /* we do not support vectored traps for asynchrounous interrupts
*/
> +        if ((val_to_write & 3) == 0) {
> +            env->stvec = val_to_write >> 2 << 2;
>           }
> -        env->stvec = val_to_write >> 2 << 2;
>           break;
>       case CSR_SCOUNTEREN:
>           env->scounteren = val_to_write;
> @@ -298,11 +297,10 @@ void csr_write_helper(CPURISCVState *env,
target_ulong val_to_write,
>           env->mepc = val_to_write;
>           break;
>       case CSR_MTVEC:
> -        if (val_to_write & 1) {
> -            qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not
supported");
> -            goto do_illegal;
> +        /* we do not support vectored traps for asynchrounous interrupts
*/
> +        if ((val_to_write & 3) == 0) {
> +            env->mtvec = val_to_write >> 2 << 2;
>           }
> -        env->mtvec = val_to_write >> 2 << 2;
>           break;
>       case CSR_MCOUNTEREN:
>           env->mcounteren = val_to_write;
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info Michael Clark
@ 2018-04-26 17:36   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:36 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:59 PM Michael Clark <mjc@sifive.com> wrote:

> mtval/stval must be set on all exceptions but zero is
> a legal value if there is no exception specific info.
> Placing the instruction bytes for illegal instruction
> exceptions in mtval/stval is an optional feature and
> is currently not supported by QEMU RISC-V.

> 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

> ---
>   target/riscv/helper.c | 8 ++++++++
>   1 file changed, 8 insertions(+)

> diff --git a/target/riscv/helper.c b/target/riscv/helper.c
> index 459fc97..3b57e13 100644
> --- a/target/riscv/helper.c
> +++ b/target/riscv/helper.c
> @@ -492,6 +492,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>                       ": badaddr 0x" TARGET_FMT_lx, env->mhartid,
env->badaddr);
>               }
>               env->sbadaddr = env->badaddr;
> +        } else {
> +            /* otherwise we must clear sbadaddr/stval
> +             * todo: support populating stval on illegal instructions */
> +            env->sbadaddr = 0;
>           }

>           target_ulong s = env->mstatus;
> @@ -513,6 +517,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>                       ": badaddr 0x" TARGET_FMT_lx, env->mhartid,
env->badaddr);
>               }
>               env->mbadaddr = env->badaddr;
> +        } else {
> +            /* otherwise we must clear mbadaddr/mtval
> +             * todo: support populating mtval on illegal instructions */
> +            env->mbadaddr = 0;
>           }

>           target_ulong s = env->mstatus;
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
@ 2018-04-26 17:42   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 17:42 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:13 PM Michael Clark <mjc@sifive.com> 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>

Alistair

> ---
>   target/riscv/Makefile.objs              |  2 +-
>   target/riscv/{helper.c => cpu_helper.c} | 34
++++++++++++++++++++++++++++++++-
>   target/riscv/op_helper.c                | 33
--------------------------------
>   3 files changed, 34 insertions(+), 35 deletions(-)
>   rename target/riscv/{helper.c => cpu_helper.c} (95%)

> diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
> index abd0a7c..fcc5d34 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 47d116e..fb3f7ef 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,38 @@ 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_mip, new_mip;
> +
> +    do {
> +        old_mip = atomic_read(&env->mip);
> +        new_mip = (old_mip & ~mask) | (value & mask);
> +    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
> +
> +    if (new_mip && !old_mip) {
> +        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> +    } else if (!new_mip && old_mip) {
> +        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> +    }
> +
> +    return old_mip;
> +}
> +
> +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 2a7f045..4b4d62b 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -640,38 +640,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_mip, new_mip;
> -
> -    do {
> -        old_mip = atomic_read(&env->mip);
> -        new_mip = (old_mip & ~mask) | (value & mask);
> -    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
> -
> -    if (new_mip && !old_mip) {
> -        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    } else if (!new_mip && old_mip) {
> -        cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    }
> -
> -    return old_mip;
> -}
> -
> -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)) {
> @@ -722,7 +690,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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-26  2:01   ` Michael Clark
@ 2018-04-26 18:22     ` Alistair Francis
  2018-04-27  0:34       ` Michael Clark
  2018-04-27  0:35       ` Richard Henderson
  0 siblings, 2 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 18:22 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Peter Maydell, suhang16,
	msuozzo, Sagar Karandikar, Bastian Koppelmann, palmer,
	Richard Henderson, Emilio G. Cota, Alistair Francis, patches

On Wed, Apr 25, 2018 at 7:01 PM Michael Clark <mjc@sifive.com> wrote:

> One last quick note.

> We are tracking RISC-V QEMU issues in the riscv.org repo:

> - https://github.com/riscv/riscv-qemu/issues

> We have tagged issues that are resolved in the 'qemu-2.13-for-upstream'
> branch (this branch can be rebased if we re-spin)

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

> And we can now maintain a stable backport branch based on a major QEMU
> release (where we plan to avoid rebasing)

> - https://github.com/riscv/riscv-qemu/tree/riscv-qemu-2.12

> We can make a PR for the first 9 patches as they are already reviewed,
> however, the with this series is to gather review for the new baseline we
> have in the riscv repo.

I think it is worth sending a PR for the first 9 patches. The current
master doesn't boot the sifive_u board and those patches will fix that.
That also helps create a smaller patch series which is easier to review.

Alistair


> Note: the only conflicts in the current series we are likely to have are
> Emilio's changes to translate.c, and I'm happy if those changes go in
first
> and we can rebase against them. The changes in the riscv repo are
currently
> all restricted to target/riscv and hw/riscv so there is little risk of
> disruption to QEMU outside of the RISC-V ecosystem.

> We haven't gone and implemented anything like generic bswap functions
> generated using TCG, if TCG_TARGET_HAS_bswapnn_imm is not implemented by
> the target, or TCG generated setcond2 and brcond2 so that large guest
> support on 32-bit is transparent for targets that don't override the
> defaults, so no worries about regressing the core. Yet... :-D

> Michael.

> On Thu, Apr 26, 2018 at 1:42 PM, Michael Clark <mjc@sifive.com> wrote:

> > Hi All,
> >
> > As a first-time QEMU contributor, it was quite a challenge to get an
> > entire port accepted upstream into QEMU. As folk who have followed the
> > progress of the port will know; at moments my nerves got the better of
me
> > as we approached soft-freeze. In any case, I'd like to thank everyone
who
> > helped out with feedback and reviews.
> >
> > We now have quite a bit of RISC-V specific code targetting QEMU 2.13 and
> > are starting to plan development for QEMU 2.14. And when I say RISC-V, I
> > mean it, as this series focuses on spec conformance. We would like to
be to
> > get a little more SiFive code in QEMU 2.14 including a better model of
HiFive1
> > and HiFive Unleashed with the addition of more SiFive devices.
> >
> > Here are some of the future plans that we would like help with:
> >
> > - Add Cadence Ethernet to SiFive U for which there is already an
emulation
> > in QEMU.
> >  - This requires a device-tree dump from the HiFive Unleashed board
> > - Improve emulation accuracy of the SiFiveUART,
> >   - Need to add fifos and full RX/TX watemark interrupt support
> >   - Good documentation exists in the FE310G000 manual.
> >   - https://www.sifive.com/documentation/chips/freedom-e310-g000-manual/
> > - Implement GPIOs e.g. SiFiveGPIO
> >   - Good documentation for the SiFive GPIO exists in the FE310 manual
> >   - We would like to be able to playback VCD files (timestamp, pin) for
> > GPIO inputs
> >   - Potentially more advanced features where inputs are time synced or
> > state based on GPIO outputs
> >   - The intended application is interrupt controller and interrupt
service
> > routine test cases.
> > - Implement Watchdog e.g. SiFiveWatchdog
> >   - Good documentation for the SiFive Watchdog exists in the FE310
manual
> > - Add an option for Xilinx PCI to the sifive_u board (Freedom Unleashed
> > can by run on FPGA using Xilinx PCI)
> >   - The RTL for the Freedom on VC707 is here: https://github.com/
> > sifive/freedom/
> > - Change virt board to use the generic Linux based GPIO reset of
> > power-off device-tree nodes
> > - Add GPEX PCI host to the virt board so that we can use VirtIO PCI
> > - Improve the SOC object model for the RISC-V boards, with consideration
> > of the RISC-V ecosystem in general
> >   - We are trying to make the core generic so that any vendor can
> > implement custom CSRs
> >   - The SiFive E and SiFive U are generic boards that are intended to
> > emulate SiFive Core IP so should be configurable
> >   - We could add HiFive1 and HiFiveUnleashed boards but at the moment
> > SiFive E and SiFive U are binary compatible
> >   - i.e. this would ideally be implemented as subclassing a generic
> > heterogenous RISC-V Core Complex
> > - Add support for dynamic misa register changes and more spec
conformance
> > details
> >   - Requires a clean way to 'predicate' illegal instructions based on
> > presence of ISA extensions in translate.c
> >   - i.e. we don't what to add a who lot of if (!riscv_has_feature(ctx,
> > RVF)) ... raise exception
> >   - A metadata approach might be better so it can be handled
generically.
> > Need to study decode tree.
> > - Implement a prototype of the RISC-V Hypervisor specification as
outlined
> > in Privileged ISA v1.11
> > - Get our growing manual testing scenarios documented and then automated
> > to add to CI
> > - Lots more... this is just what comes to mind...
> >
> > Assuming the same development timeframe for QEMU 2.13, I guess we have
4-6
> > weeks to get our pending patches reviewed.
> >
> > As for the future plans, I guess given the time it takes for reviews
that
> > we would most likely target future development towards QEMU 2.14...
> > master and the riscv.org trees are now somewhat different so if other
> > major development is done in-tree then we'll need to port this to the
new
> > baseline in the riscv.org tree.
> >
> > If you are on the 'cc you've indicated interest in helping out with the
> > RISC-V or I'm thanking you on behalf of everyone involved in RISC-V and
> > QEMU with respect to past help with the port.
> >
> > I hope that we can conduct more development upstream and I encourage
folk
> > to review the code in this patch series.... time permitting. We have 4-6
> > weeks based on my experience with the last cycle.
> >
> > FYI - I wrote a little about getting the RISC-V QEMU port upstream:
> >
> > - https://www.sifive.com/blog/2018/04/25/risc-v-qemu-part-2-
> > the-risc-v-qemu-port-is-upstream/
> >
> > Thanks and Regards,
> > Michael
> >
> > On Thu, Apr 26, 2018 at 11:45 AM, Michael Clark <mjc@sifive.com> wrote:
> >
> >> 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 focuses on
> >> correct modelling of Privileged ISA v1.10. Earlier versions
> >> of the code had many unimplemented warnings in the control
> >> and status register code. The version submitted upstream
> >> replaced calls to exit with illegal instruction traps. The
> >> changes in this series focus on implementing correct
> >> behaviour, which in some cases is to ignore writes instead
> >> of trapping, and in other cases traps are generated based
> >> on the presence of CPU features or register settings such
> >> as misa.S and mstatus.TSR/TW/TVM. Several other bugs in
> >> the RISC-V QEMU issue tracker are addresssed.
> >>
> >> The branch for this patch series can be found here:
> >>
> >> - https://github.com/riscv/riscv-qemu/commits/qemu-2.13-for-upstream
> >>
> >> The RISC-V QEMU issues that are not yet resolved upstream:
> >>
> >> - https://github.com/riscv/riscv-qemu/issues
> >>
> >> Summary of changes
> >>
> >> * Implemented TSR, TW and TVM for privileged ISA v1.10
> >> * Update floating-point to correctly mark mstatus.FS dirty.
> >> * Implements WARL behavior for CSRs that don't support writes
> >>   * Past behavior of raising traps was non-conformant
> >>     with the RISC-V Privileged ISA Specition v1.10.
> >> * Sets mtval/stval to zero on exceptions without addresses
> >>   * Past behavior of leaving the last value was non-conformant
> >>     with the RISC-V Privileged ISA Specition v1.10. mtval/stval
> >>     must be set on all exceptions; to zero if not supported.
> >> * 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%.
> >> * Honour privileged ISA v1.10 counter enable CSRs.
> >> * 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 .
> >> * Make ROMs read-only and implement device-tree size checks
> >>   * Uses memory_region_init_rom and rom_add_blob_fixed_as
> >> * Adds hexidecimal instruction bytes to disassembly output.
> >> * Several code cleanups
> >>   * Replacing hard-coded constants with enums
> >>   * Dead-code elimination
> >>
> >> 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): pending
> >> * riscv-tests: pass
> >> * checkpatch: pass
> >>
> >> Changelog
> >>
> >> v8
> >>
> >> * Use riscv prefix consistently on all cpu helpers
> >> * Add hartid and \n to qemu_log in interrupt logging
> >> * Add missing return statement in gdbstub.c
> >> * Implemented TSR, TW and TVM for privileged ISA v1.10
> >> * Merged Richard Henderson's mstatus.fs dirty fix
> >> * Dropped mstatus.FS workaround
> >> * Implemented traps for s* CSR access on CPUs without S mode
> >> * Implemented traps for pmp* CSR access for CPUs without PMP
> >> * Made local interrupt delivery use atomic updates
> >> * Implemented modular CSR interface supporting atomic accesses
> >> * Implemented privileged ISA v1.10 counter enable CSRs
> >> * Fixed mask for sstatus.mxr field when priv ISA <= v1.9.1
> >> * Fixed User/Supervisor access bug in page table walker refactor
> >> * Updated physical address bits to match the priv ISA specification
> >> * Use memory_region_init_rom and rom_add_blob_fixed_as for mask roms
> >>
> >> v7
> >>
> >> * Fix typo in mstatus.FS workaround comment
> >> * Remove privilege mode from mstatus.mxr page protection check
> >> * Shift class initialization boilerplate patch hunk to correct patch
> >> * Fix typo in include instruction hex in disassembly commit message
> >>
> >> v6
> >>
> >> * Added workaround for critical mstatus.FS MTTCG bug
> >> * Added fix for incorrect disassembly of addiw
> >>
> >> v5
> >>
> >> * Dropped fix for memory allocation bug in riscv_isa_string
> >> * Dropped Hold rcu_read_lock when accessing memory
> >>
> >> v4
> >>
> >> * Added fix for memory allocation bug in riscv_isa_string
> >> * Trivial fix to remove erroneous comment from translate.c
> >>
> >> v3
> >>
> >> * Refactor rcu_read_lock in PTE update to use single unlock
> >> * Make mstatus.mxr take effect regardless of privilege mode
> >> * Remove unnecessary class init from riscv_hart
> >> * Set mtval/stval to zero on exceptions without addresses
> >>
> >> v2
> >>
> >> * Remove unused class boilerplate retains qom parent_obj
> >> * Convert cpu definition towards future model
> >> * Honor mstatus.mxr flag in page table walker
> >>
> >> v1
> >>
> >> * Initial post merge cleanup patch series
> >>
> >> Michael Clark (33):
> >>   RISC-V: Replace hardcoded constants with enum values
> >>   RISC-V: Make virt board description match spike
> >>   RISC-V: Use ROM base address and size from memmap
> >>   RISC-V: Remove identity_translate from load_elf
> >>   RISC-V: Remove unused class definitions
> >>   RISC-V: Include instruction hex in disassembly
> >>   RISC-V: Make some header guards more specific
> >>   RISC-V: Make virt header comment title consistent
> >>   RISC-V: Remove EM_RISCV ELF_MACHINE indirection
> >>   RISC-V: Remove erroneous comment from translate.c
> >>   RISC-V: Mark ROM read-only after copying in code
> >>   RISC-V: Update address bits to support sv39 and sv48
> >>   RISC-V: Improve page table walker spec compliance
> >>   RISC-V: Update E order and I extension order
> >>   RISC-V: Hardwire satp to 0 for no-mmu case
> >>   RISC-V: Make mtvec/stvec ignore vectored traps
> >>   RISC-V: No traps on writes to misa,minstret,mcycle
> >>   RISC-V: Clear mtval/stval on exceptions without info
> >>   RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
> >>   RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
> >>   RISC-V: Add mcycle/minstret support for -icount auto
> >>   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
> >>
> >> Richard Henderson (2):
> >>   RISC-V: Split out mstatus_fs from tb_flags
> >>   RISC-V: Mark mstatus.fs dirty
> >>
> >>  disas/riscv.c                           |  39 +-
> >>  hw/riscv/riscv_hart.c                   |   6 -
> >>  hw/riscv/sifive_clint.c                 |  17 +-
> >>  hw/riscv/sifive_e.c                     |  54 +-
> >>  hw/riscv/sifive_plic.c                  |  40 +-
> >>  hw/riscv/sifive_u.c                     |  86 ++--
> >>  hw/riscv/spike.c                        |  99 ++--
> >>  hw/riscv/virt.c                         |  80 +--
> >>  include/hw/riscv/sifive_clint.h         |   4 +
> >>  include/hw/riscv/sifive_e.h             |   5 -
> >>  include/hw/riscv/sifive_plic.h          |   1 -
> >>  include/hw/riscv/sifive_u.h             |   9 +-
> >>  include/hw/riscv/spike.h                |  15 +-
> >>  include/hw/riscv/virt.h                 |  13 +-
> >>  linux-user/signal.c                     |   4 +-
> >>  target/riscv/Makefile.objs              |   2 +-
> >>  target/riscv/cpu.c                      |   8 +-
> >>  target/riscv/cpu.h                      |  84 +--
> >>  target/riscv/cpu_bits.h                 | 690
+++++++++++++------------
> >>  target/riscv/{helper.c => cpu_helper.c} | 173 ++++---
> >>  target/riscv/csr.c                      | 871
> >> ++++++++++++++++++++++++++++++++
> >>  target/riscv/fpu_helper.c               |   6 +-
> >>  target/riscv/gdbstub.c                  |  10 +-
> >>  target/riscv/op_helper.c                | 613 ++--------------------
> >>  target/riscv/translate.c                |  53 +-
> >>  25 files changed, 1700 insertions(+), 1282 deletions(-)
> >>  rename target/riscv/{helper.c => cpu_helper.c} (73%)
> >>  create mode 100644 target/riscv/csr.c
> >>
> >> --
> >> 2.7.0
> >>
> >>
> >

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

* Re: [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10 Michael Clark
@ 2018-04-26 20:02   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 20:02 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:10 PM Michael Clark <mjc@sifive.com> wrote:

> The mstatus.MXR alias in sstatus should only be writable
> by S-mode if the privileged ISA version >= v1.10. Also MXR
> was masked in sstatus CSR read but not sstatus CSR writes.
> Now we correctly mask sstatus.mxr in both read and write.

> 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

> ---
>   target/riscv/op_helper.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)

> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index b81b9b6..88c263a 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -236,7 +236,10 @@ void csr_write_helper(CPURISCVState *env,
target_ulong val_to_write,
>           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_MXR | SSTATUS_SD;
> +            | 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;
> @@ -439,7 +442,7 @@ target_ulong csr_read_helper(CPURISCVState *env,
target_ulong csrno)
>       case CSR_SSTATUS: {
>           target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
>               | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
> -            | SSTATUS_SUM |  SSTATUS_SD;
> +            | SSTATUS_SUM | SSTATUS_SD;
>           if (env->priv_ver >= PRIV_VERSION_1_10_0) {
>               mask |= SSTATUS_MXR;
>           }
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto Michael Clark
@ 2018-04-26 20:05   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-26 20:05 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:59 PM Michael Clark <mjc@sifive.com> wrote:

> Previously the mycycle/minstret CSRs and rdcycle/rdinstret
> psuedo instructions would return the time as a proxy for an
> increasing instruction counter in the absence of having a
> precise instruction count. If QEMU is invoked with -icount,
> the mcycle/minstret CSRs and rdcycle/rdinstret psuedo
> instructions will return the instruction count.

> 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

> ---
>   target/riscv/op_helper.c | 24 ++++++++++++++++++++----
>   target/riscv/translate.c |  2 ++
>   2 files changed, 22 insertions(+), 4 deletions(-)

> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 2daf07c..7d3f1ee 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -433,25 +433,41 @@ target_ulong csr_read_helper(CPURISCVState *env,
target_ulong csrno)
>       case CSR_INSTRET:
>       case CSR_CYCLE:
>           if (ctr_ok) {
> -            return cpu_get_host_ticks();
> +            if (use_icount) {
> +                return cpu_get_icount();
> +            } else {
> +                return cpu_get_host_ticks();
> +            }
>           }
>           break;
>   #if defined(TARGET_RISCV32)
>       case CSR_INSTRETH:
>       case CSR_CYCLEH:
>           if (ctr_ok) {
> -            return cpu_get_host_ticks() >> 32;
> +            if (use_icount) {
> +                return cpu_get_icount() >> 32;
> +            } else {
> +                return cpu_get_host_ticks() >> 32;
> +            }
>           }
>           break;
>   #endif
>   #ifndef CONFIG_USER_ONLY
>       case CSR_MINSTRET:
>       case CSR_MCYCLE:
> -        return cpu_get_host_ticks();
> +        if (use_icount) {
> +            return cpu_get_icount();
> +        } else {
> +            return cpu_get_host_ticks();
> +        }
>       case CSR_MINSTRETH:
>       case CSR_MCYCLEH:
>   #if defined(TARGET_RISCV32)
> -        return cpu_get_host_ticks() >> 32;
> +        if (use_icount) {
> +            return cpu_get_icount() >> 32;
> +        } else {
> +            return cpu_get_host_ticks() >> 32;
> +        }
>   #endif
>           break;
>       case CSR_MUCOUNTEREN:
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index c3a029a..c0e6a04 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -1390,6 +1390,7 @@ static void gen_system(CPURISCVState *env,
DisasContext *ctx, uint32_t opc,
>           break;
>       default:
>           tcg_gen_movi_tl(imm_rs1, rs1);
> +        gen_io_start();
>           switch (opc) {
>           case OPC_RISC_CSRRW:
>               gen_helper_csrrw(dest, cpu_env, source1, csr_store);
> @@ -1413,6 +1414,7 @@ static void gen_system(CPURISCVState *env,
DisasContext *ctx, uint32_t opc,
>               gen_exception_illegal(ctx);
>               return;
>           }
> +        gen_io_end();
>           gen_set_gpr(rd, dest);
>           /* end tb since we may be changing priv modes, to get mmu_index
right */
>           tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
@ 2018-04-27  0:14   ` Richard Henderson
  2018-04-27  7:18     ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Richard Henderson @ 2018-04-27  0:14 UTC (permalink / raw)
  To: Michael Clark, qemu-devel
  Cc: Sagar Karandikar, Bastian Koppelmann, Palmer Dabbelt,
	Alistair Francis, patches

On 04/25/2018 01:45 PM, Michael Clark wrote:
> +    uint32_t old, new;
> +    do {
> +        old = atomic_read(&plic->pending[word]);
> +        new = (old & ~(1 << (irq & 31))) | (-!!pending & (1 << (irq & 31)));
> +    } while (atomic_cmpxchg(&plic->pending[word], old, new) != old);

I prefer

  uint32_t old, new, cmp = atomic_read(...);
  do {
    old = cmp;
    new = ...;
    cmp = atomic_cmpxchg(...);
  } while (old != cmp);

to avoid an extra load, should we loop.

That said, what you have is not wrong.  So,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-26 18:22     ` Alistair Francis
@ 2018-04-27  0:34       ` Michael Clark
  2018-04-27 10:19         ` Peter Maydell
  2018-04-27  0:35       ` Richard Henderson
  1 sibling, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-27  0:34 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Peter Maydell, Su Hang,
	Matthew Suozzo, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Richard Henderson, Emilio G. Cota,
	Alistair Francis, RISC-V Patches

On Fri, Apr 27, 2018 at 6:22 AM, Alistair Francis <alistair23@gmail.com>
wrote:

> On Wed, Apr 25, 2018 at 7:01 PM Michael Clark <mjc@sifive.com> wrote:
>
> > One last quick note.
>
> > We are tracking RISC-V QEMU issues in the riscv.org repo:
>
> > - https://github.com/riscv/riscv-qemu/issues
>
> > We have tagged issues that are resolved in the 'qemu-2.13-for-upstream'
> > branch (this branch can be rebased if we re-spin)
>
> > - https://github.com/riscv/riscv-qemu/tree/qemu-2.13-for-upstream
>
> > And we can now maintain a stable backport branch based on a major QEMU
> > release (where we plan to avoid rebasing)
>
> > - https://github.com/riscv/riscv-qemu/tree/riscv-qemu-2.12
>
> > We can make a PR for the first 9 patches as they are already reviewed,
> > however, the with this series is to gather review for the new baseline we
> > have in the riscv repo.
>
> I think it is worth sending a PR for the first 9 patches. The current
> master doesn't boot the sifive_u board and those patches will fix that.
> That also helps create a smaller patch series which is easier to review.


Okay. I'll do that.

I wasn't sure whether I was going to send this series out before or after
the 2.12 release and the remaining patches that need review depend on the
earlier patches. The reason was so that patchew could digest the series
i.e. if I sent out 26 patches that depend on changes made in the first 9
which weren't merged then patchew wouldn't be able to apply the series. It
seems patchew couldn't apply the series for some completely different
reason:

- https://patchew.org/QEMU/1524699938-6764-1-git-send-email-mjc@sifive.com/

The email and series was assembled of for-2.13 prior to 2.12 being released
and it wasn't appropriate to send a PR for 2.13 while 2.12 was in freeze
and we were focusing on critical fixes. Now things have changed so i'll
make a PR...

Michael.

Alistair
>
>
> > Note: the only conflicts in the current series we are likely to have are
> > Emilio's changes to translate.c, and I'm happy if those changes go in
> first
> > and we can rebase against them. The changes in the riscv repo are
> currently
> > all restricted to target/riscv and hw/riscv so there is little risk of
> > disruption to QEMU outside of the RISC-V ecosystem.
>
> > We haven't gone and implemented anything like generic bswap functions
> > generated using TCG, if TCG_TARGET_HAS_bswapnn_imm is not implemented by
> > the target, or TCG generated setcond2 and brcond2 so that large guest
> > support on 32-bit is transparent for targets that don't override the
> > defaults, so no worries about regressing the core. Yet... :-D
>
> > Michael.
>
> > On Thu, Apr 26, 2018 at 1:42 PM, Michael Clark <mjc@sifive.com> wrote:
>
> > > Hi All,
> > >
> > > As a first-time QEMU contributor, it was quite a challenge to get an
> > > entire port accepted upstream into QEMU. As folk who have followed the
> > > progress of the port will know; at moments my nerves got the better of
> me
> > > as we approached soft-freeze. In any case, I'd like to thank everyone
> who
> > > helped out with feedback and reviews.
> > >
> > > We now have quite a bit of RISC-V specific code targetting QEMU 2.13
> and
> > > are starting to plan development for QEMU 2.14. And when I say RISC-V,
> I
> > > mean it, as this series focuses on spec conformance. We would like to
> be to
> > > get a little more SiFive code in QEMU 2.14 including a better model of
> HiFive1
> > > and HiFive Unleashed with the addition of more SiFive devices.
> > >
> > > Here are some of the future plans that we would like help with:
> > >
> > > - Add Cadence Ethernet to SiFive U for which there is already an
> emulation
> > > in QEMU.
> > >  - This requires a device-tree dump from the HiFive Unleashed board
> > > - Improve emulation accuracy of the SiFiveUART,
> > >   - Need to add fifos and full RX/TX watemark interrupt support
> > >   - Good documentation exists in the FE310G000 manual.
> > >   - https://www.sifive.com/documentation/chips/freedom-
> e310-g000-manual/
> > > - Implement GPIOs e.g. SiFiveGPIO
> > >   - Good documentation for the SiFive GPIO exists in the FE310 manual
> > >   - We would like to be able to playback VCD files (timestamp, pin) for
> > > GPIO inputs
> > >   - Potentially more advanced features where inputs are time synced or
> > > state based on GPIO outputs
> > >   - The intended application is interrupt controller and interrupt
> service
> > > routine test cases.
> > > - Implement Watchdog e.g. SiFiveWatchdog
> > >   - Good documentation for the SiFive Watchdog exists in the FE310
> manual
> > > - Add an option for Xilinx PCI to the sifive_u board (Freedom Unleashed
> > > can by run on FPGA using Xilinx PCI)
> > >   - The RTL for the Freedom on VC707 is here: https://github.com/
> > > sifive/freedom/
> > > - Change virt board to use the generic Linux based GPIO reset of
> > > power-off device-tree nodes
> > > - Add GPEX PCI host to the virt board so that we can use VirtIO PCI
> > > - Improve the SOC object model for the RISC-V boards, with
> consideration
> > > of the RISC-V ecosystem in general
> > >   - We are trying to make the core generic so that any vendor can
> > > implement custom CSRs
> > >   - The SiFive E and SiFive U are generic boards that are intended to
> > > emulate SiFive Core IP so should be configurable
> > >   - We could add HiFive1 and HiFiveUnleashed boards but at the moment
> > > SiFive E and SiFive U are binary compatible
> > >   - i.e. this would ideally be implemented as subclassing a generic
> > > heterogenous RISC-V Core Complex
> > > - Add support for dynamic misa register changes and more spec
> conformance
> > > details
> > >   - Requires a clean way to 'predicate' illegal instructions based on
> > > presence of ISA extensions in translate.c
> > >   - i.e. we don't what to add a who lot of if (!riscv_has_feature(ctx,
> > > RVF)) ... raise exception
> > >   - A metadata approach might be better so it can be handled
> generically.
> > > Need to study decode tree.
> > > - Implement a prototype of the RISC-V Hypervisor specification as
> outlined
> > > in Privileged ISA v1.11
> > > - Get our growing manual testing scenarios documented and then
> automated
> > > to add to CI
> > > - Lots more... this is just what comes to mind...
> > >
> > > Assuming the same development timeframe for QEMU 2.13, I guess we have
> 4-6
> > > weeks to get our pending patches reviewed.
> > >
> > > As for the future plans, I guess given the time it takes for reviews
> that
> > > we would most likely target future development towards QEMU 2.14...
> > > master and the riscv.org trees are now somewhat different so if other
> > > major development is done in-tree then we'll need to port this to the
> new
> > > baseline in the riscv.org tree.
> > >
> > > If you are on the 'cc you've indicated interest in helping out with the
> > > RISC-V or I'm thanking you on behalf of everyone involved in RISC-V and
> > > QEMU with respect to past help with the port.
> > >
> > > I hope that we can conduct more development upstream and I encourage
> folk
> > > to review the code in this patch series.... time permitting. We have
> 4-6
> > > weeks based on my experience with the last cycle.
> > >
> > > FYI - I wrote a little about getting the RISC-V QEMU port upstream:
> > >
> > > - https://www.sifive.com/blog/2018/04/25/risc-v-qemu-part-2-
> > > the-risc-v-qemu-port-is-upstream/
> > >
> > > Thanks and Regards,
> > > Michael
> > >
> > > On Thu, Apr 26, 2018 at 11:45 AM, Michael Clark <mjc@sifive.com>
> wrote:
> > >
> > >> 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 focuses on
> > >> correct modelling of Privileged ISA v1.10. Earlier versions
> > >> of the code had many unimplemented warnings in the control
> > >> and status register code. The version submitted upstream
> > >> replaced calls to exit with illegal instruction traps. The
> > >> changes in this series focus on implementing correct
> > >> behaviour, which in some cases is to ignore writes instead
> > >> of trapping, and in other cases traps are generated based
> > >> on the presence of CPU features or register settings such
> > >> as misa.S and mstatus.TSR/TW/TVM. Several other bugs in
> > >> the RISC-V QEMU issue tracker are addresssed.
> > >>
> > >> The branch for this patch series can be found here:
> > >>
> > >> - https://github.com/riscv/riscv-qemu/commits/qemu-2.13-for-upstream
> > >>
> > >> The RISC-V QEMU issues that are not yet resolved upstream:
> > >>
> > >> - https://github.com/riscv/riscv-qemu/issues
> > >>
> > >> Summary of changes
> > >>
> > >> * Implemented TSR, TW and TVM for privileged ISA v1.10
> > >> * Update floating-point to correctly mark mstatus.FS dirty.
> > >> * Implements WARL behavior for CSRs that don't support writes
> > >>   * Past behavior of raising traps was non-conformant
> > >>     with the RISC-V Privileged ISA Specition v1.10.
> > >> * Sets mtval/stval to zero on exceptions without addresses
> > >>   * Past behavior of leaving the last value was non-conformant
> > >>     with the RISC-V Privileged ISA Specition v1.10. mtval/stval
> > >>     must be set on all exceptions; to zero if not supported.
> > >> * 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%.
> > >> * Honour privileged ISA v1.10 counter enable CSRs.
> > >> * 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 .
> > >> * Make ROMs read-only and implement device-tree size checks
> > >>   * Uses memory_region_init_rom and rom_add_blob_fixed_as
> > >> * Adds hexidecimal instruction bytes to disassembly output.
> > >> * Several code cleanups
> > >>   * Replacing hard-coded constants with enums
> > >>   * Dead-code elimination
> > >>
> > >> 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): pending
> > >> * riscv-tests: pass
> > >> * checkpatch: pass
> > >>
> > >> Changelog
> > >>
> > >> v8
> > >>
> > >> * Use riscv prefix consistently on all cpu helpers
> > >> * Add hartid and \n to qemu_log in interrupt logging
> > >> * Add missing return statement in gdbstub.c
> > >> * Implemented TSR, TW and TVM for privileged ISA v1.10
> > >> * Merged Richard Henderson's mstatus.fs dirty fix
> > >> * Dropped mstatus.FS workaround
> > >> * Implemented traps for s* CSR access on CPUs without S mode
> > >> * Implemented traps for pmp* CSR access for CPUs without PMP
> > >> * Made local interrupt delivery use atomic updates
> > >> * Implemented modular CSR interface supporting atomic accesses
> > >> * Implemented privileged ISA v1.10 counter enable CSRs
> > >> * Fixed mask for sstatus.mxr field when priv ISA <= v1.9.1
> > >> * Fixed User/Supervisor access bug in page table walker refactor
> > >> * Updated physical address bits to match the priv ISA specification
> > >> * Use memory_region_init_rom and rom_add_blob_fixed_as for mask roms
> > >>
> > >> v7
> > >>
> > >> * Fix typo in mstatus.FS workaround comment
> > >> * Remove privilege mode from mstatus.mxr page protection check
> > >> * Shift class initialization boilerplate patch hunk to correct patch
> > >> * Fix typo in include instruction hex in disassembly commit message
> > >>
> > >> v6
> > >>
> > >> * Added workaround for critical mstatus.FS MTTCG bug
> > >> * Added fix for incorrect disassembly of addiw
> > >>
> > >> v5
> > >>
> > >> * Dropped fix for memory allocation bug in riscv_isa_string
> > >> * Dropped Hold rcu_read_lock when accessing memory
> > >>
> > >> v4
> > >>
> > >> * Added fix for memory allocation bug in riscv_isa_string
> > >> * Trivial fix to remove erroneous comment from translate.c
> > >>
> > >> v3
> > >>
> > >> * Refactor rcu_read_lock in PTE update to use single unlock
> > >> * Make mstatus.mxr take effect regardless of privilege mode
> > >> * Remove unnecessary class init from riscv_hart
> > >> * Set mtval/stval to zero on exceptions without addresses
> > >>
> > >> v2
> > >>
> > >> * Remove unused class boilerplate retains qom parent_obj
> > >> * Convert cpu definition towards future model
> > >> * Honor mstatus.mxr flag in page table walker
> > >>
> > >> v1
> > >>
> > >> * Initial post merge cleanup patch series
> > >>
> > >> Michael Clark (33):
> > >>   RISC-V: Replace hardcoded constants with enum values
> > >>   RISC-V: Make virt board description match spike
> > >>   RISC-V: Use ROM base address and size from memmap
> > >>   RISC-V: Remove identity_translate from load_elf
> > >>   RISC-V: Remove unused class definitions
> > >>   RISC-V: Include instruction hex in disassembly
> > >>   RISC-V: Make some header guards more specific
> > >>   RISC-V: Make virt header comment title consistent
> > >>   RISC-V: Remove EM_RISCV ELF_MACHINE indirection
> > >>   RISC-V: Remove erroneous comment from translate.c
> > >>   RISC-V: Mark ROM read-only after copying in code
> > >>   RISC-V: Update address bits to support sv39 and sv48
> > >>   RISC-V: Improve page table walker spec compliance
> > >>   RISC-V: Update E order and I extension order
> > >>   RISC-V: Hardwire satp to 0 for no-mmu case
> > >>   RISC-V: Make mtvec/stvec ignore vectored traps
> > >>   RISC-V: No traps on writes to misa,minstret,mcycle
> > >>   RISC-V: Clear mtval/stval on exceptions without info
> > >>   RISC-V: Allow S-mode mxr access when priv ISA >= v1.10
> > >>   RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10
> > >>   RISC-V: Add mcycle/minstret support for -icount auto
> > >>   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
> > >>
> > >> Richard Henderson (2):
> > >>   RISC-V: Split out mstatus_fs from tb_flags
> > >>   RISC-V: Mark mstatus.fs dirty
> > >>
> > >>  disas/riscv.c                           |  39 +-
> > >>  hw/riscv/riscv_hart.c                   |   6 -
> > >>  hw/riscv/sifive_clint.c                 |  17 +-
> > >>  hw/riscv/sifive_e.c                     |  54 +-
> > >>  hw/riscv/sifive_plic.c                  |  40 +-
> > >>  hw/riscv/sifive_u.c                     |  86 ++--
> > >>  hw/riscv/spike.c                        |  99 ++--
> > >>  hw/riscv/virt.c                         |  80 +--
> > >>  include/hw/riscv/sifive_clint.h         |   4 +
> > >>  include/hw/riscv/sifive_e.h             |   5 -
> > >>  include/hw/riscv/sifive_plic.h          |   1 -
> > >>  include/hw/riscv/sifive_u.h             |   9 +-
> > >>  include/hw/riscv/spike.h                |  15 +-
> > >>  include/hw/riscv/virt.h                 |  13 +-
> > >>  linux-user/signal.c                     |   4 +-
> > >>  target/riscv/Makefile.objs              |   2 +-
> > >>  target/riscv/cpu.c                      |   8 +-
> > >>  target/riscv/cpu.h                      |  84 +--
> > >>  target/riscv/cpu_bits.h                 | 690
> +++++++++++++------------
> > >>  target/riscv/{helper.c => cpu_helper.c} | 173 ++++---
> > >>  target/riscv/csr.c                      | 871
> > >> ++++++++++++++++++++++++++++++++
> > >>  target/riscv/fpu_helper.c               |   6 +-
> > >>  target/riscv/gdbstub.c                  |  10 +-
> > >>  target/riscv/op_helper.c                | 613 ++--------------------
> > >>  target/riscv/translate.c                |  53 +-
> > >>  25 files changed, 1700 insertions(+), 1282 deletions(-)
> > >>  rename target/riscv/{helper.c => cpu_helper.c} (73%)
> > >>  create mode 100644 target/riscv/csr.c
> > >>
> > >> --
> > >> 2.7.0
> > >>
> > >>
> > >
>

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-26 18:22     ` Alistair Francis
  2018-04-27  0:34       ` Michael Clark
@ 2018-04-27  0:35       ` Richard Henderson
  2018-04-27  5:00         ` Michael Clark
  1 sibling, 1 reply; 76+ messages in thread
From: Richard Henderson @ 2018-04-27  0:35 UTC (permalink / raw)
  To: Alistair Francis, Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Peter Maydell, suhang16,
	msuozzo, Sagar Karandikar, Bastian Koppelmann, palmer,
	Emilio G. Cota, Alistair Francis, patches

On 04/26/2018 08:22 AM, Alistair Francis wrote:
> On Wed, Apr 25, 2018 at 7:01 PM Michael Clark <mjc@sifive.com> wrote:
>> We can make a PR for the first 9 patches as they are already reviewed,
>> however, the with this series is to gather review for the new baseline we
>> have in the riscv repo.
> 
> I think it is worth sending a PR for the first 9 patches. The current
> master doesn't boot the sifive_u board and those patches will fix that.
> That also helps create a smaller patch series which is easier to review.

FYI, for patches that affect usability like this, you should also Cc:
qemu-stable@nongnu.org in your pull request.  That way they should be
cherry-picked from master into the 2.12.1 release.


r~

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-27  0:35       ` Richard Henderson
@ 2018-04-27  5:00         ` Michael Clark
  0 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-27  5:00 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Alistair Francis, qemu-devel@nongnu.org Developers,
	Peter Maydell, Su Hang, Matthew Suozzo, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Emilio G. Cota,
	Alistair Francis, RISC-V Patches

On Fri, Apr 27, 2018 at 12:35 PM, Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 04/26/2018 08:22 AM, Alistair Francis wrote:
> > On Wed, Apr 25, 2018 at 7:01 PM Michael Clark <mjc@sifive.com> wrote:
> >> We can make a PR for the first 9 patches as they are already reviewed,
> >> however, the with this series is to gather review for the new baseline
> we
> >> have in the riscv repo.
> >
> > I think it is worth sending a PR for the first 9 patches. The current
> > master doesn't boot the sifive_u board and those patches will fix that.
> > That also helps create a smaller patch series which is easier to review.
>
> FYI, for patches that affect usability like this, you should also Cc:
> qemu-stable@nongnu.org in your pull request.  That way they should be
> cherry-picked from master into the 2.12.1 release.
>

Ok I will. Thanks.

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-26 16:48   ` Alistair Francis
@ 2018-04-27  5:22     ` Michael Clark
  2018-04-27  5:34       ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-27  5:22 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	RISC-V Patches

On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <alistair23@gmail.com>
wrote:

> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:
>
> > The sifive_u machine already marks its ROM readonly. This fixes
> > the remaining boards. This commit also makes all boards use
> > mask_rom as the variable name for the ROM. This change also
> > makes space for the maximum device tree size size and adds
> > an explicit bounds check and error message.
>
> > 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_e.c     | 20 +++++++---------
> >   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
> >   hw/riscv/spike.c        | 64
> ++++++++++++++++++++++++++++---------------------
> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
> >   include/hw/riscv/virt.h |  4 ++++
> >   5 files changed, 93 insertions(+), 79 deletions(-)
>
> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> > index 39e4cb4..0c8b8e9 100644
> > --- a/hw/riscv/sifive_e.c
> > +++ b/hw/riscv/sifive_e.c
> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
> >   };
>
> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> > -{
> > -    int i;
> > -    for (i = 0; i < (len >> 2); i++) {
> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> > -    }
> > -}
> > -
> >   static uint64_t load_kernel(const char *kernel_filename)
> >   {
> >       uint64_t kernel_entry, kernel_high;
> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
> *machine)
> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
> > +    int i;
>
> >       /* Initialize SOC */
> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
> *machine)
> >           memmap[SIFIVE_E_DTIM].base, main_mem);
>
> >       /* Mask ROM */
> > -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
> >       memory_region_add_subregion(sys_mem,
> >           memmap[SIFIVE_E_MROM].base, mask_rom);
> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
> *machine)
> >           0x00028067,        /* 0x1004: jr      t0 */
> >       };
>
> > -    /* copy in the reset vector */
> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
> sizeof(reset_vec));
> > -    memory_region_set_readonly(mask_rom, true);
> > +    /* copy in the reset vector in little_endian byte order */
> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > +    }
> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> > +                          memmap[SIFIVE_E_MROM].base,
> &address_space_memory);
>
> >       if (machine->kernel_filename) {
> >           load_kernel(machine->kernel_filename);
> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> > index 115618b..11ba4c3 100644
> > --- a/hw/riscv/sifive_u.c
> > +++ b/hw/riscv/sifive_u.c
> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
> >       hwaddr size;
> >   } sifive_u_memmap[] = {
> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
> >   };
>
> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> > -{
> > -    int i;
> > -    for (i = 0; i < (len >> 2); i++) {
> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> > -    }
> > -}
> > -
> >   static uint64_t load_kernel(const char *kernel_filename)
> >   {
> >       uint64_t kernel_entry, kernel_high;
> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
> *machine)
> >       const struct MemmapEntry *memmap = sifive_u_memmap;
>
> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
> > -    MemoryRegion *sys_memory = get_system_memory();
> > +    MemoryRegion *system_memory = get_system_memory();
> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > +    int i;
>
> >       /* Initialize SOC */
> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> > @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
> *machine)
> >       /* register RAM */
> >       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
> >                              machine->ram_size, &error_fatal);
> > -    memory_region_add_subregion(sys_memory, memmap[SIFIVE_U_DRAM].base,
> > +    memory_region_add_subregion(system_memory,
> memmap[SIFIVE_U_DRAM].base,
> >           main_mem);
>
> >       /* create device tree */
> >       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
>
> >       /* boot rom */
> > -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
> > -                           memmap[SIFIVE_U_MROM].base, &error_fatal);
> > -    memory_region_set_readonly(boot_rom, true);
> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
> > +                           memmap[SIFIVE_U_MROM].size, &error_fatal);
> > +    memory_region_add_subregion(system_memory,
> memmap[SIFIVE_U_MROM].base,
> > +                                mask_rom);
>
> >       if (machine->kernel_filename) {
> >           load_kernel(machine->kernel_filename);
> > @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
> *machine)
> >                                          /* dtb: */
> >       };
>
> > -    /* copy in the reset vector */
> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
> sizeof(reset_vec));
> > +    /* copy in the reset vector in little_endian byte order */
> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > +    }
> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> > +                          memmap[SIFIVE_U_MROM].base,
> &address_space_memory);
>
> >       /* copy in the device tree */
> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
> > +        error_report("qemu: not enough space to store device-tree");
> > +        exit(1);
> > +    }
> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > +                          memmap[SIFIVE_U_MROM].base +
> sizeof(reset_vec),
> > +                          &address_space_memory);
>
> >       /* MMIO */
> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
> *machine)
> >           SIFIVE_U_PLIC_CONTEXT_BASE,
> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
> >           memmap[SIFIVE_U_PLIC].size);
> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
> > +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
> >           serial_hds[0], SIFIVE_PLIC(s->plic)->irqs[
> SIFIVE_U_UART0_IRQ]);
> > -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
> > +    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
> >           serial_hds[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,
> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> > index 3f6bd0a..d1dbe6b 100644
> > --- a/hw/riscv/spike.c
> > +++ b/hw/riscv/spike.c
> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
> >       hwaddr base;
> >       hwaddr size;
> >   } spike_memmap[] = {
> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
> >   };
>
> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> > -{
> > -    int i;
> > -    for (i = 0; i < (len >> 2); i++) {
> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> > -    }
> > -}
> > -
> >   static uint64_t load_kernel(const char *kernel_filename)
> >   {
> >       uint64_t kernel_entry, kernel_high;
> > @@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(MachineState
> *machine)
> >       SpikeState *s = g_new0(SpikeState, 1);
> >       MemoryRegion *system_memory = get_system_memory();
> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > +    int i;
>
> >       /* Initialize SOC */
> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> > @@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(MachineState
> *machine)
> >       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
>
> >       /* boot rom */
> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> > -                           s->fdt_size + 0x2000, &error_fatal);
> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> > +                           memmap[SPIKE_MROM].size, &error_fatal);
> > +    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
> > +                                mask_rom);
>
> >       if (machine->kernel_filename) {
> >           load_kernel(machine->kernel_filename);
> > @@ -221,16 +215,25 @@ static void spike_v1_10_0_board_init(MachineState
> *machine)
> >                                        /* dtb: */
> >       };
>
> > -    /* copy in the reset vector */
> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> sizeof(reset_vec));
> > +    /* copy in the reset vector in little_endian byte order */
> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > +    }
> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> > +                          memmap[SPIKE_MROM].base,
> &address_space_memory);
>
> >       /* copy in the device tree */
> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
> > +        error_report("qemu: not enough space to store device-tree");
> > +        exit(1);
> > +    }
> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> sizeof(reset_vec),
> > -        s->fdt, s->fdt_size);
> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
> > +                          &address_space_memory);
>
> >       /* initialize HTIF using symbols found in load_kernel */
> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> serial_hds[0]);
> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> serial_hds[0]);
>
> >       /* Core Local Interruptor (timer and IPI) */
> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> memmap[SPIKE_CLINT].size,
> > @@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(MachineState
> *machine)
> >       SpikeState *s = g_new0(SpikeState, 1);
> >       MemoryRegion *system_memory = get_system_memory();
> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > +    int i;
>
> >       /* Initialize SOC */
> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
> > @@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(MachineState
> *machine)
> >           main_mem);
>
> >       /* boot rom */
> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> > -                           0x40000, &error_fatal);
> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> > +                           memmap[SPIKE_MROM].size, &error_fatal);
> > +    memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
> > +                                mask_rom);
>
> >       if (machine->kernel_filename) {
> >           load_kernel(machine->kernel_filename);
> > @@ -319,15 +324,20 @@ static void spike_v1_09_1_board_init(MachineState
> *machine)
> >       g_free(isa);
> >       size_t config_string_len = strlen(config_string);
>
> > -    /* copy in the reset vector */
> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> sizeof(reset_vec));
> > +    /* copy in the reset vector in little_endian byte order */
> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > +    }
> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> > +                          memmap[SPIKE_MROM].base,
> &address_space_memory);
>
> >       /* copy in the config string */
> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> sizeof(reset_vec),
> > -        config_string, config_string_len);
> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
> config_string_len,
> > +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
> > +                          &address_space_memory);
>
> >       /* initialize HTIF using symbols found in load_kernel */
> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> serial_hds[0]);
> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> serial_hds[0]);
>
> >       /* Core Local Interruptor (timer and IPI) */
> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> memmap[SPIKE_CLINT].size,
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index 090befe..20c509d 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
> >       hwaddr size;
> >   } virt_memmap[] = {
> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
> >   };
>
> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> > -{
> > -    int i;
> > -    for (i = 0; i < (len >> 2); i++) {
> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> > -    }
> > -}
> > -
> >   static uint64_t load_kernel(const char *kernel_filename)
> >   {
> >       uint64_t kernel_entry, kernel_high;
> > @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
> *machine)
> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
> >       MemoryRegion *system_memory = get_system_memory();
> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >       char *plic_hart_config;
> >       size_t plic_hart_config_len;
> >       int i;
> > @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
> *machine)
> >       fdt = create_fdt(s, memmap, machine->ram_size,
> machine->kernel_cmdline);
>
> >       /* boot rom */
> > -    memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom",
> > -                           s->fdt_size + 0x2000, &error_fatal);
> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > +    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
> > +                           memmap[VIRT_MROM].size, &error_fatal);
> > +    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);
> > @@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState
> *machine)
> >                                        /* dtb: */
> >       };
>
> > -    /* copy in the reset vector */
> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
> sizeof(reset_vec));
> > +    /* copy in the reset vector in little_endian byte order */
> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > +    }
> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
> > +                          memmap[VIRT_MROM].base,
> &address_space_memory);
>
> >       /* copy in the device tree */
> > +    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
> > +        error_report("qemu: not enough space to store device-tree");
> > +        exit(1);
> > +    }
> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
> sizeof(reset_vec),
> > -        s->fdt, s->fdt_size);
> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > +                          memmap[VIRT_MROM].base + sizeof(reset_vec),
> > +                          &address_space_memory);
>
> >       /* create PLIC hart topology configuration string */
> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
> smp_cpus;
> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> > index 91163d6..6f2668e 100644
> > --- a/include/hw/riscv/virt.h
> > +++ b/include/hw/riscv/virt.h
> > @@ -19,6 +19,10 @@
> >   #ifndef HW_RISCV_VIRT_H
> >   #define HW_RISCV_VIRT_H
>
> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
> > +#define VIRT(obj) \
> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
> > +
>
> This should be in a seperate patch.


I'll shift that chunk into "Remove unused class definitions".


> Alistair
>
> >   typedef struct {
> >       /*< private >*/
> >       SysBusDevice parent_obj;
> > --
> > 2.7.0
>

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-27  5:22     ` Michael Clark
@ 2018-04-27  5:34       ` Michael Clark
  2018-04-27 16:17         ` Alistair Francis
  0 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-04-27  5:34 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	RISC-V Patches

On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com> wrote:

>
>
> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <alistair23@gmail.com>
> wrote:
>
>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:
>>
>> > The sifive_u machine already marks its ROM readonly. This fixes
>> > the remaining boards. This commit also makes all boards use
>> > mask_rom as the variable name for the ROM. This change also
>> > makes space for the maximum device tree size size and adds
>> > an explicit bounds check and error message.
>>
>> > 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_e.c     | 20 +++++++---------
>> >   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
>> >   hw/riscv/spike.c        | 64
>> ++++++++++++++++++++++++++++---------------------
>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
>> >   include/hw/riscv/virt.h |  4 ++++
>> >   5 files changed, 93 insertions(+), 79 deletions(-)
>>
>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
>> > index 39e4cb4..0c8b8e9 100644
>> > --- a/hw/riscv/sifive_e.c
>> > +++ b/hw/riscv/sifive_e.c
>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
>> >   };
>>
>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>> > -{
>> > -    int i;
>> > -    for (i = 0; i < (len >> 2); i++) {
>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> > -    }
>> > -}
>> > -
>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >   {
>> >       uint64_t kernel_entry, kernel_high;
>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
>> *machine)
>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
>> > +    int i;
>>
>> >       /* Initialize SOC */
>> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
>> *machine)
>> >           memmap[SIFIVE_E_DTIM].base, main_mem);
>>
>> >       /* Mask ROM */
>> > -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
>> >       memory_region_add_subregion(sys_mem,
>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
>> *machine)
>> >           0x00028067,        /* 0x1004: jr      t0 */
>> >       };
>>
>> > -    /* copy in the reset vector */
>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
>> sizeof(reset_vec));
>> > -    memory_region_set_readonly(mask_rom, true);
>> > +    /* copy in the reset vector in little_endian byte order */
>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> > +    }
>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>> > +                          memmap[SIFIVE_E_MROM].base,
>> &address_space_memory);
>>
>> >       if (machine->kernel_filename) {
>> >           load_kernel(machine->kernel_filename);
>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
>> > index 115618b..11ba4c3 100644
>> > --- a/hw/riscv/sifive_u.c
>> > +++ b/hw/riscv/sifive_u.c
>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
>> >       hwaddr size;
>> >   } sifive_u_memmap[] = {
>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
>> >   };
>>
>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>> > -{
>> > -    int i;
>> > -    for (i = 0; i < (len >> 2); i++) {
>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> > -    }
>> > -}
>> > -
>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >   {
>> >       uint64_t kernel_entry, kernel_high;
>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
>> *machine)
>> >       const struct MemmapEntry *memmap = sifive_u_memmap;
>>
>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
>> > -    MemoryRegion *sys_memory = get_system_memory();
>> > +    MemoryRegion *system_memory = get_system_memory();
>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> > +    int i;
>>
>> >       /* Initialize SOC */
>> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
>> > @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
>> *machine)
>> >       /* register RAM */
>> >       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
>> >                              machine->ram_size, &error_fatal);
>> > -    memory_region_add_subregion(sys_memory,
>> memmap[SIFIVE_U_DRAM].base,
>> > +    memory_region_add_subregion(system_memory,
>> memmap[SIFIVE_U_DRAM].base,
>> >           main_mem);
>>
>> >       /* create device tree */
>> >       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
>>
>> >       /* boot rom */
>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
>> > -                           memmap[SIFIVE_U_MROM].base, &error_fatal);
>> > -    memory_region_set_readonly(boot_rom, true);
>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
>> > +                           memmap[SIFIVE_U_MROM].size, &error_fatal);
>> > +    memory_region_add_subregion(system_memory,
>> memmap[SIFIVE_U_MROM].base,
>> > +                                mask_rom);
>>
>> >       if (machine->kernel_filename) {
>> >           load_kernel(machine->kernel_filename);
>> > @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
>> *machine)
>> >                                          /* dtb: */
>> >       };
>>
>> > -    /* copy in the reset vector */
>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
>> sizeof(reset_vec));
>> > +    /* copy in the reset vector in little_endian byte order */
>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> > +    }
>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>> > +                          memmap[SIFIVE_U_MROM].base,
>> &address_space_memory);
>>
>> >       /* copy in the device tree */
>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size - sizeof(reset_vec))
>> {
>> > +        error_report("qemu: not enough space to store device-tree");
>> > +        exit(1);
>> > +    }
>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> > +                          memmap[SIFIVE_U_MROM].base +
>> sizeof(reset_vec),
>> > +                          &address_space_memory);
>>
>> >       /* MMIO */
>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
>> *machine)
>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
>> >           memmap[SIFIVE_U_PLIC].size);
>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
>> > +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
>> >           serial_hds[0], SIFIVE_PLIC(s->plic)->irqs[SIF
>> IVE_U_UART0_IRQ]);
>> > -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
>> > +    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
>> >           serial_hds[1], SIFIVE_PLIC(s->plic)->irqs[SIF
>> IVE_U_UART1_IRQ]);
>> */
>> >       sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
>> >           memmap[SIFIVE_U_CLINT].size, smp_cpus,
>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
>> > index 3f6bd0a..d1dbe6b 100644
>> > --- a/hw/riscv/spike.c
>> > +++ b/hw/riscv/spike.c
>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
>> >       hwaddr base;
>> >       hwaddr size;
>> >   } spike_memmap[] = {
>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
>> >   };
>>
>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>> > -{
>> > -    int i;
>> > -    for (i = 0; i < (len >> 2); i++) {
>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> > -    }
>> > -}
>> > -
>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >   {
>> >       uint64_t kernel_entry, kernel_high;
>> > @@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(MachineState
>> *machine)
>> >       SpikeState *s = g_new0(SpikeState, 1);
>> >       MemoryRegion *system_memory = get_system_memory();
>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> > +    int i;
>>
>> >       /* Initialize SOC */
>> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
>> > @@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(MachineState
>> *machine)
>> >       create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
>>
>> >       /* boot rom */
>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>> > -                           s->fdt_size + 0x2000, &error_fatal);
>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>> > +    memory_region_add_subregion(system_memory,
>> memmap[SPIKE_MROM].base,
>> > +                                mask_rom);
>>
>> >       if (machine->kernel_filename) {
>> >           load_kernel(machine->kernel_filename);
>> > @@ -221,16 +215,25 @@ static void spike_v1_10_0_board_init(MachineState
>> *machine)
>> >                                        /* dtb: */
>> >       };
>>
>> > -    /* copy in the reset vector */
>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>> sizeof(reset_vec));
>> > +    /* copy in the reset vector in little_endian byte order */
>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> > +    }
>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>> > +                          memmap[SPIKE_MROM].base,
>> &address_space_memory);
>>
>> >       /* copy in the device tree */
>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
>> > +        error_report("qemu: not enough space to store device-tree");
>> > +        exit(1);
>> > +    }
>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>> sizeof(reset_vec),
>> > -        s->fdt, s->fdt_size);
>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> > +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
>> > +                          &address_space_memory);
>>
>> >       /* initialize HTIF using symbols found in load_kernel */
>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>> serial_hds[0]);
>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>> serial_hds[0]);
>>
>> >       /* Core Local Interruptor (timer and IPI) */
>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>> memmap[SPIKE_CLINT].size,
>> > @@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(MachineState
>> *machine)
>> >       SpikeState *s = g_new0(SpikeState, 1);
>> >       MemoryRegion *system_memory = get_system_memory();
>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> > +    int i;
>>
>> >       /* Initialize SOC */
>> >       object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
>> > @@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(MachineState
>> *machine)
>> >           main_mem);
>>
>> >       /* boot rom */
>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>> > -                           0x40000, &error_fatal);
>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>> > +    memory_region_add_subregion(system_memory,
>> memmap[SPIKE_MROM].base,
>> > +                                mask_rom);
>>
>> >       if (machine->kernel_filename) {
>> >           load_kernel(machine->kernel_filename);
>> > @@ -319,15 +324,20 @@ static void spike_v1_09_1_board_init(MachineState
>> *machine)
>> >       g_free(isa);
>> >       size_t config_string_len = strlen(config_string);
>>
>> > -    /* copy in the reset vector */
>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>> sizeof(reset_vec));
>> > +    /* copy in the reset vector in little_endian byte order */
>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> > +    }
>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>> > +                          memmap[SPIKE_MROM].base,
>> &address_space_memory);
>>
>> >       /* copy in the config string */
>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>> sizeof(reset_vec),
>> > -        config_string, config_string_len);
>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
>> config_string_len,
>> > +                          memmap[SPIKE_MROM].base + sizeof(reset_vec),
>> > +                          &address_space_memory);
>>
>> >       /* initialize HTIF using symbols found in load_kernel */
>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>> serial_hds[0]);
>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>> serial_hds[0]);
>>
>> >       /* Core Local Interruptor (timer and IPI) */
>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>> memmap[SPIKE_CLINT].size,
>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>> > index 090befe..20c509d 100644
>> > --- a/hw/riscv/virt.c
>> > +++ b/hw/riscv/virt.c
>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
>> >       hwaddr size;
>> >   } virt_memmap[] = {
>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
>> >   };
>>
>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>> > -{
>> > -    int i;
>> > -    for (i = 0; i < (len >> 2); i++) {
>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> > -    }
>> > -}
>> > -
>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >   {
>> >       uint64_t kernel_entry, kernel_high;
>> > @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
>> *machine)
>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
>> >       MemoryRegion *system_memory = get_system_memory();
>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >       char *plic_hart_config;
>> >       size_t plic_hart_config_len;
>> >       int i;
>> > @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
>> *machine)
>> >       fdt = create_fdt(s, memmap, machine->ram_size,
>> machine->kernel_cmdline);
>>
>> >       /* boot rom */
>> > -    memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom",
>> > -                           s->fdt_size + 0x2000, &error_fatal);
>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> > +    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
>> > +                           memmap[VIRT_MROM].size, &error_fatal);
>> > +    memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
>> > +                                mask_rom);
>>
>> >       if (machine->kernel_filename) {
>> >           uint64_t kernel_entry = load_kernel(machine->kernel_fi
>> lename);
>> > @@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState
>> *machine)
>> >                                        /* dtb: */
>> >       };
>>
>> > -    /* copy in the reset vector */
>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
>> sizeof(reset_vec));
>> > +    /* copy in the reset vector in little_endian byte order */
>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> > +    }
>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>> > +                          memmap[VIRT_MROM].base,
>> &address_space_memory);
>>
>> >       /* copy in the device tree */
>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
>> > +        error_report("qemu: not enough space to store device-tree");
>> > +        exit(1);
>> > +    }
>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
>> sizeof(reset_vec),
>> > -        s->fdt, s->fdt_size);
>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> > +                          memmap[VIRT_MROM].base + sizeof(reset_vec),
>> > +                          &address_space_memory);
>>
>> >       /* create PLIC hart topology configuration string */
>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
>> smp_cpus;
>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
>> > index 91163d6..6f2668e 100644
>> > --- a/include/hw/riscv/virt.h
>> > +++ b/include/hw/riscv/virt.h
>> > @@ -19,6 +19,10 @@
>> >   #ifndef HW_RISCV_VIRT_H
>> >   #define HW_RISCV_VIRT_H
>>
>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
>> > +#define VIRT(obj) \
>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
>> > +
>>
>> This should be in a seperate patch.
>
>
> I'll shift that chunk into "Remove unused class definitions".
>

Actually we to need to drop this chunk as the unused check macros were
removed from machine state structs in "Remove unused class definitions".
Somehow the chunk made it into this patch. Likely a rebase issue.

It's probably best that we add what we need back in the QOM SOC refactor
on-top of the this series, or at least after the first set of patches are
merged...

I think that's what you were planning to do anyway.

Thanks.
Michael.

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

* Re: [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
  2018-04-27  0:14   ` Richard Henderson
@ 2018-04-27  7:18     ` Michael Clark
  0 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-04-27  7:18 UTC (permalink / raw)
  To: Richard Henderson
  Cc: QEMU Developers, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Alistair Francis, RISC-V Patches

On Fri, Apr 27, 2018 at 12:14 PM, Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 04/25/2018 01:45 PM, Michael Clark wrote:
> > +    uint32_t old, new;
> > +    do {
> > +        old = atomic_read(&plic->pending[word]);
> > +        new = (old & ~(1 << (irq & 31))) | (-!!pending & (1 << (irq &
> 31)));
> > +    } while (atomic_cmpxchg(&plic->pending[word], old, new) != old);
>
> I prefer
>
>   uint32_t old, new, cmp = atomic_read(...);
>   do {
>     old = cmp;
>     new = ...;
>     cmp = atomic_cmpxchg(...);
>   } while (old != cmp);
>
> to avoid an extra load, should we loop.
>

Thanks. I've revised the code to use this convention.

I've also done so in "Implement atomic mip/sip CSR updates" which has the
same pattern.

That said, what you have is not wrong.  So,
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>
>
> r~
>

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

* Re: [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates
  2018-04-27  0:34       ` Michael Clark
@ 2018-04-27 10:19         ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2018-04-27 10:19 UTC (permalink / raw)
  To: Michael Clark
  Cc: Alistair Francis, qemu-devel@nongnu.org Developers, Su Hang,
	Matthew Suozzo, Sagar Karandikar, Bastian Koppelmann,
	Palmer Dabbelt, Richard Henderson, Emilio G. Cota,
	Alistair Francis, RISC-V Patches

On 27 April 2018 at 01:34, Michael Clark <mjc@sifive.com> wrote:
> I wasn't sure whether I was going to send this series out before or after
> the 2.12 release and the remaining patches that need review depend on the
> earlier patches. The reason was so that patchew could digest the series i.e.
> if I sent out 26 patches that depend on changes made in the first 9 which
> weren't merged then patchew wouldn't be able to apply the series.

Patchew has a feature to support that. In the second series, after
the '---' line you say
Based-on: <message-id-of-first-patchset-cover-letter>

and then patchew knows it needs to apply the first patchset before
trying to apply and test the second.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-27  5:34       ` Michael Clark
@ 2018-04-27 16:17         ` Alistair Francis
  2018-05-04  1:45           ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Alistair Francis @ 2018-04-27 16:17 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Thu, Apr 26, 2018 at 10:34 PM Michael Clark <mjc@sifive.com> wrote:



> On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com> wrote:



>> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <alistair23@gmail.com>
wrote:

>>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:

>>> > The sifive_u machine already marks its ROM readonly. This fixes
>>> > the remaining boards. This commit also makes all boards use
>>> > mask_rom as the variable name for the ROM. This change also
>>> > makes space for the maximum device tree size size and adds
>>> > an explicit bounds check and error message.

>>> > 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_e.c     | 20 +++++++---------
>>> >   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
>>> >   hw/riscv/spike.c        | 64
>>> ++++++++++++++++++++++++++++---------------------
>>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
>>> >   include/hw/riscv/virt.h |  4 ++++
>>> >   5 files changed, 93 insertions(+), 79 deletions(-)

>>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
>>> > index 39e4cb4..0c8b8e9 100644
>>> > --- a/hw/riscv/sifive_e.c
>>> > +++ b/hw/riscv/sifive_e.c
>>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
>>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
>>> >   };

>>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>>> > -{
>>> > -    int i;
>>> > -    for (i = 0; i < (len >> 2); i++) {
>>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>>> > -    }
>>> > -}
>>> > -
>>> >   static uint64_t load_kernel(const char *kernel_filename)
>>> >   {
>>> >       uint64_t kernel_entry, kernel_high;
>>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
*machine)
>>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
>>> > +    int i;

>>> >       /* Initialize SOC */
>>> >       object_initialize(&s->soc, sizeof(s->soc),
TYPE_RISCV_HART_ARRAY);
>>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
*machine)
>>> >           memmap[SIFIVE_E_DTIM].base, main_mem);

>>> >       /* Mask ROM */
>>> > -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
>>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
>>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
>>> >       memory_region_add_subregion(sys_mem,
>>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
>>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
>>> *machine)
>>> >           0x00028067,        /* 0x1004: jr      t0 */
>>> >       };

>>> > -    /* copy in the reset vector */
>>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
>>> sizeof(reset_vec));
>>> > -    memory_region_set_readonly(mask_rom, true);
>>> > +    /* copy in the reset vector in little_endian byte order */
>>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>>> > +    }
>>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>>> > +                          memmap[SIFIVE_E_MROM].base,
>>> &address_space_memory);

>>> >       if (machine->kernel_filename) {
>>> >           load_kernel(machine->kernel_filename);
>>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
>>> > index 115618b..11ba4c3 100644
>>> > --- a/hw/riscv/sifive_u.c
>>> > +++ b/hw/riscv/sifive_u.c
>>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
>>> >       hwaddr size;
>>> >   } sifive_u_memmap[] = {
>>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
>>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
>>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
>>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
>>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
>>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
>>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
>>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
>>> >   };

>>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>>> > -{
>>> > -    int i;
>>> > -    for (i = 0; i < (len >> 2); i++) {
>>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>>> > -    }
>>> > -}
>>> > -
>>> >   static uint64_t load_kernel(const char *kernel_filename)
>>> >   {
>>> >       uint64_t kernel_entry, kernel_high;
>>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
>>> *machine)
>>> >       const struct MemmapEntry *memmap = sifive_u_memmap;

>>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
>>> > -    MemoryRegion *sys_memory = get_system_memory();
>>> > +    MemoryRegion *system_memory = get_system_memory();
>>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>>> > +    int i;

>>> >       /* Initialize SOC */
>>> >       object_initialize(&s->soc, sizeof(s->soc),
TYPE_RISCV_HART_ARRAY);
>>> > @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
>>> *machine)
>>> >       /* register RAM */
>>> >       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
>>> >                              machine->ram_size, &error_fatal);
>>> > -    memory_region_add_subregion(sys_memory,
memmap[SIFIVE_U_DRAM].base,
>>> > +    memory_region_add_subregion(system_memory,
>>> memmap[SIFIVE_U_DRAM].base,
>>> >           main_mem);

>>> >       /* create device tree */
>>> >       create_fdt(s, memmap, machine->ram_size,
machine->kernel_cmdline);

>>> >       /* boot rom */
>>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
>>> > -                           memmap[SIFIVE_U_MROM].base, &error_fatal);
>>> > -    memory_region_set_readonly(boot_rom, true);
>>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
>>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
>>> > +                           memmap[SIFIVE_U_MROM].size, &error_fatal);
>>> > +    memory_region_add_subregion(system_memory,
>>> memmap[SIFIVE_U_MROM].base,
>>> > +                                mask_rom);

>>> >       if (machine->kernel_filename) {
>>> >           load_kernel(machine->kernel_filename);
>>> > @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
>>> *machine)
>>> >                                          /* dtb: */
>>> >       };

>>> > -    /* copy in the reset vector */
>>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
>>> sizeof(reset_vec));
>>> > +    /* copy in the reset vector in little_endian byte order */
>>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>>> > +    }
>>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>>> > +                          memmap[SIFIVE_U_MROM].base,
>>> &address_space_memory);

>>> >       /* copy in the device tree */
>>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size -
sizeof(reset_vec)) {
>>> > +        error_report("qemu: not enough space to store device-tree");
>>> > +        exit(1);
>>> > +    }
>>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
>>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
>>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>>> > +                          memmap[SIFIVE_U_MROM].base +
sizeof(reset_vec),
>>> > +                          &address_space_memory);

>>> >       /* MMIO */
>>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
>>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
*machine)
>>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
>>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
>>> >           memmap[SIFIVE_U_PLIC].size);
>>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
>>> > +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
>>> >           serial_hds[0],
SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
>>> > -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
>>> > +    /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
>>> >           serial_hds[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,
>>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
>>> > index 3f6bd0a..d1dbe6b 100644
>>> > --- a/hw/riscv/spike.c
>>> > +++ b/hw/riscv/spike.c
>>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
>>> >       hwaddr base;
>>> >       hwaddr size;
>>> >   } spike_memmap[] = {
>>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
>>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
>>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
>>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
>>> >   };

>>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>>> > -{
>>> > -    int i;
>>> > -    for (i = 0; i < (len >> 2); i++) {
>>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>>> > -    }
>>> > -}
>>> > -
>>> >   static uint64_t load_kernel(const char *kernel_filename)
>>> >   {
>>> >       uint64_t kernel_entry, kernel_high;
>>> > @@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(MachineState
>>> *machine)
>>> >       SpikeState *s = g_new0(SpikeState, 1);
>>> >       MemoryRegion *system_memory = get_system_memory();
>>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>>> > +    int i;

>>> >       /* Initialize SOC */
>>> >       object_initialize(&s->soc, sizeof(s->soc),
TYPE_RISCV_HART_ARRAY);
>>> > @@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(MachineState
>>> *machine)
>>> >       create_fdt(s, memmap, machine->ram_size,
machine->kernel_cmdline);

>>> >       /* boot rom */
>>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>>> > -                           s->fdt_size + 0x2000, &error_fatal);
>>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>>> > +    memory_region_add_subregion(system_memory,
memmap[SPIKE_MROM].base,
>>> > +                                mask_rom);

>>> >       if (machine->kernel_filename) {
>>> >           load_kernel(machine->kernel_filename);
>>> > @@ -221,16 +215,25 @@ static void
spike_v1_10_0_board_init(MachineState
>>> *machine)
>>> >                                        /* dtb: */
>>> >       };

>>> > -    /* copy in the reset vector */
>>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>>> sizeof(reset_vec));
>>> > +    /* copy in the reset vector in little_endian byte order */
>>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>>> > +    }
>>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>>> > +                          memmap[SPIKE_MROM].base,
>>> &address_space_memory);

>>> >       /* copy in the device tree */
>>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
>>> > +        error_report("qemu: not enough space to store device-tree");
>>> > +        exit(1);
>>> > +    }
>>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>>> sizeof(reset_vec),
>>> > -        s->fdt, s->fdt_size);
>>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>>> > +                          memmap[SPIKE_MROM].base +
sizeof(reset_vec),
>>> > +                          &address_space_memory);

>>> >       /* initialize HTIF using symbols found in load_kernel */
>>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>>> serial_hds[0]);
>>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>>> serial_hds[0]);

>>> >       /* Core Local Interruptor (timer and IPI) */
>>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>>> memmap[SPIKE_CLINT].size,
>>> > @@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(MachineState
>>> *machine)
>>> >       SpikeState *s = g_new0(SpikeState, 1);
>>> >       MemoryRegion *system_memory = get_system_memory();
>>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>>> > +    int i;

>>> >       /* Initialize SOC */
>>> >       object_initialize(&s->soc, sizeof(s->soc),
TYPE_RISCV_HART_ARRAY);
>>> > @@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(MachineState
>>> *machine)
>>> >           main_mem);

>>> >       /* boot rom */
>>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>>> > -                           0x40000, &error_fatal);
>>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>>> > +    memory_region_add_subregion(system_memory,
memmap[SPIKE_MROM].base,
>>> > +                                mask_rom);

>>> >       if (machine->kernel_filename) {
>>> >           load_kernel(machine->kernel_filename);
>>> > @@ -319,15 +324,20 @@ static void
spike_v1_09_1_board_init(MachineState
>>> *machine)
>>> >       g_free(isa);
>>> >       size_t config_string_len = strlen(config_string);

>>> > -    /* copy in the reset vector */
>>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>>> sizeof(reset_vec));
>>> > +    /* copy in the reset vector in little_endian byte order */
>>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>>> > +    }
>>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>>> > +                          memmap[SPIKE_MROM].base,
>>> &address_space_memory);

>>> >       /* copy in the config string */
>>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>>> sizeof(reset_vec),
>>> > -        config_string, config_string_len);
>>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
config_string_len,
>>> > +                          memmap[SPIKE_MROM].base +
sizeof(reset_vec),
>>> > +                          &address_space_memory);

>>> >       /* initialize HTIF using symbols found in load_kernel */
>>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>>> serial_hds[0]);
>>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>>> serial_hds[0]);

>>> >       /* Core Local Interruptor (timer and IPI) */
>>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>>> memmap[SPIKE_CLINT].size,
>>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>>> > index 090befe..20c509d 100644
>>> > --- a/hw/riscv/virt.c
>>> > +++ b/hw/riscv/virt.c
>>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
>>> >       hwaddr size;
>>> >   } virt_memmap[] = {
>>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
>>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
>>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
>>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
>>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
>>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
>>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
>>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
>>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
>>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
>>> >   };

>>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
>>> > -{
>>> > -    int i;
>>> > -    for (i = 0; i < (len >> 2); i++) {
>>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>>> > -    }
>>> > -}
>>> > -
>>> >   static uint64_t load_kernel(const char *kernel_filename)
>>> >   {
>>> >       uint64_t kernel_entry, kernel_high;
>>> > @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
>>> *machine)
>>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
>>> >       MemoryRegion *system_memory = get_system_memory();
>>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>>> >       char *plic_hart_config;
>>> >       size_t plic_hart_config_len;
>>> >       int i;
>>> > @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
>>> *machine)
>>> >       fdt = create_fdt(s, memmap, machine->ram_size,
>>> machine->kernel_cmdline);

>>> >       /* boot rom */
>>> > -    memory_region_init_ram(boot_rom, NULL,
"riscv_virt_board.bootrom",
>>> > -                           s->fdt_size + 0x2000, &error_fatal);
>>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>>> > +    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
>>> > +                           memmap[VIRT_MROM].size, &error_fatal);
>>> > +    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);
>>> > @@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState
>>> *machine)
>>> >                                        /* dtb: */
>>> >       };

>>> > -    /* copy in the reset vector */
>>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
>>> sizeof(reset_vec));
>>> > +    /* copy in the reset vector in little_endian byte order */
>>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>>> > +    }
>>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>>> > +                          memmap[VIRT_MROM].base,
&address_space_memory);

>>> >       /* copy in the device tree */
>>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
>>> > +        error_report("qemu: not enough space to store device-tree");
>>> > +        exit(1);
>>> > +    }
>>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
sizeof(reset_vec),
>>> > -        s->fdt, s->fdt_size);
>>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>>> > +                          memmap[VIRT_MROM].base + sizeof(reset_vec),
>>> > +                          &address_space_memory);

>>> >       /* create PLIC hart topology configuration string */
>>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
>>> smp_cpus;
>>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
>>> > index 91163d6..6f2668e 100644
>>> > --- a/include/hw/riscv/virt.h
>>> > +++ b/include/hw/riscv/virt.h
>>> > @@ -19,6 +19,10 @@
>>> >   #ifndef HW_RISCV_VIRT_H
>>> >   #define HW_RISCV_VIRT_H

>>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
>>> > +#define VIRT(obj) \
>>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
>>> > +

>>> This should be in a seperate patch.


>> I'll shift that chunk into "Remove unused class definitions".


> Actually we to need to drop this chunk as the unused check macros were
removed from machine state structs in "Remove unused class definitions".
Somehow the chunk made it into this patch. Likely a rebase issue.

> It's probably best that we add what we need back in the QOM SOC refactor
on-top of the this series, or at least after the first set of patches are
merged...

> I think that's what you were planning to do anyway.

Yeah, that works. So just remove it from this series.

Alistair


> Thanks.
> Michael.

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

* Re: [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
@ 2018-04-27 22:33   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-04-27 22:33 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:56 PM Michael Clark <mjc@sifive.com> 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>

Alistair

> ---
>   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 3b57e13..47d116e 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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance Michael Clark
@ 2018-05-03 20:49   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 20:49 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 4:50 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>

Alistair

> ---
>   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 64aa097..12b4757 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 02cbcea..459fc97 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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs Michael Clark
@ 2018-05-03 20:54   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 20:54 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:02 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>
> ---
>   hw/riscv/sifive_clint.c  |  8 ++++----
>   hw/riscv/sifive_plic.c   |  4 ++--
>   target/riscv/cpu.h       |  8 +++-----
>   target/riscv/op_helper.c | 23 ++++++++++++++---------
>   4 files changed, 23 insertions(+), 20 deletions(-)

> diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
> index 7cc606e..909929b 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, -1);

Using -1 for a mask seems nasty and confusing.

There is a QEMU macro MAKE_64BIT_MASK() that seems like a great fit for
this.

Alistair

>           return;
>       }

>       /* otherwise, set up the future timer interrupt */
> -    riscv_set_local_interrupt(cpu, MIP_MTIP, 0);
> +    riscv_cpu_update_mip(cpu, MIP_MTIP, 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, -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, -!!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 04e39e4..fa0298d 100644
> --- a/hw/riscv/sifive_plic.c
> +++ b/hw/riscv/sifive_plic.c
> @@ -141,10 +141,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, -!!level);
>               break;
>           case PLICMode_S:
> -            riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_SEIP, level);
> +            riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, -!!level);
>               break;
>           default:
>               break;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index e0608e6..5ac1482 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -247,7 +247,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 +255,9 @@ 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);
> +#endif
>   void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);

>   void riscv_translate_init(void);
> @@ -286,10 +288,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 7d3f1ee..2a7f045 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
> @@ -643,16 +641,23 @@ 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_mip, new_mip;

> -    if (cpu->env.mip && !old_mip) {
> +    do {
> +        old_mip = atomic_read(&env->mip);
> +        new_mip = (old_mip & ~mask) | (value & mask);
> +    } while (atomic_cmpxchg(&env->mip, old_mip, new_mip) != old_mip);
> +
> +    if (new_mip && !old_mip) {
>           cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> -    } else if (!cpu->env.mip && old_mip) {
> +    } else if (!new_mip && old_mip) {
>           cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
>       }
> +
> +    return old_mip;
>   }

>   void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions Michael Clark
@ 2018-05-03 20:56   ` Alistair Francis
  2018-05-04  4:21     ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 20:56 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:02 PM Michael Clark <mjc@sifive.com> wrote:

> * 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>

I didn't check the values, but this looks sane.

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

Alistair

> ---
>   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 12b4757..878de62 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 4b4d62b..9375331 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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
@ 2018-05-03 21:11   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 21:11 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 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>

Reviewed-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 a424867..c704545 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -491,25 +491,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;
>   }
> @@ -627,17 +633,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 */
> @@ -819,7 +819,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     },
> @@ -832,7 +832,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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs Michael Clark
@ 2018-05-03 21:21   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 21:21 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:05 PM Michael Clark <mjc@sifive.com> wrote:

> 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 4e5a56d..26741d0 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 dc79f7c..3fed92d 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 2937da0..5d33f7b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -403,7 +403,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 c704545..ecf74a0 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)

I find it's easier to read if defined instead of if not defined. In general
it would be nicer if these could be if defined SOFTMMU.

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

Alistair


> +    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;
> @@ -726,6 +741,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);
> @@ -765,89 +785,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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
@ 2018-05-03 21:22   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 21:22 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Richard Henderson, Alistair Francis,
	patches

On Wed, Apr 25, 2018 at 5:00 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>

Did Richard's SOB line get dropped?

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 3fed92d..6fb0014 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -270,8 +270,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)
> @@ -279,7 +279,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 c0e6a04..4180c42 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -43,7 +43,7 @@ typedef struct DisasContext {
>       target_ulong pc;
>       target_ulong next_pc;
>       uint32_t opcode;
> -    uint32_t flags;
> +    uint32_t mstatus_fs;
>       uint32_t mem_idx;
>       int singlestep_enabled;
>       int bstate;
> @@ -664,7 +664,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;
>       }
> @@ -694,7 +694,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;
>       }
> @@ -985,7 +985,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;
>       }

> @@ -1863,8 +1863,8 @@ void gen_intermediate_code(CPUState *cs,
TranslationBlock *tb)

>       ctx.tb = tb;
>       ctx.bstate = BS_NONE;
> -    ctx.flags = tb->flags;
>       ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK;
> +    ctx.mstatus_fs = tb->flags & TB_FLAGS_MSTATUS_FS;
>       ctx.frm = -1;  /* unknown rounding mode */

>       num_insns = 0;
> --
> 2.7.0

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

* Re: [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging
  2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging Michael Clark
@ 2018-05-03 21:25   ` Alistair Francis
  0 siblings, 0 replies; 76+ messages in thread
From: Alistair Francis @ 2018-05-03 21:25 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches

On Wed, Apr 25, 2018 at 5:05 PM Michael Clark <mjc@sifive.com> wrote:

> 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>

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 5d33f7b..a45885f 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -445,11 +445,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);
>           }
>       }

> @@ -511,8 +513,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 {
> @@ -536,8 +538,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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-04-27 16:17         ` Alistair Francis
@ 2018-05-04  1:45           ` Michael Clark
  2018-05-04 23:44             ` Alistair Francis
  0 siblings, 1 reply; 76+ messages in thread
From: Michael Clark @ 2018-05-04  1:45 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	RISC-V Patches, Peter Crosthwaite, Alexander Graf, Peter Maydell

On Sat, Apr 28, 2018 at 4:17 AM, Alistair Francis <alistair23@gmail.com>
wrote:

> On Thu, Apr 26, 2018 at 10:34 PM Michael Clark <mjc@sifive.com> wrote:
>
>
>
> > On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com> wrote:
>
>
>
> >> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <alistair23@gmail.com
> >
> wrote:
>
> >>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:
>
> >>> > The sifive_u machine already marks its ROM readonly. This fixes
> >>> > the remaining boards. This commit also makes all boards use
> >>> > mask_rom as the variable name for the ROM. This change also
> >>> > makes space for the maximum device tree size size and adds
> >>> > an explicit bounds check and error message.
>
> >>> > 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_e.c     | 20 +++++++---------
> >>> >   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
> >>> >   hw/riscv/spike.c        | 64
> >>> ++++++++++++++++++++++++++++---------------------
> >>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
> >>> >   include/hw/riscv/virt.h |  4 ++++
> >>> >   5 files changed, 93 insertions(+), 79 deletions(-)
>
> >>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> >>> > index 39e4cb4..0c8b8e9 100644
> >>> > --- a/hw/riscv/sifive_e.c
> >>> > +++ b/hw/riscv/sifive_e.c
> >>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
> >>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
> >>> >   };
>
> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> >>> > -{
> >>> > -    int i;
> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >>> > -    }
> >>> > -}
> >>> > -
> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >>> >   {
> >>> >       uint64_t kernel_entry, kernel_high;
> >>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
> *machine)
> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
> >>> > +    int i;
>
> >>> >       /* Initialize SOC */
> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> TYPE_RISCV_HART_ARRAY);
> >>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
> *machine)
> >>> >           memmap[SIFIVE_E_DTIM].base, main_mem);
>
> >>> >       /* Mask ROM */
> >>> > -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
> >>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
> >>> >       memory_region_add_subregion(sys_mem,
> >>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
> >>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
> >>> *machine)
> >>> >           0x00028067,        /* 0x1004: jr      t0 */
> >>> >       };
>
> >>> > -    /* copy in the reset vector */
> >>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
> >>> sizeof(reset_vec));
> >>> > -    memory_region_set_readonly(mask_rom, true);
> >>> > +    /* copy in the reset vector in little_endian byte order */
> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >>> > +    }
> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >>> > +                          memmap[SIFIVE_E_MROM].base,
> >>> &address_space_memory);
>
> >>> >       if (machine->kernel_filename) {
> >>> >           load_kernel(machine->kernel_filename);
> >>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> >>> > index 115618b..11ba4c3 100644
> >>> > --- a/hw/riscv/sifive_u.c
> >>> > +++ b/hw/riscv/sifive_u.c
> >>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
> >>> >       hwaddr size;
> >>> >   } sifive_u_memmap[] = {
> >>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
> >>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
> >>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
> >>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
> >>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
> >>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
> >>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
> >>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
> >>> >   };
>
> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> >>> > -{
> >>> > -    int i;
> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >>> > -    }
> >>> > -}
> >>> > -
> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >>> >   {
> >>> >       uint64_t kernel_entry, kernel_high;
> >>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
> >>> *machine)
> >>> >       const struct MemmapEntry *memmap = sifive_u_memmap;
>
> >>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
> >>> > -    MemoryRegion *sys_memory = get_system_memory();
> >>> > +    MemoryRegion *system_memory = get_system_memory();
> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >>> > +    int i;
>
> >>> >       /* Initialize SOC */
> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> TYPE_RISCV_HART_ARRAY);
> >>> > @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
> >>> *machine)
> >>> >       /* register RAM */
> >>> >       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
> >>> >                              machine->ram_size, &error_fatal);
> >>> > -    memory_region_add_subregion(sys_memory,
> memmap[SIFIVE_U_DRAM].base,
> >>> > +    memory_region_add_subregion(system_memory,
> >>> memmap[SIFIVE_U_DRAM].base,
> >>> >           main_mem);
>
> >>> >       /* create device tree */
> >>> >       create_fdt(s, memmap, machine->ram_size,
> machine->kernel_cmdline);
>
> >>> >       /* boot rom */
> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
> >>> > -                           memmap[SIFIVE_U_MROM].base,
> &error_fatal);
> >>> > -    memory_region_set_readonly(boot_rom, true);
> >>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
> >>> > +                           memmap[SIFIVE_U_MROM].size,
> &error_fatal);
> >>> > +    memory_region_add_subregion(system_memory,
> >>> memmap[SIFIVE_U_MROM].base,
> >>> > +                                mask_rom);
>
> >>> >       if (machine->kernel_filename) {
> >>> >           load_kernel(machine->kernel_filename);
> >>> > @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
> >>> *machine)
> >>> >                                          /* dtb: */
> >>> >       };
>
> >>> > -    /* copy in the reset vector */
> >>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
> >>> sizeof(reset_vec));
> >>> > +    /* copy in the reset vector in little_endian byte order */
> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >>> > +    }
> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >>> > +                          memmap[SIFIVE_U_MROM].base,
> >>> &address_space_memory);
>
> >>> >       /* copy in the device tree */
> >>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size -
> sizeof(reset_vec)) {
> >>> > +        error_report("qemu: not enough space to store device-tree");
> >>> > +        exit(1);
> >>> > +    }
> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
> >>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >>> > +                          memmap[SIFIVE_U_MROM].base +
> sizeof(reset_vec),
> >>> > +                          &address_space_memory);
>
> >>> >       /* MMIO */
> >>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
> >>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
> *machine)
> >>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
> >>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
> >>> >           memmap[SIFIVE_U_PLIC].size);
> >>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
> >>> > +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
> >>> >           serial_hds[0],
> SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
> >>> > -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
> >>> > +    /* sifive_uart_create(system_memory,
> memmap[SIFIVE_U_UART1].base,
> >>> >           serial_hds[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,
> >>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> >>> > index 3f6bd0a..d1dbe6b 100644
> >>> > --- a/hw/riscv/spike.c
> >>> > +++ b/hw/riscv/spike.c
> >>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
> >>> >       hwaddr base;
> >>> >       hwaddr size;
> >>> >   } spike_memmap[] = {
> >>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
> >>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
> >>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
> >>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
> >>> >   };
>
> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> >>> > -{
> >>> > -    int i;
> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >>> > -    }
> >>> > -}
> >>> > -
> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >>> >   {
> >>> >       uint64_t kernel_entry, kernel_high;
> >>> > @@ -173,7 +165,8 @@ static void spike_v1_10_0_board_init(
> MachineState
> >>> *machine)
> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> >>> >       MemoryRegion *system_memory = get_system_memory();
> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >>> > +    int i;
>
> >>> >       /* Initialize SOC */
> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> TYPE_RISCV_HART_ARRAY);
> >>> > @@ -196,9 +189,10 @@ static void spike_v1_10_0_board_init(
> MachineState
> >>> *machine)
> >>> >       create_fdt(s, memmap, machine->ram_size,
> machine->kernel_cmdline);
>
> >>> >       /* boot rom */
> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> >>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
> >>> > +    memory_region_add_subregion(system_memory,
> memmap[SPIKE_MROM].base,
> >>> > +                                mask_rom);
>
> >>> >       if (machine->kernel_filename) {
> >>> >           load_kernel(machine->kernel_filename);
> >>> > @@ -221,16 +215,25 @@ static void
> spike_v1_10_0_board_init(MachineState
> >>> *machine)
> >>> >                                        /* dtb: */
> >>> >       };
>
> >>> > -    /* copy in the reset vector */
> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> >>> sizeof(reset_vec));
> >>> > +    /* copy in the reset vector in little_endian byte order */
> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >>> > +    }
> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >>> > +                          memmap[SPIKE_MROM].base,
> >>> &address_space_memory);
>
> >>> >       /* copy in the device tree */
> >>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size - sizeof(reset_vec))
> {
> >>> > +        error_report("qemu: not enough space to store device-tree");
> >>> > +        exit(1);
> >>> > +    }
> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> >>> sizeof(reset_vec),
> >>> > -        s->fdt, s->fdt_size);
> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >>> > +                          memmap[SPIKE_MROM].base +
> sizeof(reset_vec),
> >>> > +                          &address_space_memory);
>
> >>> >       /* initialize HTIF using symbols found in load_kernel */
> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> >>> serial_hds[0]);
> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> >>> serial_hds[0]);
>
> >>> >       /* Core Local Interruptor (timer and IPI) */
> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> >>> memmap[SPIKE_CLINT].size,
> >>> > @@ -244,7 +247,8 @@ static void spike_v1_09_1_board_init(
> MachineState
> >>> *machine)
> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> >>> >       MemoryRegion *system_memory = get_system_memory();
> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >>> > +    int i;
>
> >>> >       /* Initialize SOC */
> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> TYPE_RISCV_HART_ARRAY);
> >>> > @@ -264,9 +268,10 @@ static void spike_v1_09_1_board_init(
> MachineState
> >>> *machine)
> >>> >           main_mem);
>
> >>> >       /* boot rom */
> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
> >>> > -                           0x40000, &error_fatal);
> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> >>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
> >>> > +    memory_region_add_subregion(system_memory,
> memmap[SPIKE_MROM].base,
> >>> > +                                mask_rom);
>
> >>> >       if (machine->kernel_filename) {
> >>> >           load_kernel(machine->kernel_filename);
> >>> > @@ -319,15 +324,20 @@ static void
> spike_v1_09_1_board_init(MachineState
> >>> *machine)
> >>> >       g_free(isa);
> >>> >       size_t config_string_len = strlen(config_string);
>
> >>> > -    /* copy in the reset vector */
> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> >>> sizeof(reset_vec));
> >>> > +    /* copy in the reset vector in little_endian byte order */
> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >>> > +    }
> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >>> > +                          memmap[SPIKE_MROM].base,
> >>> &address_space_memory);
>
> >>> >       /* copy in the config string */
> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> >>> sizeof(reset_vec),
> >>> > -        config_string, config_string_len);
> >>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
> config_string_len,
> >>> > +                          memmap[SPIKE_MROM].base +
> sizeof(reset_vec),
> >>> > +                          &address_space_memory);
>
> >>> >       /* initialize HTIF using symbols found in load_kernel */
> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> >>> serial_hds[0]);
> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> >>> serial_hds[0]);
>
> >>> >       /* Core Local Interruptor (timer and IPI) */
> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> >>> memmap[SPIKE_CLINT].size,
> >>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> >>> > index 090befe..20c509d 100644
> >>> > --- a/hw/riscv/virt.c
> >>> > +++ b/hw/riscv/virt.c
> >>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
> >>> >       hwaddr size;
> >>> >   } virt_memmap[] = {
> >>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
> >>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
> >>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
> >>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
> >>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
> >>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
> >>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
> >>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
> >>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
> >>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
> >>> >   };
>
> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
> >>> > -{
> >>> > -    int i;
> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >>> > -    }
> >>> > -}
> >>> > -
> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >>> >   {
> >>> >       uint64_t kernel_entry, kernel_high;
> >>> > @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
> >>> *machine)
> >>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
> >>> >       MemoryRegion *system_memory = get_system_memory();
> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >>> >       char *plic_hart_config;
> >>> >       size_t plic_hart_config_len;
> >>> >       int i;
> >>> > @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
> >>> *machine)
> >>> >       fdt = create_fdt(s, memmap, machine->ram_size,
> >>> machine->kernel_cmdline);
>
> >>> >       /* boot rom */
> >>> > -    memory_region_init_ram(boot_rom, NULL,
> "riscv_virt_board.bootrom",
> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
> >>> > +                           memmap[VIRT_MROM].size, &error_fatal);
> >>> > +    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);
> >>> > @@ -335,13 +328,22 @@ static void riscv_virt_board_init(MachineState
> >>> *machine)
> >>> >                                        /* dtb: */
> >>> >       };
>
> >>> > -    /* copy in the reset vector */
> >>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
> >>> sizeof(reset_vec));
> >>> > +    /* copy in the reset vector in little_endian byte order */
> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >>> > +    }
> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >>> > +                          memmap[VIRT_MROM].base,
> &address_space_memory);
>
> >>> >       /* copy in the device tree */
> >>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size - sizeof(reset_vec)) {
> >>> > +        error_report("qemu: not enough space to store device-tree");
> >>> > +        exit(1);
> >>> > +    }
> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
> sizeof(reset_vec),
> >>> > -        s->fdt, s->fdt_size);
> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >>> > +                          memmap[VIRT_MROM].base +
> sizeof(reset_vec),
> >>> > +                          &address_space_memory);
>
> >>> >       /* create PLIC hart topology configuration string */
> >>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
> >>> smp_cpus;
> >>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> >>> > index 91163d6..6f2668e 100644
> >>> > --- a/include/hw/riscv/virt.h
> >>> > +++ b/include/hw/riscv/virt.h
> >>> > @@ -19,6 +19,10 @@
> >>> >   #ifndef HW_RISCV_VIRT_H
> >>> >   #define HW_RISCV_VIRT_H
>
> >>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
> >>> > +#define VIRT(obj) \
> >>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
> >>> > +
>
> >>> This should be in a seperate patch.
>
>
> >> I'll shift that chunk into "Remove unused class definitions".
>
>
> > Actually we to need to drop this chunk as the unused check macros were
> removed from machine state structs in "Remove unused class definitions".
> Somehow the chunk made it into this patch. Likely a rebase issue.
>
> > It's probably best that we add what we need back in the QOM SOC refactor
> on-top of the this series, or at least after the first set of patches are
> merged...
>
> > I think that's what you were planning to do anyway.
>
> Yeah, that works. So just remove it from this series.
>

After rebasing I had to change this patch because of this patch which
increases the default device tree size to 1MiB. This is not controllable by
the user and we don't know how big the resultant device-tree is. It could
be < 8KiB in our case.

-
https://git.qemu.org/?p=qemu.git;a=commit;h=14ec3cbd7c1e31dca4d23f028100c8f43e156573


I studied ftd and used public interfaces and a mechanism consistent with
the fdt resize functions to calculate the size. As far as I can tell it is
accurate and covers exactly to the end of the uint32 terminator. I needed
this because our ROMs are currently small.

Peter, this is the patch that changes our ROMs from RAM to ROM
using memory_region_init_rom and rom_add_blob_fixed_as (as per
hw/arm/boot.c), and it also adds a truncation warning, so that we actually
know what size the device-tree is, given our ROMs are currently much
smaller than 1MiB. That is why we needed a method that tells us how big the
device tree actually is.

BTW I'm actually suspicious of 'fdt_resize' here:

-
https://git.qemu.org/?p=dtc.git;a=blob;f=libfdt/fdt_sw.c;h=6d33cc29d0224d9fc6307607ef7563df944da2d3

as it doesn't check that 'bufsize' has enough space for the header and
terminator, although that's potentially a dtc bug. I read dtc to make sure
the method we use to calculate the size was accurate. There probably should
be a method in dtc as we rely on some implementation details, however they
are quite simple and we can get: sizeof(header) + sizeof(structs) +
sizeof(strings)
+ terminator using public APIs and basic knowledge of the serialised
device-tree form.

Anyway, here is the rebased version of this patch using the new
'qemu_fdt_totalsize' method in the patch I just sent.

-
https://github.com/riscv/riscv-qemu/commit/a65f6e0447d6e32d75f64ba31df5f20d529d0489

I have a feeling this is the patch that fixes sifive_u. Did you bisect
which patch in the series fixed sifive_u?

I have to send a pull for the reviewed patches which I can do today, but
this is one of the patches that is early in the series that does not yet
have Reviewed-by. When I split the series this patch would be in a second
series that i'll have to link to the pull in patchew (using the method
Peter mentioned) or wait until the pull is accepted.

Michael.

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

* Re: [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions
  2018-05-03 20:56   ` Alistair Francis
@ 2018-05-04  4:21     ` Michael Clark
  0 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-05-04  4:21 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	RISC-V Patches

On Fri, May 4, 2018 at 8:56 AM, Alistair Francis <alistair23@gmail.com>
wrote:

> On Wed, Apr 25, 2018 at 5:02 PM Michael Clark <mjc@sifive.com> wrote:
>
> > * 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>
>
> I didn't check the values, but this looks sane.
>

The pre-existing values just have formatting changes to add titles and
group them consistently with the privileged specifiction.


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


Thanks.

Alistair
>
> > ---
> >   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 12b4757..878de62 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 4b4d62b..9375331 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] 76+ messages in thread

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-05-04  1:45           ` Michael Clark
@ 2018-05-04 23:44             ` Alistair Francis
  2018-05-04 23:54               ` Alistair Francis
  0 siblings, 1 reply; 76+ messages in thread
From: Alistair Francis @ 2018-05-04 23:44 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches,
	Peter Crosthwaite, Alexander Graf, Peter Maydell

On Thu, May 3, 2018 at 6:45 PM Michael Clark <mjc@sifive.com> wrote:



> On Sat, Apr 28, 2018 at 4:17 AM, Alistair Francis <alistair23@gmail.com>
wrote:

>> On Thu, Apr 26, 2018 at 10:34 PM Michael Clark <mjc@sifive.com> wrote:



>> > On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com> wrote:



>> >> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <
alistair23@gmail.com>
>> wrote:

>> >>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com> wrote:

>> >>> > The sifive_u machine already marks its ROM readonly. This fixes
>> >>> > the remaining boards. This commit also makes all boards use
>> >>> > mask_rom as the variable name for the ROM. This change also
>> >>> > makes space for the maximum device tree size size and adds
>> >>> > an explicit bounds check and error message.

>> >>> > 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_e.c     | 20 +++++++---------
>> >>> >   hw/riscv/sifive_u.c     | 46 ++++++++++++++++++-----------------
>> >>> >   hw/riscv/spike.c        | 64
>> >>> ++++++++++++++++++++++++++++---------------------
>> >>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
>> >>> >   include/hw/riscv/virt.h |  4 ++++
>> >>> >   5 files changed, 93 insertions(+), 79 deletions(-)

>> >>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
>> >>> > index 39e4cb4..0c8b8e9 100644
>> >>> > --- a/hw/riscv/sifive_e.c
>> >>> > +++ b/hw/riscv/sifive_e.c
>> >>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
>> >>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
>> >>> >   };

>> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
len)
>> >>> > -{
>> >>> > -    int i;
>> >>> > -    for (i = 0; i < (len >> 2); i++) {
>> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> >>> > -    }
>> >>> > -}
>> >>> > -
>> >>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >>> >   {
>> >>> >       uint64_t kernel_entry, kernel_high;
>> >>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
>> *machine)
>> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
>> >>> > +    int i;

>> >>> >       /* Initialize SOC */
>> >>> >       object_initialize(&s->soc, sizeof(s->soc),
>> TYPE_RISCV_HART_ARRAY);
>> >>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
>> *machine)
>> >>> >           memmap[SIFIVE_E_DTIM].base, main_mem);

>> >>> >       /* Mask ROM */
>> >>> > -    memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
>> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
>> >>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
>> >>> >       memory_region_add_subregion(sys_mem,
>> >>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
>> >>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
>> >>> *machine)
>> >>> >           0x00028067,        /* 0x1004: jr      t0 */
>> >>> >       };

>> >>> > -    /* copy in the reset vector */
>> >>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
>> >>> sizeof(reset_vec));
>> >>> > -    memory_region_set_readonly(mask_rom, true);
>> >>> > +    /* copy in the reset vector in little_endian byte order */
>> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> >>> > +    }
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
sizeof(reset_vec),
>> >>> > +                          memmap[SIFIVE_E_MROM].base,
>> >>> &address_space_memory);

>> >>> >       if (machine->kernel_filename) {
>> >>> >           load_kernel(machine->kernel_filename);
>> >>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
>> >>> > index 115618b..11ba4c3 100644
>> >>> > --- a/hw/riscv/sifive_u.c
>> >>> > +++ b/hw/riscv/sifive_u.c
>> >>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
>> >>> >       hwaddr size;
>> >>> >   } sifive_u_memmap[] = {
>> >>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
>> >>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
>> >>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
>> >>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
>> >>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
>> >>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
>> >>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
>> >>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
>> >>> >   };

>> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
len)
>> >>> > -{
>> >>> > -    int i;
>> >>> > -    for (i = 0; i < (len >> 2); i++) {
>> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> >>> > -    }
>> >>> > -}
>> >>> > -
>> >>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >>> >   {
>> >>> >       uint64_t kernel_entry, kernel_high;
>> >>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
>> >>> *machine)
>> >>> >       const struct MemmapEntry *memmap = sifive_u_memmap;

>> >>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
>> >>> > -    MemoryRegion *sys_memory = get_system_memory();
>> >>> > +    MemoryRegion *system_memory = get_system_memory();
>> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >>> > +    int i;

>> >>> >       /* Initialize SOC */
>> >>> >       object_initialize(&s->soc, sizeof(s->soc),
>> TYPE_RISCV_HART_ARRAY);
>> >>> > @@ -239,17 +232,17 @@ static void riscv_sifive_u_init(MachineState
>> >>> *machine)
>> >>> >       /* register RAM */
>> >>> >       memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
>> >>> >                              machine->ram_size, &error_fatal);
>> >>> > -    memory_region_add_subregion(sys_memory,
>> memmap[SIFIVE_U_DRAM].base,
>> >>> > +    memory_region_add_subregion(system_memory,
>> >>> memmap[SIFIVE_U_DRAM].base,
>> >>> >           main_mem);

>> >>> >       /* create device tree */
>> >>> >       create_fdt(s, memmap, machine->ram_size,
>> machine->kernel_cmdline);

>> >>> >       /* boot rom */
>> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
>> >>> > -                           memmap[SIFIVE_U_MROM].base,
&error_fatal);
>> >>> > -    memory_region_set_readonly(boot_rom, true);
>> >>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
>> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
>> >>> > +                           memmap[SIFIVE_U_MROM].size,
&error_fatal);
>> >>> > +    memory_region_add_subregion(system_memory,
>> >>> memmap[SIFIVE_U_MROM].base,
>> >>> > +                                mask_rom);

>> >>> >       if (machine->kernel_filename) {
>> >>> >           load_kernel(machine->kernel_filename);
>> >>> > @@ -272,13 +265,22 @@ static void riscv_sifive_u_init(MachineState
>> >>> *machine)
>> >>> >                                          /* dtb: */
>> >>> >       };

>> >>> > -    /* copy in the reset vector */
>> >>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
>> >>> sizeof(reset_vec));
>> >>> > +    /* copy in the reset vector in little_endian byte order */
>> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> >>> > +    }
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
sizeof(reset_vec),
>> >>> > +                          memmap[SIFIVE_U_MROM].base,
>> >>> &address_space_memory);

>> >>> >       /* copy in the device tree */
>> >>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size -
>> sizeof(reset_vec)) {
>> >>> > +        error_report("qemu: not enough space to store
device-tree");
>> >>> > +        exit(1);
>> >>> > +    }
>> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> >>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
>> >>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
>> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> >>> > +                          memmap[SIFIVE_U_MROM].base +
>> sizeof(reset_vec),
>> >>> > +                          &address_space_memory);

>> >>> >       /* MMIO */
>> >>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
>> >>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
>> *machine)
>> >>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
>> >>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
>> >>> >           memmap[SIFIVE_U_PLIC].size);
>> >>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
>> >>> > +    sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
>> >>> >           serial_hds[0],
>> SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
>> >>> > -    /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
>> >>> > +    /* sifive_uart_create(system_memory,
memmap[SIFIVE_U_UART1].base,
>> >>> >           serial_hds[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,
>> >>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
>> >>> > index 3f6bd0a..d1dbe6b 100644
>> >>> > --- a/hw/riscv/spike.c
>> >>> > +++ b/hw/riscv/spike.c
>> >>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
>> >>> >       hwaddr base;
>> >>> >       hwaddr size;
>> >>> >   } spike_memmap[] = {
>> >>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
>> >>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
>> >>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
>> >>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
>> >>> >   };

>> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
len)
>> >>> > -{
>> >>> > -    int i;
>> >>> > -    for (i = 0; i < (len >> 2); i++) {
>> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> >>> > -    }
>> >>> > -}
>> >>> > -
>> >>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >>> >   {
>> >>> >       uint64_t kernel_entry, kernel_high;
>> >>> > @@ -173,7 +165,8 @@ static void
spike_v1_10_0_board_init(MachineState
>> >>> *machine)
>> >>> >       SpikeState *s = g_new0(SpikeState, 1);
>> >>> >       MemoryRegion *system_memory = get_system_memory();
>> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >>> > +    int i;

>> >>> >       /* Initialize SOC */
>> >>> >       object_initialize(&s->soc, sizeof(s->soc),
>> TYPE_RISCV_HART_ARRAY);
>> >>> > @@ -196,9 +189,10 @@ static void
spike_v1_10_0_board_init(MachineState
>> >>> *machine)
>> >>> >       create_fdt(s, memmap, machine->ram_size,
>> machine->kernel_cmdline);

>> >>> >       /* boot rom */
>> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
>> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>> >>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>> >>> > +    memory_region_add_subregion(system_memory,
>> memmap[SPIKE_MROM].base,
>> >>> > +                                mask_rom);

>> >>> >       if (machine->kernel_filename) {
>> >>> >           load_kernel(machine->kernel_filename);
>> >>> > @@ -221,16 +215,25 @@ static void
>> spike_v1_10_0_board_init(MachineState
>> >>> *machine)
>> >>> >                                        /* dtb: */
>> >>> >       };

>> >>> > -    /* copy in the reset vector */
>> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>> >>> sizeof(reset_vec));
>> >>> > +    /* copy in the reset vector in little_endian byte order */
>> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> >>> > +    }
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
sizeof(reset_vec),
>> >>> > +                          memmap[SPIKE_MROM].base,
>> >>> &address_space_memory);

>> >>> >       /* copy in the device tree */
>> >>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size -
sizeof(reset_vec)) {
>> >>> > +        error_report("qemu: not enough space to store
device-tree");
>> >>> > +        exit(1);
>> >>> > +    }
>> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>> >>> sizeof(reset_vec),
>> >>> > -        s->fdt, s->fdt_size);
>> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> >>> > +                          memmap[SPIKE_MROM].base +
>> sizeof(reset_vec),
>> >>> > +                          &address_space_memory);

>> >>> >       /* initialize HTIF using symbols found in load_kernel */
>> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>> >>> serial_hds[0]);
>> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>> >>> serial_hds[0]);

>> >>> >       /* Core Local Interruptor (timer and IPI) */
>> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>> >>> memmap[SPIKE_CLINT].size,
>> >>> > @@ -244,7 +247,8 @@ static void
spike_v1_09_1_board_init(MachineState
>> >>> *machine)
>> >>> >       SpikeState *s = g_new0(SpikeState, 1);
>> >>> >       MemoryRegion *system_memory = get_system_memory();
>> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >>> > +    int i;

>> >>> >       /* Initialize SOC */
>> >>> >       object_initialize(&s->soc, sizeof(s->soc),
>> TYPE_RISCV_HART_ARRAY);
>> >>> > @@ -264,9 +268,10 @@ static void
spike_v1_09_1_board_init(MachineState
>> >>> *machine)
>> >>> >           main_mem);

>> >>> >       /* boot rom */
>> >>> > -    memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
>> >>> > -                           0x40000, &error_fatal);
>> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
>> >>> > +                           memmap[SPIKE_MROM].size, &error_fatal);
>> >>> > +    memory_region_add_subregion(system_memory,
>> memmap[SPIKE_MROM].base,
>> >>> > +                                mask_rom);

>> >>> >       if (machine->kernel_filename) {
>> >>> >           load_kernel(machine->kernel_filename);
>> >>> > @@ -319,15 +324,20 @@ static void
>> spike_v1_09_1_board_init(MachineState
>> >>> *machine)
>> >>> >       g_free(isa);
>> >>> >       size_t config_string_len = strlen(config_string);

>> >>> > -    /* copy in the reset vector */
>> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
>> >>> sizeof(reset_vec));
>> >>> > +    /* copy in the reset vector in little_endian byte order */
>> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> >>> > +    }
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
sizeof(reset_vec),
>> >>> > +                          memmap[SPIKE_MROM].base,
>> >>> &address_space_memory);

>> >>> >       /* copy in the config string */
>> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
>> >>> sizeof(reset_vec),
>> >>> > -        config_string, config_string_len);
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
>> config_string_len,
>> >>> > +                          memmap[SPIKE_MROM].base +
>> sizeof(reset_vec),
>> >>> > +                          &address_space_memory);

>> >>> >       /* initialize HTIF using symbols found in load_kernel */
>> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
>> >>> serial_hds[0]);
>> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
>> >>> serial_hds[0]);

>> >>> >       /* Core Local Interruptor (timer and IPI) */
>> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
>> >>> memmap[SPIKE_CLINT].size,
>> >>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>> >>> > index 090befe..20c509d 100644
>> >>> > --- a/hw/riscv/virt.c
>> >>> > +++ b/hw/riscv/virt.c
>> >>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
>> >>> >       hwaddr size;
>> >>> >   } virt_memmap[] = {
>> >>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
>> >>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
>> >>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
>> >>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
>> >>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
>> >>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
>> >>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
>> >>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
>> >>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
>> >>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
>> >>> >   };

>> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
len)
>> >>> > -{
>> >>> > -    int i;
>> >>> > -    for (i = 0; i < (len >> 2); i++) {
>> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
>> >>> > -    }
>> >>> > -}
>> >>> > -
>> >>> >   static uint64_t load_kernel(const char *kernel_filename)
>> >>> >   {
>> >>> >       uint64_t kernel_entry, kernel_high;
>> >>> > @@ -272,7 +264,7 @@ static void riscv_virt_board_init(MachineState
>> >>> *machine)
>> >>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
>> >>> >       MemoryRegion *system_memory = get_system_memory();
>> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
>> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>> >>> >       char *plic_hart_config;
>> >>> >       size_t plic_hart_config_len;
>> >>> >       int i;
>> >>> > @@ -299,9 +291,10 @@ static void riscv_virt_board_init(MachineState
>> >>> *machine)
>> >>> >       fdt = create_fdt(s, memmap, machine->ram_size,
>> >>> machine->kernel_cmdline);

>> >>> >       /* boot rom */
>> >>> > -    memory_region_init_ram(boot_rom, NULL,
>> "riscv_virt_board.bootrom",
>> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
>> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
>> >>> > +    memory_region_init_rom(mask_rom, NULL,
"riscv_virt_board.mrom",
>> >>> > +                           memmap[VIRT_MROM].size, &error_fatal);
>> >>> > +    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);
>> >>> > @@ -335,13 +328,22 @@ static void
riscv_virt_board_init(MachineState
>> >>> *machine)
>> >>> >                                        /* dtb: */
>> >>> >       };

>> >>> > -    /* copy in the reset vector */
>> >>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
>> >>> sizeof(reset_vec));
>> >>> > +    /* copy in the reset vector in little_endian byte order */
>> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
>> >>> > +    }
>> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
sizeof(reset_vec),
>> >>> > +                          memmap[VIRT_MROM].base,
>> &address_space_memory);

>> >>> >       /* copy in the device tree */
>> >>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size -
sizeof(reset_vec)) {
>> >>> > +        error_report("qemu: not enough space to store
device-tree");
>> >>> > +        exit(1);
>> >>> > +    }
>> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
>> >>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
>> sizeof(reset_vec),
>> >>> > -        s->fdt, s->fdt_size);
>> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
>> >>> > +                          memmap[VIRT_MROM].base +
sizeof(reset_vec),
>> >>> > +                          &address_space_memory);

>> >>> >       /* create PLIC hart topology configuration string */
>> >>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
>> >>> smp_cpus;
>> >>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
>> >>> > index 91163d6..6f2668e 100644
>> >>> > --- a/include/hw/riscv/virt.h
>> >>> > +++ b/include/hw/riscv/virt.h
>> >>> > @@ -19,6 +19,10 @@
>> >>> >   #ifndef HW_RISCV_VIRT_H
>> >>> >   #define HW_RISCV_VIRT_H

>> >>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
>> >>> > +#define VIRT(obj) \
>> >>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
>> >>> > +

>> >>> This should be in a seperate patch.


>> >> I'll shift that chunk into "Remove unused class definitions".


>> > Actually we to need to drop this chunk as the unused check macros were
>> removed from machine state structs in "Remove unused class definitions".
>> Somehow the chunk made it into this patch. Likely a rebase issue.

>> > It's probably best that we add what we need back in the QOM SOC
refactor
>> on-top of the this series, or at least after the first set of patches are
>> merged...

>> > I think that's what you were planning to do anyway.

>> Yeah, that works. So just remove it from this series.


> After rebasing I had to change this patch because of this patch which
increases the default device tree size to 1MiB. This is not controllable by
the user and we don't know how big the resultant device-tree is. It could
be < 8KiB in our case.

> -
https://git.qemu.org/?p=qemu.git;a=commit;h=14ec3cbd7c1e31dca4d23f028100c8f43e156573

> I studied ftd and used public interfaces and a mechanism consistent with
the fdt resize functions to calculate the size. As far as I can tell it is
accurate and covers exactly to the end of the uint32 terminator. I needed
this because our ROMs are currently small.

> Peter, this is the patch that changes our ROMs from RAM to ROM using
memory_region_init_rom and rom_add_blob_fixed_as (as per hw/arm/boot.c),
and it also adds a truncation warning, so that we actually know what size
the device-tree is, given our ROMs are currently much smaller than 1MiB.
That is why we needed a method that tells us how big the device tree
actually is.

> BTW I'm actually suspicious of 'fdt_resize' here:

> -
https://git.qemu.org/?p=dtc.git;a=blob;f=libfdt/fdt_sw.c;h=6d33cc29d0224d9fc6307607ef7563df944da2d3

> as it doesn't check that 'bufsize' has enough space for the header and
terminator, although that's potentially a dtc bug. I read dtc to make sure
the method we use to calculate the size was accurate. There probably should
be a method in dtc as we rely on some implementation details, however they
are quite simple and we can get: sizeof(header) + sizeof(structs) +
sizeof(strings) + terminator using public APIs and basic knowledge of the
serialised device-tree form.

> Anyway, here is the rebased version of this patch using the new
'qemu_fdt_totalsize' method in the patch I just sent.

> -
https://github.com/riscv/riscv-qemu/commit/a65f6e0447d6e32d75f64ba31df5f20d529d0489

> I have a feeling this is the patch that fixes sifive_u. Did you bisect
which patch in the series fixed sifive_u?

I agree, I think this is the patch.

No, I havent' bisected it. I didn't think there was much point, but if we
want patches backported to stable I guess there is. I'll dig into it.


> I have to send a pull for the reviewed patches which I can do today, but
this is one of the patches that is early in the series that does not yet
have Reviewed-by. When I split the series this patch would be in a second
series that i'll have to link to the pull in patchew (using the method
Peter mentioned) or wait until the pull is accepted.

Great, let's get the first part of the series merged. It'd be nice to send
out the next version of the second part while the PR is being merged.

Alistair


> Michael.

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-05-04 23:44             ` Alistair Francis
@ 2018-05-04 23:54               ` Alistair Francis
  2018-05-05  2:02                 ` Michael Clark
  0 siblings, 1 reply; 76+ messages in thread
From: Alistair Francis @ 2018-05-04 23:54 UTC (permalink / raw)
  To: Michael Clark
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, palmer, Alistair Francis, patches,
	Peter Crosthwaite, Alexander Graf, Peter Maydell

On Fri, May 4, 2018 at 4:44 PM Alistair Francis <alistair23@gmail.com>
wrote:

> On Thu, May 3, 2018 at 6:45 PM Michael Clark <mjc@sifive.com> wrote:



> > On Sat, Apr 28, 2018 at 4:17 AM, Alistair Francis <alistair23@gmail.com>
> wrote:

> >> On Thu, Apr 26, 2018 at 10:34 PM Michael Clark <mjc@sifive.com> wrote:



> >> > On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com>
wrote:



> >> >> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <
> alistair23@gmail.com>
> >> wrote:

> >> >>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com>
wrote:

> >> >>> > The sifive_u machine already marks its ROM readonly. This fixes
> >> >>> > the remaining boards. This commit also makes all boards use
> >> >>> > mask_rom as the variable name for the ROM. This change also
> >> >>> > makes space for the maximum device tree size size and adds
> >> >>> > an explicit bounds check and error message.

> >> >>> > 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_e.c     | 20 +++++++---------
> >> >>> >   hw/riscv/sifive_u.c     | 46
++++++++++++++++++-----------------
> >> >>> >   hw/riscv/spike.c        | 64
> >> >>> ++++++++++++++++++++++++++++---------------------
> >> >>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
> >> >>> >   include/hw/riscv/virt.h |  4 ++++
> >> >>> >   5 files changed, 93 insertions(+), 79 deletions(-)

> >> >>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> >> >>> > index 39e4cb4..0c8b8e9 100644
> >> >>> > --- a/hw/riscv/sifive_e.c
> >> >>> > +++ b/hw/riscv/sifive_e.c
> >> >>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
> >> >>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
> >> >>> >   };

> >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> len)
> >> >>> > -{
> >> >>> > -    int i;
> >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >> >>> > -    }
> >> >>> > -}
> >> >>> > -
> >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >> >>> >   {
> >> >>> >       uint64_t kernel_entry, kernel_high;
> >> >>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState
> >> *machine)
> >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >> >>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >> >>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
> >> >>> > +    int i;

> >> >>> >       /* Initialize SOC */
> >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> >> TYPE_RISCV_HART_ARRAY);
> >> >>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState
> >> *machine)
> >> >>> >           memmap[SIFIVE_E_DTIM].base, main_mem);

> >> >>> >       /* Mask ROM */
> >> >>> > -    memory_region_init_ram(mask_rom, NULL,
"riscv.sifive.e.mrom",
> >> >>> > +    memory_region_init_rom(mask_rom, NULL,
"riscv.sifive.e.mrom",
> >> >>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
> >> >>> >       memory_region_add_subregion(sys_mem,
> >> >>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
> >> >>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState
> >> >>> *machine)
> >> >>> >           0x00028067,        /* 0x1004: jr      t0 */
> >> >>> >       };

> >> >>> > -    /* copy in the reset vector */
> >> >>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
> >> >>> sizeof(reset_vec));
> >> >>> > -    memory_region_set_readonly(mask_rom, true);
> >> >>> > +    /* copy in the reset vector in little_endian byte order */
> >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> >>> > +    }
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >> >>> > +                          memmap[SIFIVE_E_MROM].base,
> >> >>> &address_space_memory);

> >> >>> >       if (machine->kernel_filename) {
> >> >>> >           load_kernel(machine->kernel_filename);
> >> >>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> >> >>> > index 115618b..11ba4c3 100644
> >> >>> > --- a/hw/riscv/sifive_u.c
> >> >>> > +++ b/hw/riscv/sifive_u.c
> >> >>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
> >> >>> >       hwaddr size;
> >> >>> >   } sifive_u_memmap[] = {
> >> >>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
> >> >>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
> >> >>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
> >> >>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
> >> >>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
> >> >>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
> >> >>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
> >> >>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
> >> >>> >   };

> >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> len)
> >> >>> > -{
> >> >>> > -    int i;
> >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >> >>> > -    }
> >> >>> > -}
> >> >>> > -
> >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >> >>> >   {
> >> >>> >       uint64_t kernel_entry, kernel_high;
> >> >>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(MachineState
> >> >>> *machine)
> >> >>> >       const struct MemmapEntry *memmap = sifive_u_memmap;

> >> >>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
> >> >>> > -    MemoryRegion *sys_memory = get_system_memory();
> >> >>> > +    MemoryRegion *system_memory = get_system_memory();
> >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >> >>> > +    int i;

> >> >>> >       /* Initialize SOC */
> >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> >> TYPE_RISCV_HART_ARRAY);
> >> >>> > @@ -239,17 +232,17 @@ static void
riscv_sifive_u_init(MachineState
> >> >>> *machine)
> >> >>> >       /* register RAM */
> >> >>> >       memory_region_init_ram(main_mem, NULL,
"riscv.sifive.u.ram",
> >> >>> >                              machine->ram_size, &error_fatal);
> >> >>> > -    memory_region_add_subregion(sys_memory,
> >> memmap[SIFIVE_U_DRAM].base,
> >> >>> > +    memory_region_add_subregion(system_memory,
> >> >>> memmap[SIFIVE_U_DRAM].base,
> >> >>> >           main_mem);

> >> >>> >       /* create device tree */
> >> >>> >       create_fdt(s, memmap, machine->ram_size,
> >> machine->kernel_cmdline);

> >> >>> >       /* boot rom */
> >> >>> > -    memory_region_init_ram(boot_rom, NULL,
"riscv.sifive.u.mrom",
> >> >>> > -                           memmap[SIFIVE_U_MROM].base,
> &error_fatal);
> >> >>> > -    memory_region_set_readonly(boot_rom, true);
> >> >>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
> >> >>> > +    memory_region_init_rom(mask_rom, NULL,
"riscv.sifive.u.mrom",
> >> >>> > +                           memmap[SIFIVE_U_MROM].size,
> &error_fatal);
> >> >>> > +    memory_region_add_subregion(system_memory,
> >> >>> memmap[SIFIVE_U_MROM].base,
> >> >>> > +                                mask_rom);

> >> >>> >       if (machine->kernel_filename) {
> >> >>> >           load_kernel(machine->kernel_filename);
> >> >>> > @@ -272,13 +265,22 @@ static void
riscv_sifive_u_init(MachineState
> >> >>> *machine)
> >> >>> >                                          /* dtb: */
> >> >>> >       };

> >> >>> > -    /* copy in the reset vector */
> >> >>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
> >> >>> sizeof(reset_vec));
> >> >>> > +    /* copy in the reset vector in little_endian byte order */
> >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> >>> > +    }
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >> >>> > +                          memmap[SIFIVE_U_MROM].base,
> >> >>> &address_space_memory);

> >> >>> >       /* copy in the device tree */
> >> >>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size -
> >> sizeof(reset_vec)) {
> >> >>> > +        error_report("qemu: not enough space to store
> device-tree");
> >> >>> > +        exit(1);
> >> >>> > +    }
> >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >> >>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
> >> >>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
> >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >> >>> > +                          memmap[SIFIVE_U_MROM].base +
> >> sizeof(reset_vec),
> >> >>> > +                          &address_space_memory);

> >> >>> >       /* MMIO */
> >> >>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
> >> >>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(MachineState
> >> *machine)
> >> >>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
> >> >>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
> >> >>> >           memmap[SIFIVE_U_PLIC].size);
> >> >>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
> >> >>> > +    sifive_uart_create(system_memory,
memmap[SIFIVE_U_UART0].base,
> >> >>> >           serial_hds[0],
> >> SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
> >> >>> > -    /* sifive_uart_create(sys_memory,
memmap[SIFIVE_U_UART1].base,
> >> >>> > +    /* sifive_uart_create(system_memory,
> memmap[SIFIVE_U_UART1].base,
> >> >>> >           serial_hds[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,
> >> >>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> >> >>> > index 3f6bd0a..d1dbe6b 100644
> >> >>> > --- a/hw/riscv/spike.c
> >> >>> > +++ b/hw/riscv/spike.c
> >> >>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
> >> >>> >       hwaddr base;
> >> >>> >       hwaddr size;
> >> >>> >   } spike_memmap[] = {
> >> >>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
> >> >>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
> >> >>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
> >> >>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
> >> >>> >   };

> >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> len)
> >> >>> > -{
> >> >>> > -    int i;
> >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >> >>> > -    }
> >> >>> > -}
> >> >>> > -
> >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >> >>> >   {
> >> >>> >       uint64_t kernel_entry, kernel_high;
> >> >>> > @@ -173,7 +165,8 @@ static void
> spike_v1_10_0_board_init(MachineState
> >> >>> *machine)
> >> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> >> >>> >       MemoryRegion *system_memory = get_system_memory();
> >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >> >>> > +    int i;

> >> >>> >       /* Initialize SOC */
> >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> >> TYPE_RISCV_HART_ARRAY);
> >> >>> > @@ -196,9 +189,10 @@ static void
> spike_v1_10_0_board_init(MachineState
> >> >>> *machine)
> >> >>> >       create_fdt(s, memmap, machine->ram_size,
> >> machine->kernel_cmdline);

> >> >>> >       /* boot rom */
> >> >>> > -    memory_region_init_ram(boot_rom, NULL,
"riscv.spike.bootrom",
> >> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> >> >>> > +                           memmap[SPIKE_MROM].size,
&error_fatal);
> >> >>> > +    memory_region_add_subregion(system_memory,
> >> memmap[SPIKE_MROM].base,
> >> >>> > +                                mask_rom);

> >> >>> >       if (machine->kernel_filename) {
> >> >>> >           load_kernel(machine->kernel_filename);
> >> >>> > @@ -221,16 +215,25 @@ static void
> >> spike_v1_10_0_board_init(MachineState
> >> >>> *machine)
> >> >>> >                                        /* dtb: */
> >> >>> >       };

> >> >>> > -    /* copy in the reset vector */
> >> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> >> >>> sizeof(reset_vec));
> >> >>> > +    /* copy in the reset vector in little_endian byte order */
> >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> >>> > +    }
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >> >>> > +                          memmap[SPIKE_MROM].base,
> >> >>> &address_space_memory);

> >> >>> >       /* copy in the device tree */
> >> >>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size -
> sizeof(reset_vec)) {
> >> >>> > +        error_report("qemu: not enough space to store
> device-tree");
> >> >>> > +        exit(1);
> >> >>> > +    }
> >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> >> >>> sizeof(reset_vec),
> >> >>> > -        s->fdt, s->fdt_size);
> >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >> >>> > +                          memmap[SPIKE_MROM].base +
> >> sizeof(reset_vec),
> >> >>> > +                          &address_space_memory);

> >> >>> >       /* initialize HTIF using symbols found in load_kernel */
> >> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> >> >>> serial_hds[0]);
> >> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> >> >>> serial_hds[0]);

> >> >>> >       /* Core Local Interruptor (timer and IPI) */
> >> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> >> >>> memmap[SPIKE_CLINT].size,
> >> >>> > @@ -244,7 +247,8 @@ static void
> spike_v1_09_1_board_init(MachineState
> >> >>> *machine)
> >> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> >> >>> >       MemoryRegion *system_memory = get_system_memory();
> >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >> >>> > +    int i;

> >> >>> >       /* Initialize SOC */
> >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> >> TYPE_RISCV_HART_ARRAY);
> >> >>> > @@ -264,9 +268,10 @@ static void
> spike_v1_09_1_board_init(MachineState
> >> >>> *machine)
> >> >>> >           main_mem);

> >> >>> >       /* boot rom */
> >> >>> > -    memory_region_init_ram(boot_rom, NULL,
"riscv.spike.bootrom",
> >> >>> > -                           0x40000, &error_fatal);
> >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> >> >>> > +                           memmap[SPIKE_MROM].size,
&error_fatal);
> >> >>> > +    memory_region_add_subregion(system_memory,
> >> memmap[SPIKE_MROM].base,
> >> >>> > +                                mask_rom);

> >> >>> >       if (machine->kernel_filename) {
> >> >>> >           load_kernel(machine->kernel_filename);
> >> >>> > @@ -319,15 +324,20 @@ static void
> >> spike_v1_09_1_board_init(MachineState
> >> >>> *machine)
> >> >>> >       g_free(isa);
> >> >>> >       size_t config_string_len = strlen(config_string);

> >> >>> > -    /* copy in the reset vector */
> >> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> >> >>> sizeof(reset_vec));
> >> >>> > +    /* copy in the reset vector in little_endian byte order */
> >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> >>> > +    }
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >> >>> > +                          memmap[SPIKE_MROM].base,
> >> >>> &address_space_memory);

> >> >>> >       /* copy in the config string */
> >> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> >> >>> sizeof(reset_vec),
> >> >>> > -        config_string, config_string_len);
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
> >> config_string_len,
> >> >>> > +                          memmap[SPIKE_MROM].base +
> >> sizeof(reset_vec),
> >> >>> > +                          &address_space_memory);

> >> >>> >       /* initialize HTIF using symbols found in load_kernel */
> >> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> >> >>> serial_hds[0]);
> >> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> >> >>> serial_hds[0]);

> >> >>> >       /* Core Local Interruptor (timer and IPI) */
> >> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> >> >>> memmap[SPIKE_CLINT].size,
> >> >>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> >> >>> > index 090befe..20c509d 100644
> >> >>> > --- a/hw/riscv/virt.c
> >> >>> > +++ b/hw/riscv/virt.c
> >> >>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
> >> >>> >       hwaddr size;
> >> >>> >   } virt_memmap[] = {
> >> >>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
> >> >>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
> >> >>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
> >> >>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
> >> >>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
> >> >>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
> >> >>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
> >> >>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
> >> >>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
> >> >>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
> >> >>> >   };

> >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> len)
> >> >>> > -{
> >> >>> > -    int i;
> >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
> >> >>> > -    }
> >> >>> > -}
> >> >>> > -
> >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> >> >>> >   {
> >> >>> >       uint64_t kernel_entry, kernel_high;
> >> >>> > @@ -272,7 +264,7 @@ static void
riscv_virt_board_init(MachineState
> >> >>> *machine)
> >> >>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
> >> >>> >       MemoryRegion *system_memory = get_system_memory();
> >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> >> >>> >       char *plic_hart_config;
> >> >>> >       size_t plic_hart_config_len;
> >> >>> >       int i;
> >> >>> > @@ -299,9 +291,10 @@ static void
riscv_virt_board_init(MachineState
> >> >>> *machine)
> >> >>> >       fdt = create_fdt(s, memmap, machine->ram_size,
> >> >>> machine->kernel_cmdline);

> >> >>> >       /* boot rom */
> >> >>> > -    memory_region_init_ram(boot_rom, NULL,
> >> "riscv_virt_board.bootrom",
> >> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> >> >>> > +    memory_region_init_rom(mask_rom, NULL,
> "riscv_virt_board.mrom",
> >> >>> > +                           memmap[VIRT_MROM].size,
&error_fatal);
> >> >>> > +    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);
> >> >>> > @@ -335,13 +328,22 @@ static void
> riscv_virt_board_init(MachineState
> >> >>> *machine)
> >> >>> >                                        /* dtb: */
> >> >>> >       };

> >> >>> > -    /* copy in the reset vector */
> >> >>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
> >> >>> sizeof(reset_vec));
> >> >>> > +    /* copy in the reset vector in little_endian byte order */
> >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> >>> > +    }
> >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> sizeof(reset_vec),
> >> >>> > +                          memmap[VIRT_MROM].base,
> >> &address_space_memory);

> >> >>> >       /* copy in the device tree */
> >> >>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size -
> sizeof(reset_vec)) {
> >> >>> > +        error_report("qemu: not enough space to store
> device-tree");
> >> >>> > +        exit(1);
> >> >>> > +    }
> >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> >> >>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
> >> sizeof(reset_vec),
> >> >>> > -        s->fdt, s->fdt_size);
> >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> >> >>> > +                          memmap[VIRT_MROM].base +
> sizeof(reset_vec),
> >> >>> > +                          &address_space_memory);

> >> >>> >       /* create PLIC hart topology configuration string */
> >> >>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1)
*
> >> >>> smp_cpus;
> >> >>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> >> >>> > index 91163d6..6f2668e 100644
> >> >>> > --- a/include/hw/riscv/virt.h
> >> >>> > +++ b/include/hw/riscv/virt.h
> >> >>> > @@ -19,6 +19,10 @@
> >> >>> >   #ifndef HW_RISCV_VIRT_H
> >> >>> >   #define HW_RISCV_VIRT_H

> >> >>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
> >> >>> > +#define VIRT(obj) \
> >> >>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
> >> >>> > +

> >> >>> This should be in a seperate patch.


> >> >> I'll shift that chunk into "Remove unused class definitions".


> >> > Actually we to need to drop this chunk as the unused check macros
were
> >> removed from machine state structs in "Remove unused class
definitions".
> >> Somehow the chunk made it into this patch. Likely a rebase issue.

> >> > It's probably best that we add what we need back in the QOM SOC
> refactor
> >> on-top of the this series, or at least after the first set of patches
are
> >> merged...

> >> > I think that's what you were planning to do anyway.

> >> Yeah, that works. So just remove it from this series.


> > After rebasing I had to change this patch because of this patch which
> increases the default device tree size to 1MiB. This is not controllable
by
> the user and we don't know how big the resultant device-tree is. It could
> be < 8KiB in our case.

> > -

https://git.qemu.org/?p=qemu.git;a=commit;h=14ec3cbd7c1e31dca4d23f028100c8f43e156573

> > I studied ftd and used public interfaces and a mechanism consistent with
> the fdt resize functions to calculate the size. As far as I can tell it is
> accurate and covers exactly to the end of the uint32 terminator. I needed
> this because our ROMs are currently small.

> > Peter, this is the patch that changes our ROMs from RAM to ROM using
> memory_region_init_rom and rom_add_blob_fixed_as (as per hw/arm/boot.c),
> and it also adds a truncation warning, so that we actually know what size
> the device-tree is, given our ROMs are currently much smaller than 1MiB.
> That is why we needed a method that tells us how big the device tree
> actually is.

> > BTW I'm actually suspicious of 'fdt_resize' here:

> > -

https://git.qemu.org/?p=dtc.git;a=blob;f=libfdt/fdt_sw.c;h=6d33cc29d0224d9fc6307607ef7563df944da2d3

> > as it doesn't check that 'bufsize' has enough space for the header and
> terminator, although that's potentially a dtc bug. I read dtc to make sure
> the method we use to calculate the size was accurate. There probably
should
> be a method in dtc as we rely on some implementation details, however they
> are quite simple and we can get: sizeof(header) + sizeof(structs) +
> sizeof(strings) + terminator using public APIs and basic knowledge of the
> serialised device-tree form.

> > Anyway, here is the rebased version of this patch using the new
> 'qemu_fdt_totalsize' method in the patch I just sent.

> > -

https://github.com/riscv/riscv-qemu/commit/a65f6e0447d6e32d75f64ba31df5f20d529d0489

> > I have a feeling this is the patch that fixes sifive_u. Did you bisect
> which patch in the series fixed sifive_u?

> I agree, I think this is the patch.

> No, I havent' bisected it. I didn't think there was much point, but if we
> want patches backported to stable I guess there is. I'll dig into it.

Yep, just checked this patch is the first patch in which the SiFive U
machine works.

If this patch is rebased onto master if also works, so only this patch is
required.

Alistair



> > I have to send a pull for the reviewed patches which I can do today, but
> this is one of the patches that is early in the series that does not yet
> have Reviewed-by. When I split the series this patch would be in a second
> series that i'll have to link to the pull in patchew (using the method
> Peter mentioned) or wait until the pull is accepted.

> Great, let's get the first part of the series merged. It'd be nice to send
> out the next version of the second part while the PR is being merged.

> Alistair


> > Michael.

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

* Re: [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code
  2018-05-04 23:54               ` Alistair Francis
@ 2018-05-05  2:02                 ` Michael Clark
  0 siblings, 0 replies; 76+ messages in thread
From: Michael Clark @ 2018-05-05  2:02 UTC (permalink / raw)
  Cc: qemu-devel@nongnu.org Developers, Sagar Karandikar,
	Bastian Koppelmann, Palmer Dabbelt, Alistair Francis,
	RISC-V Patches, Peter Crosthwaite, Alexander Graf, Peter Maydell

On Sat, May 5, 2018 at 11:54 AM, Alistair Francis <alistair23@gmail.com>
wrote:

> On Fri, May 4, 2018 at 4:44 PM Alistair Francis <alistair23@gmail.com>
> wrote:
>
> > On Thu, May 3, 2018 at 6:45 PM Michael Clark <mjc@sifive.com> wrote:
>
>
>
> > > On Sat, Apr 28, 2018 at 4:17 AM, Alistair Francis <
> alistair23@gmail.com>
> > wrote:
>
> > >> On Thu, Apr 26, 2018 at 10:34 PM Michael Clark <mjc@sifive.com>
> wrote:
>
>
>
> > >> > On Fri, Apr 27, 2018 at 5:22 PM, Michael Clark <mjc@sifive.com>
> wrote:
>
>
>
> > >> >> On Fri, Apr 27, 2018 at 4:48 AM, Alistair Francis <
> > alistair23@gmail.com>
> > >> wrote:
>
> > >> >>> On Wed, Apr 25, 2018 at 5:03 PM Michael Clark <mjc@sifive.com>
> wrote:
>
> > >> >>> > The sifive_u machine already marks its ROM readonly. This fixes
> > >> >>> > the remaining boards. This commit also makes all boards use
> > >> >>> > mask_rom as the variable name for the ROM. This change also
> > >> >>> > makes space for the maximum device tree size size and adds
> > >> >>> > an explicit bounds check and error message.
>
> > >> >>> > 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_e.c     | 20 +++++++---------
> > >> >>> >   hw/riscv/sifive_u.c     | 46
> ++++++++++++++++++-----------------
> > >> >>> >   hw/riscv/spike.c        | 64
> > >> >>> ++++++++++++++++++++++++++++---------------------
> > >> >>> >   hw/riscv/virt.c         | 38 +++++++++++++++--------------
> > >> >>> >   include/hw/riscv/virt.h |  4 ++++
> > >> >>> >   5 files changed, 93 insertions(+), 79 deletions(-)
>
> > >> >>> > diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> > >> >>> > index 39e4cb4..0c8b8e9 100644
> > >> >>> > --- a/hw/riscv/sifive_e.c
> > >> >>> > +++ b/hw/riscv/sifive_e.c
> > >> >>> > @@ -74,14 +74,6 @@ static const struct MemmapEntry {
> > >> >>> >       [SIFIVE_E_DTIM] =     { 0x80000000,     0x4000 }
> > >> >>> >   };
>
> > >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> > len)
> > >> >>> > -{
> > >> >>> > -    int i;
> > >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> > >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2),
> rom[i]);
> > >> >>> > -    }
> > >> >>> > -}
> > >> >>> > -
> > >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> > >> >>> >   {
> > >> >>> >       uint64_t kernel_entry, kernel_high;
> > >> >>> > @@ -112,6 +104,7 @@ static void riscv_sifive_e_init(
> MachineState
> > >> *machine)
> > >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > >> >>> >       MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > >> >>> >       MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
> > >> >>> > +    int i;
>
> > >> >>> >       /* Initialize SOC */
> > >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> > >> TYPE_RISCV_HART_ARRAY);
> > >> >>> > @@ -131,7 +124,7 @@ static void riscv_sifive_e_init(
> MachineState
> > >> *machine)
> > >> >>> >           memmap[SIFIVE_E_DTIM].base, main_mem);
>
> > >> >>> >       /* Mask ROM */
> > >> >>> > -    memory_region_init_ram(mask_rom, NULL,
> "riscv.sifive.e.mrom",
> > >> >>> > +    memory_region_init_rom(mask_rom, NULL,
> "riscv.sifive.e.mrom",
> > >> >>> >           memmap[SIFIVE_E_MROM].size, &error_fatal);
> > >> >>> >       memory_region_add_subregion(sys_mem,
> > >> >>> >           memmap[SIFIVE_E_MROM].base, mask_rom);
> > >> >>> > @@ -185,9 +178,12 @@ static void riscv_sifive_e_init(
> MachineState
> > >> >>> *machine)
> > >> >>> >           0x00028067,        /* 0x1004: jr      t0 */
> > >> >>> >       };
>
> > >> >>> > -    /* copy in the reset vector */
> > >> >>> > -    copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec,
> > >> >>> sizeof(reset_vec));
> > >> >>> > -    memory_region_set_readonly(mask_rom, true);
> > >> >>> > +    /* copy in the reset vector in little_endian byte order */
> > >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > >> >>> > +    }
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> > sizeof(reset_vec),
> > >> >>> > +                          memmap[SIFIVE_E_MROM].base,
> > >> >>> &address_space_memory);
>
> > >> >>> >       if (machine->kernel_filename) {
> > >> >>> >           load_kernel(machine->kernel_filename);
> > >> >>> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> > >> >>> > index 115618b..11ba4c3 100644
> > >> >>> > --- a/hw/riscv/sifive_u.c
> > >> >>> > +++ b/hw/riscv/sifive_u.c
> > >> >>> > @@ -52,7 +52,7 @@ static const struct MemmapEntry {
> > >> >>> >       hwaddr size;
> > >> >>> >   } sifive_u_memmap[] = {
> > >> >>> >       [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
> > >> >>> > -    [SIFIVE_U_MROM] =     {     0x1000,     0x2000 },
> > >> >>> > +    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
> > >> >>> >       [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
> > >> >>> >       [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
> > >> >>> >       [SIFIVE_U_UART0] =    { 0x10013000,     0x1000 },
> > >> >>> > @@ -60,14 +60,6 @@ static const struct MemmapEntry {
> > >> >>> >       [SIFIVE_U_DRAM] =     { 0x80000000,        0x0 },
> > >> >>> >   };
>
> > >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> > len)
> > >> >>> > -{
> > >> >>> > -    int i;
> > >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> > >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2),
> rom[i]);
> > >> >>> > -    }
> > >> >>> > -}
> > >> >>> > -
> > >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> > >> >>> >   {
> > >> >>> >       uint64_t kernel_entry, kernel_high;
> > >> >>> > @@ -221,9 +213,10 @@ static void riscv_sifive_u_init(
> MachineState
> > >> >>> *machine)
> > >> >>> >       const struct MemmapEntry *memmap = sifive_u_memmap;
>
> > >> >>> >       SiFiveUState *s = g_new0(SiFiveUState, 1);
> > >> >>> > -    MemoryRegion *sys_memory = get_system_memory();
> > >> >>> > +    MemoryRegion *system_memory = get_system_memory();
> > >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    int i;
>
> > >> >>> >       /* Initialize SOC */
> > >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> > >> TYPE_RISCV_HART_ARRAY);
> > >> >>> > @@ -239,17 +232,17 @@ static void
> riscv_sifive_u_init(MachineState
> > >> >>> *machine)
> > >> >>> >       /* register RAM */
> > >> >>> >       memory_region_init_ram(main_mem, NULL,
> "riscv.sifive.u.ram",
> > >> >>> >                              machine->ram_size, &error_fatal);
> > >> >>> > -    memory_region_add_subregion(sys_memory,
> > >> memmap[SIFIVE_U_DRAM].base,
> > >> >>> > +    memory_region_add_subregion(system_memory,
> > >> >>> memmap[SIFIVE_U_DRAM].base,
> > >> >>> >           main_mem);
>
> > >> >>> >       /* create device tree */
> > >> >>> >       create_fdt(s, memmap, machine->ram_size,
> > >> machine->kernel_cmdline);
>
> > >> >>> >       /* boot rom */
> > >> >>> > -    memory_region_init_ram(boot_rom, NULL,
> "riscv.sifive.u.mrom",
> > >> >>> > -                           memmap[SIFIVE_U_MROM].base,
> > &error_fatal);
> > >> >>> > -    memory_region_set_readonly(boot_rom, true);
> > >> >>> > -    memory_region_add_subregion(sys_memory, 0x0, boot_rom);
> > >> >>> > +    memory_region_init_rom(mask_rom, NULL,
> "riscv.sifive.u.mrom",
> > >> >>> > +                           memmap[SIFIVE_U_MROM].size,
> > &error_fatal);
> > >> >>> > +    memory_region_add_subregion(system_memory,
> > >> >>> memmap[SIFIVE_U_MROM].base,
> > >> >>> > +                                mask_rom);
>
> > >> >>> >       if (machine->kernel_filename) {
> > >> >>> >           load_kernel(machine->kernel_filename);
> > >> >>> > @@ -272,13 +265,22 @@ static void
> riscv_sifive_u_init(MachineState
> > >> >>> *machine)
> > >> >>> >                                          /* dtb: */
> > >> >>> >       };
>
> > >> >>> > -    /* copy in the reset vector */
> > >> >>> > -    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
> > >> >>> sizeof(reset_vec));
> > >> >>> > +    /* copy in the reset vector in little_endian byte order */
> > >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > >> >>> > +    }
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> > sizeof(reset_vec),
> > >> >>> > +                          memmap[SIFIVE_U_MROM].base,
> > >> >>> &address_space_memory);
>
> > >> >>> >       /* copy in the device tree */
> > >> >>> > +    if (s->fdt_size >= memmap[SIFIVE_U_MROM].size -
> > >> sizeof(reset_vec)) {
> > >> >>> > +        error_report("qemu: not enough space to store
> > device-tree");
> > >> >>> > +        exit(1);
> > >> >>> > +    }
> > >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > >> >>> > -    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
> > >> >>> > -        sizeof(reset_vec), s->fdt, s->fdt_size);
> > >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > >> >>> > +                          memmap[SIFIVE_U_MROM].base +
> > >> sizeof(reset_vec),
> > >> >>> > +                          &address_space_memory);
>
> > >> >>> >       /* MMIO */
> > >> >>> >       s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
> > >> >>> > @@ -292,9 +294,9 @@ static void riscv_sifive_u_init(
> MachineState
> > >> *machine)
> > >> >>> >           SIFIVE_U_PLIC_CONTEXT_BASE,
> > >> >>> >           SIFIVE_U_PLIC_CONTEXT_STRIDE,
> > >> >>> >           memmap[SIFIVE_U_PLIC].size);
> > >> >>> > -    sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
> > >> >>> > +    sifive_uart_create(system_memory,
> memmap[SIFIVE_U_UART0].base,
> > >> >>> >           serial_hds[0],
> > >> SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
> > >> >>> > -    /* sifive_uart_create(sys_memory,
> memmap[SIFIVE_U_UART1].base,
> > >> >>> > +    /* sifive_uart_create(system_memory,
> > memmap[SIFIVE_U_UART1].base,
> > >> >>> >           serial_hds[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,
> > >> >>> > diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> > >> >>> > index 3f6bd0a..d1dbe6b 100644
> > >> >>> > --- a/hw/riscv/spike.c
> > >> >>> > +++ b/hw/riscv/spike.c
> > >> >>> > @@ -46,19 +46,11 @@ static const struct MemmapEntry {
> > >> >>> >       hwaddr base;
> > >> >>> >       hwaddr size;
> > >> >>> >   } spike_memmap[] = {
> > >> >>> > -    [SPIKE_MROM] =     {     0x1000,     0x2000 },
> > >> >>> > +    [SPIKE_MROM] =     {     0x1000,    0x11000 },
> > >> >>> >       [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
> > >> >>> >       [SPIKE_DRAM] =     { 0x80000000,        0x0 },
> > >> >>> >   };
>
> > >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> > len)
> > >> >>> > -{
> > >> >>> > -    int i;
> > >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> > >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2),
> rom[i]);
> > >> >>> > -    }
> > >> >>> > -}
> > >> >>> > -
> > >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> > >> >>> >   {
> > >> >>> >       uint64_t kernel_entry, kernel_high;
> > >> >>> > @@ -173,7 +165,8 @@ static void
> > spike_v1_10_0_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> > >> >>> >       MemoryRegion *system_memory = get_system_memory();
> > >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    int i;
>
> > >> >>> >       /* Initialize SOC */
> > >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> > >> TYPE_RISCV_HART_ARRAY);
> > >> >>> > @@ -196,9 +189,10 @@ static void
> > spike_v1_10_0_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       create_fdt(s, memmap, machine->ram_size,
> > >> machine->kernel_cmdline);
>
> > >> >>> >       /* boot rom */
> > >> >>> > -    memory_region_init_ram(boot_rom, NULL,
> "riscv.spike.bootrom",
> > >> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> > >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > >> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> > >> >>> > +                           memmap[SPIKE_MROM].size,
> &error_fatal);
> > >> >>> > +    memory_region_add_subregion(system_memory,
> > >> memmap[SPIKE_MROM].base,
> > >> >>> > +                                mask_rom);
>
> > >> >>> >       if (machine->kernel_filename) {
> > >> >>> >           load_kernel(machine->kernel_filename);
> > >> >>> > @@ -221,16 +215,25 @@ static void
> > >> spike_v1_10_0_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >                                        /* dtb: */
> > >> >>> >       };
>
> > >> >>> > -    /* copy in the reset vector */
> > >> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> > >> >>> sizeof(reset_vec));
> > >> >>> > +    /* copy in the reset vector in little_endian byte order */
> > >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > >> >>> > +    }
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> > sizeof(reset_vec),
> > >> >>> > +                          memmap[SPIKE_MROM].base,
> > >> >>> &address_space_memory);
>
> > >> >>> >       /* copy in the device tree */
> > >> >>> > +    if (s->fdt_size >= memmap[SPIKE_MROM].size -
> > sizeof(reset_vec)) {
> > >> >>> > +        error_report("qemu: not enough space to store
> > device-tree");
> > >> >>> > +        exit(1);
> > >> >>> > +    }
> > >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > >> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> > >> >>> sizeof(reset_vec),
> > >> >>> > -        s->fdt, s->fdt_size);
> > >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > >> >>> > +                          memmap[SPIKE_MROM].base +
> > >> sizeof(reset_vec),
> > >> >>> > +                          &address_space_memory);
>
> > >> >>> >       /* initialize HTIF using symbols found in load_kernel */
> > >> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> > >> >>> serial_hds[0]);
> > >> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> > >> >>> serial_hds[0]);
>
> > >> >>> >       /* Core Local Interruptor (timer and IPI) */
> > >> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> > >> >>> memmap[SPIKE_CLINT].size,
> > >> >>> > @@ -244,7 +247,8 @@ static void
> > spike_v1_09_1_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       SpikeState *s = g_new0(SpikeState, 1);
> > >> >>> >       MemoryRegion *system_memory = get_system_memory();
> > >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    int i;
>
> > >> >>> >       /* Initialize SOC */
> > >> >>> >       object_initialize(&s->soc, sizeof(s->soc),
> > >> TYPE_RISCV_HART_ARRAY);
> > >> >>> > @@ -264,9 +268,10 @@ static void
> > spike_v1_09_1_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >           main_mem);
>
> > >> >>> >       /* boot rom */
> > >> >>> > -    memory_region_init_ram(boot_rom, NULL,
> "riscv.spike.bootrom",
> > >> >>> > -                           0x40000, &error_fatal);
> > >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > >> >>> > +    memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
> > >> >>> > +                           memmap[SPIKE_MROM].size,
> &error_fatal);
> > >> >>> > +    memory_region_add_subregion(system_memory,
> > >> memmap[SPIKE_MROM].base,
> > >> >>> > +                                mask_rom);
>
> > >> >>> >       if (machine->kernel_filename) {
> > >> >>> >           load_kernel(machine->kernel_filename);
> > >> >>> > @@ -319,15 +324,20 @@ static void
> > >> spike_v1_09_1_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       g_free(isa);
> > >> >>> >       size_t config_string_len = strlen(config_string);
>
> > >> >>> > -    /* copy in the reset vector */
> > >> >>> > -    copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec,
> > >> >>> sizeof(reset_vec));
> > >> >>> > +    /* copy in the reset vector in little_endian byte order */
> > >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > >> >>> > +    }
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> > sizeof(reset_vec),
> > >> >>> > +                          memmap[SPIKE_MROM].base,
> > >> >>> &address_space_memory);
>
> > >> >>> >       /* copy in the config string */
> > >> >>> > -    cpu_physical_memory_write(memmap[SPIKE_MROM].base +
> > >> >>> sizeof(reset_vec),
> > >> >>> > -        config_string, config_string_len);
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", config_string,
> > >> config_string_len,
> > >> >>> > +                          memmap[SPIKE_MROM].base +
> > >> sizeof(reset_vec),
> > >> >>> > +                          &address_space_memory);
>
> > >> >>> >       /* initialize HTIF using symbols found in load_kernel */
> > >> >>> > -    htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env,
> > >> >>> serial_hds[0]);
> > >> >>> > +    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env,
> > >> >>> serial_hds[0]);
>
> > >> >>> >       /* Core Local Interruptor (timer and IPI) */
> > >> >>> >       sifive_clint_create(memmap[SPIKE_CLINT].base,
> > >> >>> memmap[SPIKE_CLINT].size,
> > >> >>> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > >> >>> > index 090befe..20c509d 100644
> > >> >>> > --- a/hw/riscv/virt.c
> > >> >>> > +++ b/hw/riscv/virt.c
> > >> >>> > @@ -45,8 +45,8 @@ static const struct MemmapEntry {
> > >> >>> >       hwaddr size;
> > >> >>> >   } virt_memmap[] = {
> > >> >>> >       [VIRT_DEBUG] =    {        0x0,      0x100 },
> > >> >>> > -    [VIRT_MROM] =     {     0x1000,     0x2000 },
> > >> >>> > -    [VIRT_TEST] =     {     0x4000,     0x1000 },
> > >> >>> > +    [VIRT_MROM] =     {     0x1000,    0x11000 },
> > >> >>> > +    [VIRT_TEST] =     {   0x100000,     0x1000 },
> > >> >>> >       [VIRT_CLINT] =    {  0x2000000,    0x10000 },
> > >> >>> >       [VIRT_PLIC] =     {  0xc000000,  0x4000000 },
> > >> >>> >       [VIRT_UART0] =    { 0x10000000,      0x100 },
> > >> >>> > @@ -54,14 +54,6 @@ static const struct MemmapEntry {
> > >> >>> >       [VIRT_DRAM] =     { 0x80000000,        0x0 },
> > >> >>> >   };
>
> > >> >>> > -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t
> > len)
> > >> >>> > -{
> > >> >>> > -    int i;
> > >> >>> > -    for (i = 0; i < (len >> 2); i++) {
> > >> >>> > -        stl_phys(&address_space_memory, pa + (i << 2),
> rom[i]);
> > >> >>> > -    }
> > >> >>> > -}
> > >> >>> > -
> > >> >>> >   static uint64_t load_kernel(const char *kernel_filename)
> > >> >>> >   {
> > >> >>> >       uint64_t kernel_entry, kernel_high;
> > >> >>> > @@ -272,7 +264,7 @@ static void
> riscv_virt_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       RISCVVirtState *s = g_new0(RISCVVirtState, 1);
> > >> >>> >       MemoryRegion *system_memory = get_system_memory();
> > >> >>> >       MemoryRegion *main_mem = g_new(MemoryRegion, 1);
> > >> >>> > -    MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> > >> >>> > +    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
> > >> >>> >       char *plic_hart_config;
> > >> >>> >       size_t plic_hart_config_len;
> > >> >>> >       int i;
> > >> >>> > @@ -299,9 +291,10 @@ static void
> riscv_virt_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >       fdt = create_fdt(s, memmap, machine->ram_size,
> > >> >>> machine->kernel_cmdline);
>
> > >> >>> >       /* boot rom */
> > >> >>> > -    memory_region_init_ram(boot_rom, NULL,
> > >> "riscv_virt_board.bootrom",
> > >> >>> > -                           s->fdt_size + 0x2000, &error_fatal);
> > >> >>> > -    memory_region_add_subregion(system_memory, 0x0, boot_rom);
> > >> >>> > +    memory_region_init_rom(mask_rom, NULL,
> > "riscv_virt_board.mrom",
> > >> >>> > +                           memmap[VIRT_MROM].size,
> &error_fatal);
> > >> >>> > +    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);
> > >> >>> > @@ -335,13 +328,22 @@ static void
> > riscv_virt_board_init(MachineState
> > >> >>> *machine)
> > >> >>> >                                        /* dtb: */
> > >> >>> >       };
>
> > >> >>> > -    /* copy in the reset vector */
> > >> >>> > -    copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec,
> > >> >>> sizeof(reset_vec));
> > >> >>> > +    /* copy in the reset vector in little_endian byte order */
> > >> >>> > +    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > >> >>> > +        reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > >> >>> > +    }
> > >> >>> > +    rom_add_blob_fixed_as("mrom.reset", reset_vec,
> > sizeof(reset_vec),
> > >> >>> > +                          memmap[VIRT_MROM].base,
> > >> &address_space_memory);
>
> > >> >>> >       /* copy in the device tree */
> > >> >>> > +    if (s->fdt_size >= memmap[VIRT_MROM].size -
> > sizeof(reset_vec)) {
> > >> >>> > +        error_report("qemu: not enough space to store
> > device-tree");
> > >> >>> > +        exit(1);
> > >> >>> > +    }
> > >> >>> >       qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
> > >> >>> > -    cpu_physical_memory_write(memmap[VIRT_MROM].base +
> > >> sizeof(reset_vec),
> > >> >>> > -        s->fdt, s->fdt_size);
> > >> >>> > +    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
> > >> >>> > +                          memmap[VIRT_MROM].base +
> > sizeof(reset_vec),
> > >> >>> > +                          &address_space_memory);
>
> > >> >>> >       /* create PLIC hart topology configuration string */
> > >> >>> >       plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1)
> *
> > >> >>> smp_cpus;
> > >> >>> > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
> > >> >>> > index 91163d6..6f2668e 100644
> > >> >>> > --- a/include/hw/riscv/virt.h
> > >> >>> > +++ b/include/hw/riscv/virt.h
> > >> >>> > @@ -19,6 +19,10 @@
> > >> >>> >   #ifndef HW_RISCV_VIRT_H
> > >> >>> >   #define HW_RISCV_VIRT_H
>
> > >> >>> > +#define TYPE_RISCV_VIRT_BOARD "riscv.virt"
> > >> >>> > +#define VIRT(obj) \
> > >> >>> > +    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD)
> > >> >>> > +
>
> > >> >>> This should be in a seperate patch.
>
>
> > >> >> I'll shift that chunk into "Remove unused class definitions".
>
>
> > >> > Actually we to need to drop this chunk as the unused check macros
> were
> > >> removed from machine state structs in "Remove unused class
> definitions".
> > >> Somehow the chunk made it into this patch. Likely a rebase issue.
>
> > >> > It's probably best that we add what we need back in the QOM SOC
> > refactor
> > >> on-top of the this series, or at least after the first set of patches
> are
> > >> merged...
>
> > >> > I think that's what you were planning to do anyway.
>
> > >> Yeah, that works. So just remove it from this series.
>
>
> > > After rebasing I had to change this patch because of this patch which
> > increases the default device tree size to 1MiB. This is not controllable
> by
> > the user and we don't know how big the resultant device-tree is. It could
> > be < 8KiB in our case.
>
> > > -
>
> https://git.qemu.org/?p=qemu.git;a=commit;h=14ec3cbd7c1e31dca4d23f028100c8
> f43e156573
>
> > > I studied ftd and used public interfaces and a mechanism consistent
> with
> > the fdt resize functions to calculate the size. As far as I can tell it
> is
> > accurate and covers exactly to the end of the uint32 terminator. I needed
> > this because our ROMs are currently small.
>
> > > Peter, this is the patch that changes our ROMs from RAM to ROM using
> > memory_region_init_rom and rom_add_blob_fixed_as (as per hw/arm/boot.c),
> > and it also adds a truncation warning, so that we actually know what size
> > the device-tree is, given our ROMs are currently much smaller than 1MiB.
> > That is why we needed a method that tells us how big the device tree
> > actually is.
>
> > > BTW I'm actually suspicious of 'fdt_resize' here:
>
> > > -
>
> https://git.qemu.org/?p=dtc.git;a=blob;f=libfdt/fdt_sw.c;h=
> 6d33cc29d0224d9fc6307607ef7563df944da2d3
>
> > > as it doesn't check that 'bufsize' has enough space for the header and
> > terminator, although that's potentially a dtc bug. I read dtc to make
> sure
> > the method we use to calculate the size was accurate. There probably
> should
> > be a method in dtc as we rely on some implementation details, however
> they
> > are quite simple and we can get: sizeof(header) + sizeof(structs) +
> > sizeof(strings) + terminator using public APIs and basic knowledge of the
> > serialised device-tree form.
>
> > > Anyway, here is the rebased version of this patch using the new
> > 'qemu_fdt_totalsize' method in the patch I just sent.
>
> > > -
>
> https://github.com/riscv/riscv-qemu/commit/a65f6e0447d6e32d75f64ba31df5f2
> 0d529d0489
>
> > > I have a feeling this is the patch that fixes sifive_u. Did you bisect
> > which patch in the series fixed sifive_u?
>
> > I agree, I think this is the patch.
>
> > No, I havent' bisected it. I didn't think there was much point, but if we
> > want patches backported to stable I guess there is. I'll dig into it.
>
> Yep, just checked this patch is the first patch in which the SiFive U
> machine works.
>
> If this patch is rebased onto master if also works, so only this patch is
> required.
>
> Alistair
>
>
>
> > > I have to send a pull for the reviewed patches which I can do today,
> but
> > this is one of the patches that is early in the series that does not yet
> > have Reviewed-by. When I split the series this patch would be in a second
> > series that i'll have to link to the pull in patchew (using the method
> > Peter mentioned) or wait until the pull is accepted.
>
> > Great, let's get the first part of the series merged. It'd be nice to
> send
> > out the next version of the second part while the PR is being merged.
>

Okay, I assume I can add your "Reviewed-by:" to this patch which fixes a
bubble in the early set of sequential patches.

I need to do the PR... however we now depend on review for this patch due
to a recent device_tree change in upstream:

- https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg00892.html

We have small ROMs on these machines. They are smaller than the new 1MiB
default introduced in 14ec3cbd7c1e31dca4d23f028100c8f43e156573 which is now
in master.

I'm disinclined towards bumping the ROM sizes when it is reasonable to want
to be able to query the size of the  device_tree. 1MiB mask ROM is possibly
too large for some small embedded system mask ROMs. However if we can't
merge the qemu_fdt_totalsize patch then we'll need to bump all of the ROM
sizes.

Relying on cpu_physical_memory_write and rom_add_blob_fixed_as to silently
drop writes doesn't allow us to detect device-tree truncation (which
happened to me). I could remove the check and we'd then be relying on
rom_add_blob_fixed_as
adding a block that is larger than the ROM we created from the memory map.

In fact, the warning triggered when I rebased and tested linux in 'virt',
due to the current ROM size, which resulted in me implementing
qemu_fdt_totalsize. It now means we detecting whether the device tree is
going to be truncated versus checking whether the default buffer length
from create_device_tree fits within the ROM.

This is a snippet from the rebased version of "Mark ROM read-only after
copying in code".  I just added one line with "s->fdt_size =
qemu_fdt_totalsize(s->fdt);" before the device tree ROM size check and call
to rom_add_blob_fixed_as, which means we only copy in the actual. I've
tested 'virt' with 8 CPUs (as that's the current limit for CPU stacks in
the bbl firmware) to make sure qemu_fdt_totalsize is working, which it is.

-    /* copy in the reset vector */
-    copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec,
sizeof(reset_vec));
+    /* copy in the reset vector in little_endian byte order */
+    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+        reset_vec[i] = cpu_to_le32(reset_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+                          memmap[SIFIVE_U_MROM].base,
&address_space_memory);

     /* copy in the device tree */
+    s->fdt_size = qemu_fdt_totalsize(s->fdt);
+    if (s->fdt_size > memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
+        error_report("not enough space to store device-tree");
+        exit(1);
+    }
     qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
-    cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
-        sizeof(reset_vec), s->fdt, s->fdt_size);
+    rom_add_blob_fixed_as("mrom.fdt", s->fdt, s->fdt_size,
+                          memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
+                          &address_space_memory);

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

end of thread, other threads:[~2018-05-05  2:02 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-25 23:45 [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 01/35] RISC-V: Replace hardcoded constants with enum values Michael Clark
2018-04-26 16:37   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 02/35] RISC-V: Make virt board description match spike Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 03/35] RISC-V: Use ROM base address and size from memmap Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 04/35] RISC-V: Remove identity_translate from load_elf Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 05/35] RISC-V: Remove unused class definitions Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 06/35] RISC-V: Include instruction hex in disassembly Michael Clark
2018-04-26 17:05   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 07/35] RISC-V: Make some header guards more specific Michael Clark
2018-04-26 16:43   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 08/35] RISC-V: Make virt header comment title consistent Michael Clark
2018-04-26 16:42   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 09/35] RISC-V: Remove EM_RISCV ELF_MACHINE indirection Michael Clark
2018-04-26 16:42   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 10/35] RISC-V: Remove erroneous comment from translate.c Michael Clark
2018-04-25 23:51   ` [Qemu-devel] [patches] " Palmer Dabbelt
2018-04-26 16:48   ` [Qemu-devel] " Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 11/35] RISC-V: Mark ROM read-only after copying in code Michael Clark
2018-04-26 16:48   ` Alistair Francis
2018-04-27  5:22     ` Michael Clark
2018-04-27  5:34       ` Michael Clark
2018-04-27 16:17         ` Alistair Francis
2018-05-04  1:45           ` Michael Clark
2018-05-04 23:44             ` Alistair Francis
2018-05-04 23:54               ` Alistair Francis
2018-05-05  2:02                 ` Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 12/35] RISC-V: Update address bits to support sv39 and sv48 Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 13/35] RISC-V: Improve page table walker spec compliance Michael Clark
2018-05-03 20:49   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 14/35] RISC-V: Update E order and I extension order Michael Clark
2018-04-26 17:11   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 15/35] RISC-V: Hardwire satp to 0 for no-mmu case Michael Clark
2018-04-26 17:21   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 16/35] RISC-V: Make mtvec/stvec ignore vectored traps Michael Clark
2018-04-26 17:27   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 17/35] RISC-V: No traps on writes to misa, minstret, mcycle Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 18/35] RISC-V: Clear mtval/stval on exceptions without info Michael Clark
2018-04-26 17:36   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 19/35] RISC-V: Allow S-mode mxr access when priv ISA >= v1.10 Michael Clark
2018-04-26 20:02   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 20/35] RISC-V: Use [ms]counteren CSRs " Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 21/35] RISC-V: Add mcycle/minstret support for -icount auto Michael Clark
2018-04-26 20:05   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps Michael Clark
2018-04-27  0:14   ` Richard Henderson
2018-04-27  7:18     ` Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 23/35] RISC-V: Simplify riscv_cpu_local_irqs_pending Michael Clark
2018-04-27 22:33   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 24/35] RISC-V: Allow setting and clearing multiple irqs Michael Clark
2018-05-03 20:54   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 25/35] RISC-V: Move non-ops from op_helper to cpu_helper Michael Clark
2018-04-26 17:42   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 26/35] RISC-V: Update CSR and interrupt definitions Michael Clark
2018-05-03 20:56   ` Alistair Francis
2018-05-04  4:21     ` Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 27/35] RISC-V: Implement modular CSR helper interface Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 28/35] RISC-V: Implement atomic mip/sip CSR updates Michael Clark
2018-05-03 21:11   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 29/35] RISC-V: Implement existential predicates for CSRs Michael Clark
2018-05-03 21:21   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 30/35] RISC-V: Split out mstatus_fs from tb_flags Michael Clark
2018-05-03 21:22   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 31/35] RISC-V: Mark mstatus.fs dirty Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 32/35] RISC-V: Implement mstatus.TSR/TW/TVM Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 33/35] RISC-V: Add public API for the CSR dispatch table Michael Clark
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 34/35] RISC-V: Add hartid and \n to interrupt logging Michael Clark
2018-05-03 21:25   ` Alistair Francis
2018-04-25 23:45 ` [Qemu-devel] [PATCH v8 35/35] RISC-V: Use riscv prefix consistently on cpu helpers Michael Clark
2018-04-26  1:42 ` [Qemu-devel] [PATCH v8 00/35] QEMU 2.13 Privileged ISA emulation updates Michael Clark
2018-04-26  2:01   ` Michael Clark
2018-04-26 18:22     ` Alistair Francis
2018-04-27  0:34       ` Michael Clark
2018-04-27 10:19         ` Peter Maydell
2018-04-27  0:35       ` Richard Henderson
2018-04-27  5:00         ` Michael Clark

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.