All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far)
@ 2023-07-11 12:14 Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 01/16] target/riscv: Remove unuseful KVM stubs Philippe Mathieu-Daudé
                   ` (15 more replies)
  0 siblings, 16 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

v3: Rebased on master
    (commit 94d68c1136, merge tag 'pull-riscv-to-apply-20230710-1')

Philippe Mathieu-Daudé (16):
  target/riscv: Remove unuseful KVM stubs
  target/riscv: Remove unused 'instmap.h' header in translate.c
  target/riscv: Restrict sysemu specific header to user emulation
  target/riscv: Restrict 'rv128' machine to TCG accelerator
  target/riscv: Move sysemu-specific files to target/riscv/sysemu/
  target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu
  target/riscv: Move TCG-specific files to target/riscv/tcg/
  target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c
  target/riscv: Expose some 'trigger' prototypes from debug.c
  target/riscv: Extract TCG-specific code from debug.c
  target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/
  target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c
  target/riscv: Move TCG/sysemu-specific code to tcg/sysemu/cpu_helper.c
  target/riscv: Move sysemu-specific code to sysemu/cpu_helper.c
  target/riscv: Restrict TCG-specific prototype declarations
  gitlab-ci.d/crossbuilds: Add KVM riscv64 cross-build jobs

 target/riscv/cpu.h                            |   27 +-
 target/riscv/internals.h                      |    4 +
 target/riscv/{ => sysemu}/debug.h             |    6 +
 target/riscv/{ => sysemu}/instmap.h           |    0
 target/riscv/{ => sysemu}/kvm_riscv.h         |    0
 target/riscv/{ => sysemu}/pmp.h               |    0
 target/riscv/{ => sysemu}/pmu.h               |    0
 target/riscv/{ => sysemu}/time_helper.h       |    0
 target/riscv/{ => tcg}/XVentanaCondOps.decode |    0
 target/riscv/{ => tcg}/insn16.decode          |    0
 target/riscv/{ => tcg}/insn32.decode          |    0
 target/riscv/{ => tcg}/xthead.decode          |    0
 hw/riscv/virt.c                               |    2 +-
 target/riscv/cpu.c                            |   35 +-
 target/riscv/cpu_helper.c                     | 1692 +----------------
 target/riscv/csr.c                            |    6 +-
 target/riscv/{ => sysemu}/arch_dump.c         |    0
 target/riscv/sysemu/cpu_helper.c              |  863 +++++++++
 target/riscv/{ => sysemu}/debug.c             |  153 +-
 target/riscv/{ => sysemu}/kvm-stub.c          |    0
 target/riscv/{ => sysemu}/kvm.c               |    4 +-
 target/riscv/{ => sysemu}/machine.c           |    0
 target/riscv/{ => sysemu}/monitor.c           |    0
 target/riscv/{ => sysemu}/pmp.c               |    0
 target/riscv/{ => sysemu}/pmu.c               |    0
 target/riscv/{ => sysemu}/riscv-qmp-cmds.c    |    0
 target/riscv/{ => sysemu}/time_helper.c       |    0
 target/riscv/{ => tcg}/bitmanip_helper.c      |    0
 target/riscv/tcg/cpu.c                        |   98 +
 target/riscv/{ => tcg}/crypto_helper.c        |    0
 target/riscv/{ => tcg}/fpu_helper.c           |    0
 target/riscv/{ => tcg}/m128_helper.c          |    0
 target/riscv/{ => tcg}/op_helper.c            |    0
 target/riscv/tcg/sysemu/cpu_helper.c          |  765 ++++++++
 target/riscv/tcg/sysemu/debug.c               |  165 ++
 target/riscv/tcg/tcg-stub.c                   |   31 +
 target/riscv/{ => tcg}/translate.c            |    1 -
 target/riscv/{ => tcg}/vector_helper.c        |    0
 target/riscv/{ => tcg}/zce_helper.c           |    0
 .gitlab-ci.d/crossbuilds.yml                  |    8 +
 target/riscv/meson.build                      |   33 +-
 target/riscv/sysemu/meson.build               |   13 +
 target/riscv/tcg/meson.build                  |   22 +
 target/riscv/tcg/sysemu/meson.build           |    4 +
 44 files changed, 2038 insertions(+), 1894 deletions(-)
 rename target/riscv/{ => sysemu}/debug.h (96%)
 rename target/riscv/{ => sysemu}/instmap.h (100%)
 rename target/riscv/{ => sysemu}/kvm_riscv.h (100%)
 rename target/riscv/{ => sysemu}/pmp.h (100%)
 rename target/riscv/{ => sysemu}/pmu.h (100%)
 rename target/riscv/{ => sysemu}/time_helper.h (100%)
 rename target/riscv/{ => tcg}/XVentanaCondOps.decode (100%)
 rename target/riscv/{ => tcg}/insn16.decode (100%)
 rename target/riscv/{ => tcg}/insn32.decode (100%)
 rename target/riscv/{ => tcg}/xthead.decode (100%)
 rename target/riscv/{ => sysemu}/arch_dump.c (100%)
 create mode 100644 target/riscv/sysemu/cpu_helper.c
 rename target/riscv/{ => sysemu}/debug.c (83%)
 rename target/riscv/{ => sysemu}/kvm-stub.c (100%)
 rename target/riscv/{ => sysemu}/kvm.c (99%)
 rename target/riscv/{ => sysemu}/machine.c (100%)
 rename target/riscv/{ => sysemu}/monitor.c (100%)
 rename target/riscv/{ => sysemu}/pmp.c (100%)
 rename target/riscv/{ => sysemu}/pmu.c (100%)
 rename target/riscv/{ => sysemu}/riscv-qmp-cmds.c (100%)
 rename target/riscv/{ => sysemu}/time_helper.c (100%)
 rename target/riscv/{ => tcg}/bitmanip_helper.c (100%)
 create mode 100644 target/riscv/tcg/cpu.c
 rename target/riscv/{ => tcg}/crypto_helper.c (100%)
 rename target/riscv/{ => tcg}/fpu_helper.c (100%)
 rename target/riscv/{ => tcg}/m128_helper.c (100%)
 rename target/riscv/{ => tcg}/op_helper.c (100%)
 create mode 100644 target/riscv/tcg/sysemu/cpu_helper.c
 create mode 100644 target/riscv/tcg/sysemu/debug.c
 create mode 100644 target/riscv/tcg/tcg-stub.c
 rename target/riscv/{ => tcg}/translate.c (99%)
 rename target/riscv/{ => tcg}/vector_helper.c (100%)
 rename target/riscv/{ => tcg}/zce_helper.c (100%)
 create mode 100644 target/riscv/sysemu/meson.build
 create mode 100644 target/riscv/tcg/meson.build
 create mode 100644 target/riscv/tcg/sysemu/meson.build

-- 
2.38.1



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

* [PATCH v3 01/16] target/riscv: Remove unuseful KVM stubs
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 02/16] target/riscv: Remove unused 'instmap.h' header in translate.c Philippe Mathieu-Daudé
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé,
	Alistair Francis

Since we always check whether KVM is enabled before calling
kvm_riscv_reset_vcpu() and kvm_riscv_set_irq(), their call
is elided by the compiler when KVM is not available.
Therefore the stubs are not even linked. Remove them.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/kvm-stub.c  | 30 ------------------------------
 target/riscv/kvm.c       |  4 +---
 target/riscv/meson.build |  2 +-
 3 files changed, 2 insertions(+), 34 deletions(-)
 delete mode 100644 target/riscv/kvm-stub.c

diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm-stub.c
deleted file mode 100644
index 4e8fc31a21..0000000000
--- a/target/riscv/kvm-stub.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * QEMU KVM RISC-V specific function stubs
- *
- * Copyright (c) 2020 Huawei Technologies Co., Ltd
- *
- * 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 "cpu.h"
-#include "kvm_riscv.h"
-
-void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
-{
-    abort();
-}
-
-void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
-{
-    abort();
-}
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index 9d8a8982f9..b2bbcd9058 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -984,9 +984,7 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
 {
     CPURISCVState *env = &cpu->env;
 
-    if (!kvm_enabled()) {
-        return;
-    }
+    assert(kvm_enabled());
     env->pc = cpu->env.kernel_addr;
     env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */
     env->gpr[11] = cpu->env.fdt_addr;          /* a1 */
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 7f56c5f88d..e3ab3df4e5 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -22,7 +22,7 @@ riscv_ss.add(files(
   'crypto_helper.c',
   'zce_helper.c'
 ))
-riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
+riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
 
 riscv_system_ss = ss.source_set()
 riscv_system_ss.add(files(
-- 
2.38.1



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

* [PATCH v3 02/16] target/riscv: Remove unused 'instmap.h' header in translate.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 01/16] target/riscv: Remove unuseful KVM stubs Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation Philippe Mathieu-Daudé
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé,
	Alistair Francis

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 697df1be9e..c65be83442 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -30,7 +30,6 @@
 #include "exec/log.h"
 #include "semihosting/semihost.h"
 
-#include "instmap.h"
 #include "internals.h"
 
 #define HELPER_H "helper.h"
-- 
2.38.1



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

* [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 01/16] target/riscv: Remove unuseful KVM stubs Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 02/16] target/riscv: Remove unused 'instmap.h' header in translate.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-12 15:18   ` Daniel Henrique Barboza
  2023-07-11 12:14 ` [PATCH v3 04/16] target/riscv: Restrict 'rv128' machine to TCG accelerator Philippe Mathieu-Daudé
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé,
	Alistair Francis

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c        | 10 ++++++----
 target/riscv/cpu_helper.c |  2 ++
 target/riscv/csr.c        |  2 ++
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9339c0241d..5712a54404 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -23,9 +23,14 @@
 #include "qemu/log.h"
 #include "cpu.h"
 #include "cpu_vendorid.h"
+#ifndef CONFIG_USER_ONLY
 #include "pmu.h"
-#include "internals.h"
 #include "time_helper.h"
+#include "sysemu/tcg.h"
+#include "sysemu/kvm.h"
+#include "kvm_riscv.h"
+#endif
+#include "internals.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
@@ -33,9 +38,6 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "fpu/softfloat-helpers.h"
-#include "sysemu/kvm.h"
-#include "sysemu/tcg.h"
-#include "kvm_riscv.h"
 #include "tcg/tcg.h"
 
 /* RISC-V CPU definitions */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9f611d89bb..e8b7f70be3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -28,7 +28,9 @@
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
+#ifndef CONFIG_USER_ONLY
 #include "sysemu/cpu-timers.h"
+#endif
 #include "cpu_bits.h"
 #include "debug.h"
 #include "tcg/oversized-guest.h"
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index ea7585329e..e5737dcf58 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -21,8 +21,10 @@
 #include "qemu/log.h"
 #include "qemu/timer.h"
 #include "cpu.h"
+#ifndef CONFIG_USER_ONLY
 #include "pmu.h"
 #include "time_helper.h"
+#endif
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
 #include "exec/tb-flush.h"
-- 
2.38.1



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

* [PATCH v3 04/16] target/riscv: Restrict 'rv128' machine to TCG accelerator
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (2 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 05/16] target/riscv: Move sysemu-specific files to target/riscv/sysemu/ Philippe Mathieu-Daudé
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé,
	Alistair Francis

We only build for 32/64-bit hosts, so TCG is required for
128-bit targets.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5712a54404..faf703afcb 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -495,6 +495,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj)
 #endif
 }
 
+#ifdef CONFIG_TCG
 static void rv128_base_cpu_init(Object *obj)
 {
     if (qemu_tcg_mttcg_enabled()) {
@@ -513,7 +514,10 @@ static void rv128_base_cpu_init(Object *obj)
     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
 #endif
 }
-#else
+#endif
+
+#else /* !TARGET_RISCV64 */
+
 static void rv32_base_cpu_init(Object *obj)
 {
     CPURISCVState *env = &RISCV_CPU(obj)->env;
@@ -595,7 +599,7 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
     cpu->cfg.ext_icsr = true;
     cpu->cfg.pmp = true;
 }
-#endif
+#endif /* !TARGET_RISCV64 */
 
 #if defined(CONFIG_KVM)
 static void riscv_host_cpu_init(Object *obj)
@@ -2274,8 +2278,10 @@ static const TypeInfo riscv_cpu_type_infos[] = {
     DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C,         rv64_sifive_u_cpu_init),
     DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906,       rv64_thead_c906_cpu_init),
     DEFINE_CPU(TYPE_RISCV_CPU_VEYRON_V1,        rv64_veyron_v1_cpu_init),
+#ifdef CONFIG_TCG
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
-#endif
+#endif /* CONFIG_TCG */
+#endif /* TARGET_RISCV64 */
 };
 
 DEFINE_TYPES(riscv_cpu_type_infos)
-- 
2.38.1



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

* [PATCH v3 05/16] target/riscv: Move sysemu-specific files to target/riscv/sysemu/
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (3 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 04/16] target/riscv: Restrict 'rv128' machine to TCG accelerator Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu Philippe Mathieu-Daudé
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé,
	Alistair Francis

Move sysemu-specific files to the a new 'sysemu' sub-directory,
adapt meson rules.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/cpu.h                         |  2 +-
 target/riscv/{ => sysemu}/instmap.h        |  0
 target/riscv/{ => sysemu}/kvm_riscv.h      |  0
 target/riscv/{ => sysemu}/pmp.h            |  0
 target/riscv/{ => sysemu}/pmu.h            |  0
 target/riscv/{ => sysemu}/time_helper.h    |  0
 hw/riscv/virt.c                            |  2 +-
 target/riscv/cpu.c                         |  6 ++---
 target/riscv/cpu_helper.c                  |  4 +--
 target/riscv/csr.c                         |  4 +--
 target/riscv/{ => sysemu}/arch_dump.c      |  0
 target/riscv/sysemu/kvm-stub.c             | 30 ++++++++++++++++++++++
 target/riscv/{ => sysemu}/kvm.c            |  0
 target/riscv/{ => sysemu}/machine.c        |  0
 target/riscv/{ => sysemu}/monitor.c        |  0
 target/riscv/{ => sysemu}/pmp.c            |  0
 target/riscv/{ => sysemu}/pmu.c            |  0
 target/riscv/{ => sysemu}/riscv-qmp-cmds.c |  0
 target/riscv/{ => sysemu}/time_helper.c    |  0
 target/riscv/meson.build                   | 13 +++-------
 target/riscv/sysemu/meson.build            | 11 ++++++++
 21 files changed, 54 insertions(+), 18 deletions(-)
 rename target/riscv/{ => sysemu}/instmap.h (100%)
 rename target/riscv/{ => sysemu}/kvm_riscv.h (100%)
 rename target/riscv/{ => sysemu}/pmp.h (100%)
 rename target/riscv/{ => sysemu}/pmu.h (100%)
 rename target/riscv/{ => sysemu}/time_helper.h (100%)
 rename target/riscv/{ => sysemu}/arch_dump.c (100%)
 create mode 100644 target/riscv/sysemu/kvm-stub.c
 rename target/riscv/{ => sysemu}/kvm.c (100%)
 rename target/riscv/{ => sysemu}/machine.c (100%)
 rename target/riscv/{ => sysemu}/monitor.c (100%)
 rename target/riscv/{ => sysemu}/pmp.c (100%)
 rename target/riscv/{ => sysemu}/pmu.c (100%)
 rename target/riscv/{ => sysemu}/riscv-qmp-cmds.c (100%)
 rename target/riscv/{ => sysemu}/time_helper.c (100%)
 create mode 100644 target/riscv/sysemu/meson.build

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6ea22e0eea..dba78db644 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -93,7 +93,7 @@ typedef enum {
 #define MAX_RISCV_PMPS (16)
 
 #if !defined(CONFIG_USER_ONLY)
-#include "pmp.h"
+#include "sysemu/pmp.h"
 #include "debug.h"
 #endif
 
diff --git a/target/riscv/instmap.h b/target/riscv/sysemu/instmap.h
similarity index 100%
rename from target/riscv/instmap.h
rename to target/riscv/sysemu/instmap.h
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/sysemu/kvm_riscv.h
similarity index 100%
rename from target/riscv/kvm_riscv.h
rename to target/riscv/sysemu/kvm_riscv.h
diff --git a/target/riscv/pmp.h b/target/riscv/sysemu/pmp.h
similarity index 100%
rename from target/riscv/pmp.h
rename to target/riscv/sysemu/pmp.h
diff --git a/target/riscv/pmu.h b/target/riscv/sysemu/pmu.h
similarity index 100%
rename from target/riscv/pmu.h
rename to target/riscv/sysemu/pmu.h
diff --git a/target/riscv/time_helper.h b/target/riscv/sysemu/time_helper.h
similarity index 100%
rename from target/riscv/time_helper.h
rename to target/riscv/sysemu/time_helper.h
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index d90286dc46..74f789a85b 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -30,7 +30,7 @@
 #include "hw/char/serial.h"
 #include "target/riscv/cpu.h"
 #include "hw/core/sysbus-fdt.h"
-#include "target/riscv/pmu.h"
+#include "target/riscv/sysemu/pmu.h"
 #include "hw/riscv/riscv_hart.h"
 #include "hw/riscv/virt.h"
 #include "hw/riscv/boot.h"
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index faf703afcb..91433f3041 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -24,11 +24,11 @@
 #include "cpu.h"
 #include "cpu_vendorid.h"
 #ifndef CONFIG_USER_ONLY
-#include "pmu.h"
-#include "time_helper.h"
+#include "sysemu/pmu.h"
+#include "sysemu/time_helper.h"
 #include "sysemu/tcg.h"
 #include "sysemu/kvm.h"
-#include "kvm_riscv.h"
+#include "sysemu/kvm_riscv.h"
 #endif
 #include "internals.h"
 #include "exec/exec-all.h"
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e8b7f70be3..0adde26321 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,9 +22,9 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "internals.h"
-#include "pmu.h"
+#include "sysemu/pmu.h"
 #include "exec/exec-all.h"
-#include "instmap.h"
+#include "sysemu/instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e5737dcf58..29151429ee 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -22,8 +22,8 @@
 #include "qemu/timer.h"
 #include "cpu.h"
 #ifndef CONFIG_USER_ONLY
-#include "pmu.h"
-#include "time_helper.h"
+#include "sysemu/pmu.h"
+#include "sysemu/time_helper.h"
 #endif
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
diff --git a/target/riscv/arch_dump.c b/target/riscv/sysemu/arch_dump.c
similarity index 100%
rename from target/riscv/arch_dump.c
rename to target/riscv/sysemu/arch_dump.c
diff --git a/target/riscv/sysemu/kvm-stub.c b/target/riscv/sysemu/kvm-stub.c
new file mode 100644
index 0000000000..4e8fc31a21
--- /dev/null
+++ b/target/riscv/sysemu/kvm-stub.c
@@ -0,0 +1,30 @@
+/*
+ * QEMU KVM RISC-V specific function stubs
+ *
+ * Copyright (c) 2020 Huawei Technologies Co., Ltd
+ *
+ * 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 "cpu.h"
+#include "kvm_riscv.h"
+
+void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
+{
+    abort();
+}
+
+void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
+{
+    abort();
+}
diff --git a/target/riscv/kvm.c b/target/riscv/sysemu/kvm.c
similarity index 100%
rename from target/riscv/kvm.c
rename to target/riscv/sysemu/kvm.c
diff --git a/target/riscv/machine.c b/target/riscv/sysemu/machine.c
similarity index 100%
rename from target/riscv/machine.c
rename to target/riscv/sysemu/machine.c
diff --git a/target/riscv/monitor.c b/target/riscv/sysemu/monitor.c
similarity index 100%
rename from target/riscv/monitor.c
rename to target/riscv/sysemu/monitor.c
diff --git a/target/riscv/pmp.c b/target/riscv/sysemu/pmp.c
similarity index 100%
rename from target/riscv/pmp.c
rename to target/riscv/sysemu/pmp.c
diff --git a/target/riscv/pmu.c b/target/riscv/sysemu/pmu.c
similarity index 100%
rename from target/riscv/pmu.c
rename to target/riscv/sysemu/pmu.c
diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/sysemu/riscv-qmp-cmds.c
similarity index 100%
rename from target/riscv/riscv-qmp-cmds.c
rename to target/riscv/sysemu/riscv-qmp-cmds.c
diff --git a/target/riscv/time_helper.c b/target/riscv/sysemu/time_helper.c
similarity index 100%
rename from target/riscv/time_helper.c
rename to target/riscv/sysemu/time_helper.c
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index e3ab3df4e5..8967dfaded 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -7,6 +7,8 @@ gen = [
 ]
 
 riscv_ss = ss.source_set()
+riscv_system_ss = ss.source_set()
+
 riscv_ss.add(gen)
 riscv_ss.add(files(
   'cpu.c',
@@ -22,19 +24,12 @@ riscv_ss.add(files(
   'crypto_helper.c',
   'zce_helper.c'
 ))
-riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
 
-riscv_system_ss = ss.source_set()
 riscv_system_ss.add(files(
-  'arch_dump.c',
-  'pmp.c',
   'debug.c',
-  'monitor.c',
-  'machine.c',
-  'pmu.c',
-  'time_helper.c',
-  'riscv-qmp-cmds.c',
 ))
 
+subdir('sysemu')
+
 target_arch += {'riscv': riscv_ss}
 target_softmmu_arch += {'riscv': riscv_system_ss}
diff --git a/target/riscv/sysemu/meson.build b/target/riscv/sysemu/meson.build
new file mode 100644
index 0000000000..64de0256a5
--- /dev/null
+++ b/target/riscv/sysemu/meson.build
@@ -0,0 +1,11 @@
+riscv_system_ss.add(files(
+  'arch_dump.c',
+  'machine.c',
+  'monitor.c',
+  'pmp.c',
+  'pmu.c',
+  'riscv-qmp-cmds.c',
+  'time_helper.c',
+))
+
+riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
-- 
2.38.1



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

* [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (4 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 05/16] target/riscv: Move sysemu-specific files to target/riscv/sysemu/ Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-14  3:17   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/ Philippe Mathieu-Daudé
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

riscv_cpu_do_interrupt() is not reachable on user emulation.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu.h        | 5 +++--
 target/riscv/cpu_helper.c | 7 ++-----
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index dba78db644..0602b948d4 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -416,7 +416,6 @@ extern const char * const riscv_int_regnamesh[];
 extern const char * const riscv_fpr_regnames[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
-void riscv_cpu_do_interrupt(CPUState *cpu);
 int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                                int cpuid, DumpState *s);
 int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
@@ -449,6 +448,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
 #define cpu_mmu_index riscv_cpu_mmu_index
 
 #ifndef CONFIG_USER_ONLY
+void riscv_cpu_do_interrupt(CPUState *cpu);
 void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
                                      vaddr addr, unsigned size,
                                      MMUAccessType access_type,
@@ -472,7 +472,8 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
                                    void *rmw_fn_arg);
 
 RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
-#endif
+#endif /* !CONFIG_USER_ONLY */
+
 void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
 
 void riscv_translate_init(void);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 0adde26321..597c47bc56 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1579,7 +1579,6 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env,
 
     return xinsn;
 }
-#endif /* !CONFIG_USER_ONLY */
 
 /*
  * Handle Traps
@@ -1589,8 +1588,6 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env,
  */
 void riscv_cpu_do_interrupt(CPUState *cs)
 {
-#if !defined(CONFIG_USER_ONLY)
-
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     bool write_gva = false;
@@ -1783,6 +1780,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
     env->two_stage_lookup = false;
     env->two_stage_indirect_lookup = false;
-#endif
-    cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */
 }
+
+#endif /* !CONFIG_USER_ONLY */
-- 
2.38.1



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

* [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (5 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:00   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c Philippe Mathieu-Daudé
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Move TCG-specific files to the a new 'tcg' sub-directory. Add
stubs for riscv_cpu_[get/set]_fflags and riscv_raise_exception().
Adapt meson rules.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/{ => tcg}/XVentanaCondOps.decode |  0
 target/riscv/{ => tcg}/insn16.decode          |  0
 target/riscv/{ => tcg}/insn32.decode          |  0
 target/riscv/{ => tcg}/xthead.decode          |  0
 target/riscv/{ => tcg}/bitmanip_helper.c      |  0
 target/riscv/{ => tcg}/crypto_helper.c        |  0
 target/riscv/{ => tcg}/fpu_helper.c           |  0
 target/riscv/{ => tcg}/m128_helper.c          |  0
 target/riscv/{ => tcg}/op_helper.c            |  0
 target/riscv/tcg/tcg-stub.c                   | 25 +++++++++++++++++++
 target/riscv/{ => tcg}/translate.c            |  0
 target/riscv/{ => tcg}/vector_helper.c        |  0
 target/riscv/{ => tcg}/zce_helper.c           |  0
 target/riscv/meson.build                      | 18 +------------
 target/riscv/tcg/meson.build                  | 19 ++++++++++++++
 15 files changed, 45 insertions(+), 17 deletions(-)
 rename target/riscv/{ => tcg}/XVentanaCondOps.decode (100%)
 rename target/riscv/{ => tcg}/insn16.decode (100%)
 rename target/riscv/{ => tcg}/insn32.decode (100%)
 rename target/riscv/{ => tcg}/xthead.decode (100%)
 rename target/riscv/{ => tcg}/bitmanip_helper.c (100%)
 rename target/riscv/{ => tcg}/crypto_helper.c (100%)
 rename target/riscv/{ => tcg}/fpu_helper.c (100%)
 rename target/riscv/{ => tcg}/m128_helper.c (100%)
 rename target/riscv/{ => tcg}/op_helper.c (100%)
 create mode 100644 target/riscv/tcg/tcg-stub.c
 rename target/riscv/{ => tcg}/translate.c (100%)
 rename target/riscv/{ => tcg}/vector_helper.c (100%)
 rename target/riscv/{ => tcg}/zce_helper.c (100%)
 create mode 100644 target/riscv/tcg/meson.build

diff --git a/target/riscv/XVentanaCondOps.decode b/target/riscv/tcg/XVentanaCondOps.decode
similarity index 100%
rename from target/riscv/XVentanaCondOps.decode
rename to target/riscv/tcg/XVentanaCondOps.decode
diff --git a/target/riscv/insn16.decode b/target/riscv/tcg/insn16.decode
similarity index 100%
rename from target/riscv/insn16.decode
rename to target/riscv/tcg/insn16.decode
diff --git a/target/riscv/insn32.decode b/target/riscv/tcg/insn32.decode
similarity index 100%
rename from target/riscv/insn32.decode
rename to target/riscv/tcg/insn32.decode
diff --git a/target/riscv/xthead.decode b/target/riscv/tcg/xthead.decode
similarity index 100%
rename from target/riscv/xthead.decode
rename to target/riscv/tcg/xthead.decode
diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/tcg/bitmanip_helper.c
similarity index 100%
rename from target/riscv/bitmanip_helper.c
rename to target/riscv/tcg/bitmanip_helper.c
diff --git a/target/riscv/crypto_helper.c b/target/riscv/tcg/crypto_helper.c
similarity index 100%
rename from target/riscv/crypto_helper.c
rename to target/riscv/tcg/crypto_helper.c
diff --git a/target/riscv/fpu_helper.c b/target/riscv/tcg/fpu_helper.c
similarity index 100%
rename from target/riscv/fpu_helper.c
rename to target/riscv/tcg/fpu_helper.c
diff --git a/target/riscv/m128_helper.c b/target/riscv/tcg/m128_helper.c
similarity index 100%
rename from target/riscv/m128_helper.c
rename to target/riscv/tcg/m128_helper.c
diff --git a/target/riscv/op_helper.c b/target/riscv/tcg/op_helper.c
similarity index 100%
rename from target/riscv/op_helper.c
rename to target/riscv/tcg/op_helper.c
diff --git a/target/riscv/tcg/tcg-stub.c b/target/riscv/tcg/tcg-stub.c
new file mode 100644
index 0000000000..dfe42ae2ac
--- /dev/null
+++ b/target/riscv/tcg/tcg-stub.c
@@ -0,0 +1,25 @@
+/*
+ * QEMU RISC-V TCG stubs
+ *
+ * Copyright (c) 2023 Linaro
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
+{
+    g_assert_not_reached();
+}
+
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong)
+{
+    g_assert_not_reached();
+}
+
+G_NORETURN void riscv_raise_exception(CPURISCVState *env,
+                                      uint32_t exception, uintptr_t pc)
+{
+    g_assert_not_reached();
+}
diff --git a/target/riscv/translate.c b/target/riscv/tcg/translate.c
similarity index 100%
rename from target/riscv/translate.c
rename to target/riscv/tcg/translate.c
diff --git a/target/riscv/vector_helper.c b/target/riscv/tcg/vector_helper.c
similarity index 100%
rename from target/riscv/vector_helper.c
rename to target/riscv/tcg/vector_helper.c
diff --git a/target/riscv/zce_helper.c b/target/riscv/tcg/zce_helper.c
similarity index 100%
rename from target/riscv/zce_helper.c
rename to target/riscv/tcg/zce_helper.c
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 8967dfaded..8ef47f43f9 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -1,34 +1,18 @@
-# FIXME extra_args should accept files()
-gen = [
-  decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
-  decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
-  decodetree.process('xthead.decode', extra_args: '--static-decode=decode_xthead'),
-  decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
-]
-
 riscv_ss = ss.source_set()
 riscv_system_ss = ss.source_set()
 
-riscv_ss.add(gen)
 riscv_ss.add(files(
   'cpu.c',
   'cpu_helper.c',
   'csr.c',
-  'fpu_helper.c',
   'gdbstub.c',
-  'op_helper.c',
-  'vector_helper.c',
-  'bitmanip_helper.c',
-  'translate.c',
-  'm128_helper.c',
-  'crypto_helper.c',
-  'zce_helper.c'
 ))
 
 riscv_system_ss.add(files(
   'debug.c',
 ))
 
+subdir('tcg')
 subdir('sysemu')
 
 target_arch += {'riscv': riscv_ss}
diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
new file mode 100644
index 0000000000..65670493b1
--- /dev/null
+++ b/target/riscv/tcg/meson.build
@@ -0,0 +1,19 @@
+# FIXME extra_args should accept files()
+gen = [
+  decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
+  decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
+  decodetree.process('xthead.decode', extra_args: '--static-decode=decode_xthead'),
+  decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
+]
+riscv_ss.add(when: 'CONFIG_TCG', if_true: gen)
+
+riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'fpu_helper.c',
+  'op_helper.c',
+  'vector_helper.c',
+  'bitmanip_helper.c',
+  'translate.c',
+  'm128_helper.c',
+  'crypto_helper.c',
+  'zce_helper.c',
+), if_false: files('tcg-stub.c'))
-- 
2.38.1



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

* [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (6 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/ Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:01   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c Philippe Mathieu-Daudé
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu_helper.c    | 84 -------------------------------
 target/riscv/tcg/cpu.c       | 98 ++++++++++++++++++++++++++++++++++++
 target/riscv/tcg/meson.build |  1 +
 3 files changed, 99 insertions(+), 84 deletions(-)
 create mode 100644 target/riscv/tcg/cpu.c

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 597c47bc56..6f8778c6d3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -64,90 +64,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #endif
 }
 
-void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
-                          uint64_t *cs_base, uint32_t *pflags)
-{
-    CPUState *cs = env_cpu(env);
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    RISCVExtStatus fs, vs;
-    uint32_t flags = 0;
-
-    *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
-    *cs_base = 0;
-
-    if (cpu->cfg.ext_zve32f) {
-        /*
-         * If env->vl equals to VLMAX, we can use generic vector operation
-         * expanders (GVEC) to accerlate the vector operations.
-         * However, as LMUL could be a fractional number. The maximum
-         * vector size can be operated might be less than 8 bytes,
-         * which is not supported by GVEC. So we set vl_eq_vlmax flag to true
-         * only when maxsz >= 8 bytes.
-         */
-        uint32_t vlmax = vext_get_vlmax(cpu, env->vtype);
-        uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW);
-        uint32_t maxsz = vlmax << sew;
-        bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
-                           (maxsz >= 8);
-        flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
-        flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew);
-        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
-                           FIELD_EX64(env->vtype, VTYPE, VLMUL));
-        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
-        flags = FIELD_DP32(flags, TB_FLAGS, VTA,
-                           FIELD_EX64(env->vtype, VTYPE, VTA));
-        flags = FIELD_DP32(flags, TB_FLAGS, VMA,
-                           FIELD_EX64(env->vtype, VTYPE, VMA));
-        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
-    } else {
-        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
-    }
-
-#ifdef CONFIG_USER_ONLY
-    fs = EXT_STATUS_DIRTY;
-    vs = EXT_STATUS_DIRTY;
-#else
-    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
-
-    flags |= cpu_mmu_index(env, 0);
-    fs = get_field(env->mstatus, MSTATUS_FS);
-    vs = get_field(env->mstatus, MSTATUS_VS);
-
-    if (env->virt_enabled) {
-        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
-        /*
-         * Merge DISABLED and !DIRTY states using MIN.
-         * We will set both fields when dirtying.
-         */
-        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
-        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
-    }
-
-    /* With Zfinx, floating point is enabled/disabled by Smstateen. */
-    if (!riscv_has_ext(env, RVF)) {
-        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
-             ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
-    }
-
-    if (cpu->cfg.debug && !icount_enabled()) {
-        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
-    }
-#endif
-
-    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
-    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
-    flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
-    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
-    if (env->cur_pmmask != 0) {
-        flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
-    }
-    if (env->cur_pmbase != 0) {
-        flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1);
-    }
-
-    *pflags = flags;
-}
-
 void riscv_cpu_update_mask(CPURISCVState *env)
 {
     target_ulong mask = 0, base = 0;
diff --git a/target/riscv/tcg/cpu.c b/target/riscv/tcg/cpu.c
new file mode 100644
index 0000000000..2ae6919b80
--- /dev/null
+++ b/target/riscv/tcg/cpu.c
@@ -0,0 +1,98 @@
+/*
+ * RISC-V CPU helpers (TCG specific)
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#ifndef CONFIG_USER_ONLY
+#include "sysemu/cpu-timers.h"
+#endif
+
+void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
+                          uint64_t *cs_base, uint32_t *pflags)
+{
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    RISCVExtStatus fs, vs;
+    uint32_t flags = 0;
+
+    *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
+    *cs_base = 0;
+
+    if (cpu->cfg.ext_zve32f) {
+        /*
+         * If env->vl equals to VLMAX, we can use generic vector operation
+         * expanders (GVEC) to accerlate the vector operations.
+         * However, as LMUL could be a fractional number. The maximum
+         * vector size can be operated might be less than 8 bytes,
+         * which is not supported by GVEC. So we set vl_eq_vlmax flag to true
+         * only when maxsz >= 8 bytes.
+         */
+        uint32_t vlmax = vext_get_vlmax(cpu, env->vtype);
+        uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW);
+        uint32_t maxsz = vlmax << sew;
+        bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
+                           (maxsz >= 8);
+        flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
+        flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew);
+        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
+                           FIELD_EX64(env->vtype, VTYPE, VLMUL));
+        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
+        flags = FIELD_DP32(flags, TB_FLAGS, VTA,
+                           FIELD_EX64(env->vtype, VTYPE, VTA));
+        flags = FIELD_DP32(flags, TB_FLAGS, VMA,
+                           FIELD_EX64(env->vtype, VTYPE, VMA));
+        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
+    } else {
+        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
+    }
+
+#ifdef CONFIG_USER_ONLY
+    fs = EXT_STATUS_DIRTY;
+    vs = EXT_STATUS_DIRTY;
+#else
+    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
+
+    flags |= cpu_mmu_index(env, 0);
+    fs = get_field(env->mstatus, MSTATUS_FS);
+    vs = get_field(env->mstatus, MSTATUS_VS);
+
+    if (env->virt_enabled) {
+        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
+        /*
+         * Merge DISABLED and !DIRTY states using MIN.
+         * We will set both fields when dirtying.
+         */
+        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
+        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
+    }
+
+    /* With Zfinx, floating point is enabled/disabled by Smstateen. */
+    if (!riscv_has_ext(env, RVF)) {
+        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
+             ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
+    }
+
+    if (cpu->cfg.debug && !icount_enabled()) {
+        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
+    }
+#endif
+
+    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
+    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
+    flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
+    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
+    if (env->cur_pmmask != 0) {
+        flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
+    }
+    if (env->cur_pmbase != 0) {
+        flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1);
+    }
+
+    *pflags = flags;
+}
diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
index 65670493b1..a615aafd9a 100644
--- a/target/riscv/tcg/meson.build
+++ b/target/riscv/tcg/meson.build
@@ -8,6 +8,7 @@ gen = [
 riscv_ss.add(when: 'CONFIG_TCG', if_true: gen)
 
 riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'cpu.c',
   'fpu_helper.c',
   'op_helper.c',
   'vector_helper.c',
-- 
2.38.1



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

* [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (7 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:01   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 10/16] target/riscv: Extract TCG-specific code " Philippe Mathieu-Daudé
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

We want to extract TCG-specific code from debug.c, but some
functions call get_trigger_type() / do_trigger_action().
Expose these prototypes in "debug.h".

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/debug.h | 4 ++++
 target/riscv/debug.c | 5 ++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index c471748d5a..65cd45b8f3 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -147,4 +147,8 @@ void riscv_trigger_init(CPURISCVState *env);
 
 bool riscv_itrigger_enabled(CPURISCVState *env);
 void riscv_itrigger_update_priv(CPURISCVState *env);
+
+target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index);
+void do_trigger_action(CPURISCVState *env, target_ulong trigger_index);
+
 #endif /* RISCV_DEBUG_H */
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 75ee1c4971..5676f2c57e 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -88,8 +88,7 @@ static inline target_ulong extract_trigger_type(CPURISCVState *env,
     }
 }
 
-static inline target_ulong get_trigger_type(CPURISCVState *env,
-                                            target_ulong trigger_index)
+target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index)
 {
     return extract_trigger_type(env, env->tdata1[trigger_index]);
 }
@@ -217,7 +216,7 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask,
     }
 }
 
-static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
+void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
 {
     trigger_action_t action = get_trigger_action(env, trigger_index);
 
-- 
2.38.1



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

* [PATCH v3 10/16] target/riscv: Extract TCG-specific code from debug.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (8 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:03   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/ Philippe Mathieu-Daudé
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Extract TCG-specific code from debug.c to tcg/sysemu/debug.c,
restrict the prototypes to TCG, adapt meson rules.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/debug.h                |   2 +
 target/riscv/debug.c                | 148 -------------------------
 target/riscv/tcg/sysemu/debug.c     | 165 ++++++++++++++++++++++++++++
 target/riscv/tcg/meson.build        |   2 +
 target/riscv/tcg/sysemu/meson.build |   3 +
 5 files changed, 172 insertions(+), 148 deletions(-)
 create mode 100644 target/riscv/tcg/sysemu/debug.c
 create mode 100644 target/riscv/tcg/sysemu/meson.build

diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 65cd45b8f3..0b3bdd5be1 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -139,9 +139,11 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val);
 
 target_ulong tinfo_csr_read(CPURISCVState *env);
 
+#ifdef CONFIG_TCG
 void riscv_cpu_debug_excp_handler(CPUState *cs);
 bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
 bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
+#endif
 
 void riscv_trigger_init(CPURISCVState *env);
 
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 5676f2c57e..45a2605d8a 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -754,154 +754,6 @@ target_ulong tinfo_csr_read(CPURISCVState *env)
            BIT(TRIGGER_TYPE_AD_MATCH6);
 }
 
-void riscv_cpu_debug_excp_handler(CPUState *cs)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-
-    if (cs->watchpoint_hit) {
-        if (cs->watchpoint_hit->flags & BP_CPU) {
-            do_trigger_action(env, DBG_ACTION_BP);
-        }
-    } else {
-        if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
-            do_trigger_action(env, DBG_ACTION_BP);
-        }
-    }
-}
-
-bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    CPUBreakpoint *bp;
-    target_ulong ctrl;
-    target_ulong pc;
-    int trigger_type;
-    int i;
-
-    QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-        for (i = 0; i < RV_MAX_TRIGGERS; i++) {
-            trigger_type = get_trigger_type(env, i);
-
-            switch (trigger_type) {
-            case TRIGGER_TYPE_AD_MATCH:
-                /* type 2 trigger cannot be fired in VU/VS mode */
-                if (env->virt_enabled) {
-                    return false;
-                }
-
-                ctrl = env->tdata1[i];
-                pc = env->tdata2[i];
-
-                if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
-                    /* check U/S/M bit against current privilege level */
-                    if ((ctrl >> 3) & BIT(env->priv)) {
-                        return true;
-                    }
-                }
-                break;
-            case TRIGGER_TYPE_AD_MATCH6:
-                ctrl = env->tdata1[i];
-                pc = env->tdata2[i];
-
-                if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) {
-                    if (env->virt_enabled) {
-                        /* check VU/VS bit against current privilege level */
-                        if ((ctrl >> 23) & BIT(env->priv)) {
-                            return true;
-                        }
-                    } else {
-                        /* check U/S/M bit against current privilege level */
-                        if ((ctrl >> 3) & BIT(env->priv)) {
-                            return true;
-                        }
-                    }
-                }
-                break;
-            default:
-                /* other trigger types are not supported or irrelevant */
-                break;
-            }
-        }
-    }
-
-    return false;
-}
-
-bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    target_ulong ctrl;
-    target_ulong addr;
-    int trigger_type;
-    int flags;
-    int i;
-
-    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
-        trigger_type = get_trigger_type(env, i);
-
-        switch (trigger_type) {
-        case TRIGGER_TYPE_AD_MATCH:
-            /* type 2 trigger cannot be fired in VU/VS mode */
-            if (env->virt_enabled) {
-                return false;
-            }
-
-            ctrl = env->tdata1[i];
-            addr = env->tdata2[i];
-            flags = 0;
-
-            if (ctrl & TYPE2_LOAD) {
-                flags |= BP_MEM_READ;
-            }
-            if (ctrl & TYPE2_STORE) {
-                flags |= BP_MEM_WRITE;
-            }
-
-            if ((wp->flags & flags) && (wp->vaddr == addr)) {
-                /* check U/S/M bit against current privilege level */
-                if ((ctrl >> 3) & BIT(env->priv)) {
-                    return true;
-                }
-            }
-            break;
-        case TRIGGER_TYPE_AD_MATCH6:
-            ctrl = env->tdata1[i];
-            addr = env->tdata2[i];
-            flags = 0;
-
-            if (ctrl & TYPE6_LOAD) {
-                flags |= BP_MEM_READ;
-            }
-            if (ctrl & TYPE6_STORE) {
-                flags |= BP_MEM_WRITE;
-            }
-
-            if ((wp->flags & flags) && (wp->vaddr == addr)) {
-                if (env->virt_enabled) {
-                    /* check VU/VS bit against current privilege level */
-                    if ((ctrl >> 23) & BIT(env->priv)) {
-                        return true;
-                    }
-                } else {
-                    /* check U/S/M bit against current privilege level */
-                    if ((ctrl >> 3) & BIT(env->priv)) {
-                        return true;
-                    }
-                }
-            }
-            break;
-        default:
-            /* other trigger types are not supported */
-            break;
-        }
-    }
-
-    return false;
-}
-
 void riscv_trigger_init(CPURISCVState *env)
 {
     target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
diff --git a/target/riscv/tcg/sysemu/debug.c b/target/riscv/tcg/sysemu/debug.c
new file mode 100644
index 0000000000..cdd6744b3a
--- /dev/null
+++ b/target/riscv/tcg/sysemu/debug.c
@@ -0,0 +1,165 @@
+/*
+ * QEMU RISC-V Native Debug Support (TCG specific)
+ *
+ * Copyright (c) 2022 Wind River Systems, Inc.
+ *
+ * Author:
+ *   Bin Meng <bin.meng@windriver.com>
+ *
+ * This provides the native debug support via the Trigger Module, as defined
+ * in the RISC-V Debug Specification:
+ * https://github.com/riscv/riscv-debug-spec/raw/master/riscv-debug-stable.pdf
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+
+void riscv_cpu_debug_excp_handler(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+
+    if (cs->watchpoint_hit) {
+        if (cs->watchpoint_hit->flags & BP_CPU) {
+            do_trigger_action(env, DBG_ACTION_BP);
+        }
+    } else {
+        if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
+            do_trigger_action(env, DBG_ACTION_BP);
+        }
+    }
+}
+
+bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    CPUBreakpoint *bp;
+    target_ulong ctrl;
+    target_ulong pc;
+    int trigger_type;
+    int i;
+
+    QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
+        for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+            trigger_type = get_trigger_type(env, i);
+
+            switch (trigger_type) {
+            case TRIGGER_TYPE_AD_MATCH:
+                /* type 2 trigger cannot be fired in VU/VS mode */
+                if (env->virt_enabled) {
+                    return false;
+                }
+
+                ctrl = env->tdata1[i];
+                pc = env->tdata2[i];
+
+                if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
+                    /* check U/S/M bit against current privilege level */
+                    if ((ctrl >> 3) & BIT(env->priv)) {
+                        return true;
+                    }
+                }
+                break;
+            case TRIGGER_TYPE_AD_MATCH6:
+                ctrl = env->tdata1[i];
+                pc = env->tdata2[i];
+
+                if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) {
+                    if (env->virt_enabled) {
+                        /* check VU/VS bit against current privilege level */
+                        if ((ctrl >> 23) & BIT(env->priv)) {
+                            return true;
+                        }
+                    } else {
+                        /* check U/S/M bit against current privilege level */
+                        if ((ctrl >> 3) & BIT(env->priv)) {
+                            return true;
+                        }
+                    }
+                }
+                break;
+            default:
+                /* other trigger types are not supported or irrelevant */
+                break;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    target_ulong ctrl;
+    target_ulong addr;
+    int trigger_type;
+    int flags;
+    int i;
+
+    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+        trigger_type = get_trigger_type(env, i);
+
+        switch (trigger_type) {
+        case TRIGGER_TYPE_AD_MATCH:
+            /* type 2 trigger cannot be fired in VU/VS mode */
+            if (env->virt_enabled) {
+                return false;
+            }
+
+            ctrl = env->tdata1[i];
+            addr = env->tdata2[i];
+            flags = 0;
+
+            if (ctrl & TYPE2_LOAD) {
+                flags |= BP_MEM_READ;
+            }
+            if (ctrl & TYPE2_STORE) {
+                flags |= BP_MEM_WRITE;
+            }
+
+            if ((wp->flags & flags) && (wp->vaddr == addr)) {
+                /* check U/S/M bit against current privilege level */
+                if ((ctrl >> 3) & BIT(env->priv)) {
+                    return true;
+                }
+            }
+            break;
+        case TRIGGER_TYPE_AD_MATCH6:
+            ctrl = env->tdata1[i];
+            addr = env->tdata2[i];
+            flags = 0;
+
+            if (ctrl & TYPE6_LOAD) {
+                flags |= BP_MEM_READ;
+            }
+            if (ctrl & TYPE6_STORE) {
+                flags |= BP_MEM_WRITE;
+            }
+
+            if ((wp->flags & flags) && (wp->vaddr == addr)) {
+                if (env->virt_enabled) {
+                    /* check VU/VS bit against current privilege level */
+                    if ((ctrl >> 23) & BIT(env->priv)) {
+                        return true;
+                    }
+                } else {
+                    /* check U/S/M bit against current privilege level */
+                    if ((ctrl >> 3) & BIT(env->priv)) {
+                        return true;
+                    }
+                }
+            }
+            break;
+        default:
+            /* other trigger types are not supported */
+            break;
+        }
+    }
+
+    return false;
+}
diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
index a615aafd9a..933d340799 100644
--- a/target/riscv/tcg/meson.build
+++ b/target/riscv/tcg/meson.build
@@ -18,3 +18,5 @@ riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
   'crypto_helper.c',
   'zce_helper.c',
 ), if_false: files('tcg-stub.c'))
+
+subdir('sysemu')
diff --git a/target/riscv/tcg/sysemu/meson.build b/target/riscv/tcg/sysemu/meson.build
new file mode 100644
index 0000000000..e8e61e5784
--- /dev/null
+++ b/target/riscv/tcg/sysemu/meson.build
@@ -0,0 +1,3 @@
+riscv_system_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'debug.c',
+))
-- 
2.38.1



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

* [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (9 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 10/16] target/riscv: Extract TCG-specific code " Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:04   ` Alistair Francis
  2023-07-11 12:14 ` [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c Philippe Mathieu-Daudé
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu.h                | 2 +-
 target/riscv/{ => sysemu}/debug.h | 0
 target/riscv/cpu_helper.c         | 2 +-
 target/riscv/{ => sysemu}/debug.c | 0
 target/riscv/meson.build          | 4 ----
 target/riscv/sysemu/meson.build   | 1 +
 6 files changed, 3 insertions(+), 6 deletions(-)
 rename target/riscv/{ => sysemu}/debug.h (100%)
 rename target/riscv/{ => sysemu}/debug.c (100%)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0602b948d4..8d8e30d6c1 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -94,7 +94,7 @@ typedef enum {
 
 #if !defined(CONFIG_USER_ONLY)
 #include "sysemu/pmp.h"
-#include "debug.h"
+#include "sysemu/debug.h"
 #endif
 
 #define RV_VLEN_MAX 1024
diff --git a/target/riscv/debug.h b/target/riscv/sysemu/debug.h
similarity index 100%
rename from target/riscv/debug.h
rename to target/riscv/sysemu/debug.h
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6f8778c6d3..6c773000a5 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -32,7 +32,7 @@
 #include "sysemu/cpu-timers.h"
 #endif
 #include "cpu_bits.h"
-#include "debug.h"
+#include "sysemu/debug.h"
 #include "tcg/oversized-guest.h"
 
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
diff --git a/target/riscv/debug.c b/target/riscv/sysemu/debug.c
similarity index 100%
rename from target/riscv/debug.c
rename to target/riscv/sysemu/debug.c
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 8ef47f43f9..49cdcde679 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -8,10 +8,6 @@ riscv_ss.add(files(
   'gdbstub.c',
 ))
 
-riscv_system_ss.add(files(
-  'debug.c',
-))
-
 subdir('tcg')
 subdir('sysemu')
 
diff --git a/target/riscv/sysemu/meson.build b/target/riscv/sysemu/meson.build
index 64de0256a5..e902ba2dad 100644
--- a/target/riscv/sysemu/meson.build
+++ b/target/riscv/sysemu/meson.build
@@ -1,5 +1,6 @@
 riscv_system_ss.add(files(
   'arch_dump.c',
+  'debug.c',
   'machine.c',
   'monitor.c',
   'pmp.c',
-- 
2.38.1



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

* [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (10 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/ Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-19  1:04   ` Alistair Francis
  2023-07-11 12:14 ` [RFC PATCH v3 13/16] target/riscv: Move TCG/sysemu-specific code to tcg/sysemu/cpu_helper.c Philippe Mathieu-Daudé
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

We want to extract TCG/sysemu-specific code from cpu_helper.c,
but some functions call riscv_cpu_pending_to_irq(). Expose the
prototype in "internals.h".

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/internals.h  | 4 ++++
 target/riscv/cpu_helper.c | 6 +++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index b5f823c7ec..b6881b4815 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -72,6 +72,10 @@ target_ulong fclass_d(uint64_t frs1);
 
 #ifndef CONFIG_USER_ONLY
 extern const VMStateDescription vmstate_riscv_cpu;
+
+int riscv_cpu_pending_to_irq(CPURISCVState *env,
+                             int extirq, unsigned int extirq_def_prio,
+                             uint64_t pending, uint8_t *iprio);
 #endif
 
 enum {
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6c773000a5..e73cf56e5c 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -256,9 +256,9 @@ uint8_t riscv_cpu_default_priority(int irq)
     return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
 };
 
-static int riscv_cpu_pending_to_irq(CPURISCVState *env,
-                                    int extirq, unsigned int extirq_def_prio,
-                                    uint64_t pending, uint8_t *iprio)
+int riscv_cpu_pending_to_irq(CPURISCVState *env,
+                             int extirq, unsigned int extirq_def_prio,
+                             uint64_t pending, uint8_t *iprio)
 {
     int irq, best_irq = RISCV_EXCP_NONE;
     unsigned int prio, best_prio = UINT_MAX;
-- 
2.38.1



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

* [RFC PATCH v3 13/16] target/riscv: Move TCG/sysemu-specific code to tcg/sysemu/cpu_helper.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (11 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 14/16] target/riscv: Move sysemu-specific code to sysemu/cpu_helper.c Philippe Mathieu-Daudé
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Move TCG/sysemu-specific code and restrict the corresponding
prototypes to TCG, adapting meson rules.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
RFC due to riscv_cpu_get_phys_page_debug()
---
 target/riscv/cpu.h                   |  15 +-
 target/riscv/cpu_helper.c            | 745 --------------------------
 target/riscv/tcg/sysemu/cpu_helper.c | 765 +++++++++++++++++++++++++++
 target/riscv/tcg/tcg-stub.c          |   6 +
 target/riscv/tcg/sysemu/meson.build  |   1 +
 5 files changed, 781 insertions(+), 751 deletions(-)
 create mode 100644 target/riscv/tcg/sysemu/cpu_helper.c

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8d8e30d6c1..6d78e59214 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -434,12 +434,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
 bool riscv_cpu_vector_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
-G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
-                                               MMUAccessType access_type,
-                                               int mmu_idx, uintptr_t retaddr);
-bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-                        MMUAccessType access_type, int mmu_idx,
-                        bool probe, uintptr_t retaddr);
 char *riscv_isa_string(RISCVCPU *cpu);
 void riscv_cpu_list(void);
 void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
@@ -449,11 +443,20 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
 
 #ifndef CONFIG_USER_ONLY
 void riscv_cpu_do_interrupt(CPUState *cpu);
+#ifdef CONFIG_TCG
+bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+                        MMUAccessType access_type, int mmu_idx,
+                        bool probe, uintptr_t retaddr);
 void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
                                      vaddr addr, unsigned size,
                                      MMUAccessType access_type,
                                      int mmu_idx, MemTxAttrs attrs,
                                      MemTxResult response, uintptr_t retaddr);
+G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+                                               MMUAccessType access_type,
+                                               int mmu_idx, uintptr_t retaddr);
+#endif /* CONFIG_TCG */
+
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
 void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e73cf56e5c..f1d0cd1e64 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -331,69 +331,6 @@ int riscv_cpu_vsirq_pending(CPURISCVState *env)
                                     irqs >> 1, env->hviprio);
 }
 
-static int riscv_cpu_local_irq_pending(CPURISCVState *env)
-{
-    int virq;
-    uint64_t irqs, pending, mie, hsie, vsie;
-
-    /* Determine interrupt enable state of all privilege modes */
-    if (env->virt_enabled) {
-        mie = 1;
-        hsie = 1;
-        vsie = (env->priv < PRV_S) ||
-               (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
-    } else {
-        mie = (env->priv < PRV_M) ||
-              (env->priv == PRV_M && get_field(env->mstatus, MSTATUS_MIE));
-        hsie = (env->priv < PRV_S) ||
-               (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
-        vsie = 0;
-    }
-
-    /* Determine all pending interrupts */
-    pending = riscv_cpu_all_pending(env);
-
-    /* Check M-mode interrupts */
-    irqs = pending & ~env->mideleg & -mie;
-    if (irqs) {
-        return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
-                                        irqs, env->miprio);
-    }
-
-    /* Check HS-mode interrupts */
-    irqs = pending & env->mideleg & ~env->hideleg & -hsie;
-    if (irqs) {
-        return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
-                                        irqs, env->siprio);
-    }
-
-    /* Check VS-mode interrupts */
-    irqs = pending & env->mideleg & env->hideleg & -vsie;
-    if (irqs) {
-        virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
-                                        irqs >> 1, env->hviprio);
-        return (virq <= 0) ? virq : virq + 1;
-    }
-
-    /* Indicate no pending interrupt */
-    return RISCV_EXCP_NONE;
-}
-
-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_local_irq_pending(env);
-        if (interruptno >= 0) {
-            cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
-            riscv_cpu_do_interrupt(cs);
-            return true;
-        }
-    }
-    return false;
-}
-
 /* Return true is floating point support is currently enabled */
 bool riscv_cpu_fp_enabled(CPURISCVState *env)
 {
@@ -609,688 +546,6 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
     env->load_res = -1;
 }
 
-/*
- * get_physical_address_pmp - check PMP permission for this physical address
- *
- * Match the PMP region and check permission for this physical address and it's
- * TLB page. Returns 0 if the permission checking was successful
- *
- * @env: CPURISCVState
- * @prot: The returned protection attributes
- * @addr: The physical address to be checked permission
- * @access_type: The type of MMU access
- * @mode: Indicates current privilege level.
- */
-static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
-                                    int size, MMUAccessType access_type,
-                                    int mode)
-{
-    pmp_priv_t pmp_priv;
-    bool pmp_has_privs;
-
-    if (!riscv_cpu_cfg(env)->pmp) {
-        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-        return TRANSLATE_SUCCESS;
-    }
-
-    pmp_has_privs = pmp_hart_has_privs(env, addr, size, 1 << access_type,
-                                       &pmp_priv, mode);
-    if (!pmp_has_privs) {
-        *prot = 0;
-        return TRANSLATE_PMP_FAIL;
-    }
-
-    *prot = pmp_priv_to_page_prot(pmp_priv);
-
-    return TRANSLATE_SUCCESS;
-}
-
-/*
- * get_physical_address - get the physical address for this virtual address
- *
- * Do a page table walk to obtain the physical address corresponding to a
- * virtual address. Returns 0 if the translation was successful
- *
- * Adapted from Spike's mmu_t::translate and mmu_t::walk
- *
- * @env: CPURISCVState
- * @physical: This will be set to the calculated physical address
- * @prot: The returned protection attributes
- * @addr: The virtual address or guest physical address to be translated
- * @fault_pte_addr: If not NULL, this will be set to fault pte address
- *                  when a error occurs on pte address translation.
- *                  This will already be shifted to match htval.
- * @access_type: The type of MMU access
- * @mmu_idx: Indicates current privilege level
- * @first_stage: Are we in first stage translation?
- *               Second stage is used for hypervisor guest translation
- * @two_stage: Are we going to perform two stage translation
- * @is_debug: Is this access from a debugger or the monitor?
- */
-static int get_physical_address(CPURISCVState *env, hwaddr *physical,
-                                int *ret_prot, vaddr addr,
-                                target_ulong *fault_pte_addr,
-                                int access_type, int mmu_idx,
-                                bool first_stage, bool two_stage,
-                                bool is_debug)
-{
-    /*
-     * NOTE: the env->pc value visible here will not be
-     * correct, but the value visible to the exception handler
-     * (riscv_cpu_do_interrupt) is correct
-     */
-    MemTxResult res;
-    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
-    int mode = mmuidx_priv(mmu_idx);
-    bool use_background = false;
-    hwaddr ppn;
-    int napot_bits = 0;
-    target_ulong napot_mask;
-
-    /*
-     * Check if we should use the background registers for the two
-     * stage translation. We don't need to check if we actually need
-     * two stage translation as that happened before this function
-     * was called. Background registers will be used if the guest has
-     * forced a two stage translation to be on (in HS or M mode).
-     */
-    if (!env->virt_enabled && two_stage) {
-        use_background = true;
-    }
-
-    if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
-        *physical = addr;
-        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-        return TRANSLATE_SUCCESS;
-    }
-
-    *ret_prot = 0;
-
-    hwaddr base;
-    int levels, ptidxbits, ptesize, vm, widened;
-
-    if (first_stage == true) {
-        if (use_background) {
-            if (riscv_cpu_mxl(env) == MXL_RV32) {
-                base = (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSHIFT;
-                vm = get_field(env->vsatp, SATP32_MODE);
-            } else {
-                base = (hwaddr)get_field(env->vsatp, SATP64_PPN) << PGSHIFT;
-                vm = get_field(env->vsatp, SATP64_MODE);
-            }
-        } else {
-            if (riscv_cpu_mxl(env) == MXL_RV32) {
-                base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
-                vm = get_field(env->satp, SATP32_MODE);
-            } else {
-                base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
-                vm = get_field(env->satp, SATP64_MODE);
-            }
-        }
-        widened = 0;
-    } else {
-        if (riscv_cpu_mxl(env) == MXL_RV32) {
-            base = (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT;
-            vm = get_field(env->hgatp, SATP32_MODE);
-        } else {
-            base = (hwaddr)get_field(env->hgatp, SATP64_PPN) << PGSHIFT;
-            vm = get_field(env->hgatp, SATP64_MODE);
-        }
-        widened = 2;
-    }
-
-    switch (vm) {
-    case VM_1_10_SV32:
-      levels = 2; ptidxbits = 10; ptesize = 4; break;
-    case VM_1_10_SV39:
-      levels = 3; ptidxbits = 9; ptesize = 8; break;
-    case VM_1_10_SV48:
-      levels = 4; ptidxbits = 9; ptesize = 8; break;
-    case VM_1_10_SV57:
-      levels = 5; ptidxbits = 9; ptesize = 8; break;
-    case VM_1_10_MBARE:
-        *physical = addr;
-        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-        return TRANSLATE_SUCCESS;
-    default:
-      g_assert_not_reached();
-    }
-
-    CPUState *cs = env_cpu(env);
-    int va_bits = PGSHIFT + levels * ptidxbits + widened;
-
-    if (first_stage == true) {
-        target_ulong mask, masked_msbs;
-
-        if (TARGET_LONG_BITS > (va_bits - 1)) {
-            mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
-        } else {
-            mask = 0;
-        }
-        masked_msbs = (addr >> (va_bits - 1)) & mask;
-
-        if (masked_msbs != 0 && masked_msbs != mask) {
-            return TRANSLATE_FAIL;
-        }
-    } else {
-        if (vm != VM_1_10_SV32 && addr >> va_bits != 0) {
-            return TRANSLATE_FAIL;
-        }
-    }
-
-    bool pbmte = env->menvcfg & MENVCFG_PBMTE;
-    bool hade = env->menvcfg & MENVCFG_HADE;
-
-    if (first_stage && two_stage && env->virt_enabled) {
-        pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
-        hade = hade && (env->henvcfg & HENVCFG_HADE);
-    }
-
-    int ptshift = (levels - 1) * ptidxbits;
-    target_ulong pte;
-    hwaddr pte_addr;
-    int i;
-
-#if !TCG_OVERSIZED_GUEST
-restart:
-#endif
-    for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
-        target_ulong idx;
-        if (i == 0) {
-            idx = (addr >> (PGSHIFT + ptshift)) &
-                           ((1 << (ptidxbits + widened)) - 1);
-        } else {
-            idx = (addr >> (PGSHIFT + ptshift)) &
-                           ((1 << ptidxbits) - 1);
-        }
-
-        /* check that physical address of PTE is legal */
-
-        if (two_stage && first_stage) {
-            int vbase_prot;
-            hwaddr vbase;
-
-            /* Do the second stage translation on the base PTE address. */
-            int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
-                                                 base, NULL, MMU_DATA_LOAD,
-                                                 MMUIdx_U, false, true,
-                                                 is_debug);
-
-            if (vbase_ret != TRANSLATE_SUCCESS) {
-                if (fault_pte_addr) {
-                    *fault_pte_addr = (base + idx * ptesize) >> 2;
-                }
-                return TRANSLATE_G_STAGE_FAIL;
-            }
-
-            pte_addr = vbase + idx * ptesize;
-        } else {
-            pte_addr = base + idx * ptesize;
-        }
-
-        int pmp_prot;
-        int pmp_ret = get_physical_address_pmp(env, &pmp_prot, pte_addr,
-                                               sizeof(target_ulong),
-                                               MMU_DATA_LOAD, PRV_S);
-        if (pmp_ret != TRANSLATE_SUCCESS) {
-            return TRANSLATE_PMP_FAIL;
-        }
-
-        if (riscv_cpu_mxl(env) == MXL_RV32) {
-            pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
-        } else {
-            pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
-        }
-
-        if (res != MEMTX_OK) {
-            return TRANSLATE_FAIL;
-        }
-
-        if (riscv_cpu_sxl(env) == MXL_RV32) {
-            ppn = pte >> PTE_PPN_SHIFT;
-        } else {
-            if (pte & PTE_RESERVED) {
-                return TRANSLATE_FAIL;
-            }
-
-            if (!pbmte && (pte & PTE_PBMT)) {
-                return TRANSLATE_FAIL;
-            }
-
-            if (!riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
-                return TRANSLATE_FAIL;
-            }
-
-            ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
-        }
-
-        if (!(pte & PTE_V)) {
-            /* Invalid PTE */
-            return TRANSLATE_FAIL;
-        }
-        if (pte & (PTE_R | PTE_W | PTE_X)) {
-            goto leaf;
-        }
-
-        /* Inner PTE, continue walking */
-        if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
-            return TRANSLATE_FAIL;
-        }
-        base = ppn << PGSHIFT;
-    }
-
-    /* No leaf pte at any translation level. */
-    return TRANSLATE_FAIL;
-
- leaf:
-    if (ppn & ((1ULL << ptshift) - 1)) {
-        /* Misaligned PPN */
-        return TRANSLATE_FAIL;
-    }
-    if (!pbmte && (pte & PTE_PBMT)) {
-        /* Reserved without Svpbmt. */
-        return TRANSLATE_FAIL;
-    }
-
-    /* Check for reserved combinations of RWX flags. */
-    switch (pte & (PTE_R | PTE_W | PTE_X)) {
-    case PTE_W:
-    case PTE_W | PTE_X:
-        return TRANSLATE_FAIL;
-    }
-
-    int prot = 0;
-    if (pte & PTE_R) {
-        prot |= PAGE_READ;
-    }
-    if (pte & PTE_W) {
-        prot |= PAGE_WRITE;
-    }
-    if (pte & PTE_X) {
-        bool mxr;
-
-        if (first_stage == true) {
-            mxr = get_field(env->mstatus, MSTATUS_MXR);
-        } else {
-            mxr = get_field(env->vsstatus, MSTATUS_MXR);
-        }
-        if (mxr) {
-            prot |= PAGE_READ;
-        }
-        prot |= PAGE_EXEC;
-    }
-
-    if (pte & PTE_U) {
-        if (mode != PRV_U) {
-            if (!mmuidx_sum(mmu_idx)) {
-                return TRANSLATE_FAIL;
-            }
-            /* SUM allows only read+write, not execute. */
-            prot &= PAGE_READ | PAGE_WRITE;
-        }
-    } else if (mode != PRV_S) {
-        /* Supervisor PTE flags when not S mode */
-        return TRANSLATE_FAIL;
-    }
-
-    if (!((prot >> access_type) & 1)) {
-        /* Access check failed */
-        return TRANSLATE_FAIL;
-    }
-
-    /* If necessary, set accessed and dirty bits. */
-    target_ulong updated_pte = pte | PTE_A |
-                (access_type == MMU_DATA_STORE ? PTE_D : 0);
-
-    /* Page table updates need to be atomic with MTTCG enabled */
-    if (updated_pte != pte && !is_debug) {
-        if (!hade) {
-            return TRANSLATE_FAIL;
-        }
-
-        /*
-         * - if accessed or dirty bits need updating, and the PTE is
-         *   in RAM, then we do so atomically with a compare and swap.
-         * - 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, MEMTXATTRS_UNSPECIFIED);
-        if (memory_region_is_ram(mr)) {
-            target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
-#if TCG_OVERSIZED_GUEST
-            /*
-             * MTTCG is not enabled on oversized TCG guests so
-             * page table updates do not need to be atomic
-             */
-            *pte_pa = pte = updated_pte;
-#else
-            target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
-            if (old_pte != pte) {
-                goto restart;
-            }
-            pte = updated_pte;
-#endif
-        } else {
-            /*
-             * Misconfigured PTE in ROM (AD bits are not preset) or
-             * PTE is in IO space and can't be updated atomically.
-             */
-            return TRANSLATE_FAIL;
-        }
-    }
-
-    /* For superpage mappings, make a fake leaf PTE for the TLB's benefit. */
-    target_ulong vpn = addr >> PGSHIFT;
-
-    if (riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
-        napot_bits = ctzl(ppn) + 1;
-        if ((i != (levels - 1)) || (napot_bits != 4)) {
-            return TRANSLATE_FAIL;
-        }
-    }
-
-    napot_mask = (1 << napot_bits) - 1;
-    *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
-                  (vpn & (((target_ulong)1 << ptshift) - 1))
-                 ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
-
-    /*
-     * Remove write permission unless this is a store, or the page is
-     * already dirty, so that we TLB miss on later writes to update
-     * the dirty bit.
-     */
-    if (access_type != MMU_DATA_STORE && !(pte & PTE_D)) {
-        prot &= ~PAGE_WRITE;
-    }
-    *ret_prot = prot;
-
-    return TRANSLATE_SUCCESS;
-}
-
-static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
-                                MMUAccessType access_type, bool pmp_violation,
-                                bool first_stage, bool two_stage,
-                                bool two_stage_indirect)
-{
-    CPUState *cs = env_cpu(env);
-    int page_fault_exceptions, vm;
-    uint64_t stap_mode;
-
-    if (riscv_cpu_mxl(env) == MXL_RV32) {
-        stap_mode = SATP32_MODE;
-    } else {
-        stap_mode = SATP64_MODE;
-    }
-
-    if (first_stage) {
-        vm = get_field(env->satp, stap_mode);
-    } else {
-        vm = get_field(env->hgatp, stap_mode);
-    }
-
-    page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
-
-    switch (access_type) {
-    case MMU_INST_FETCH:
-        if (env->virt_enabled && !first_stage) {
-            cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
-        } else {
-            cs->exception_index = page_fault_exceptions ?
-                RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
-        }
-        break;
-    case MMU_DATA_LOAD:
-        if (two_stage && !first_stage) {
-            cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
-        } else {
-            cs->exception_index = page_fault_exceptions ?
-                RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
-        }
-        break;
-    case MMU_DATA_STORE:
-        if (two_stage && !first_stage) {
-            cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
-        } else {
-            cs->exception_index = page_fault_exceptions ?
-                RISCV_EXCP_STORE_PAGE_FAULT :
-                RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
-        }
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    env->badaddr = address;
-    env->two_stage_lookup = two_stage;
-    env->two_stage_indirect_lookup = two_stage_indirect;
-}
-
-hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    hwaddr phys_addr;
-    int prot;
-    int mmu_idx = cpu_mmu_index(&cpu->env, false);
-
-    if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
-                             true, env->virt_enabled, true)) {
-        return -1;
-    }
-
-    if (env->virt_enabled) {
-        if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL,
-                                 0, mmu_idx, false, true, true)) {
-            return -1;
-        }
-    }
-
-    return phys_addr & TARGET_PAGE_MASK;
-}
-
-void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
-                                     vaddr addr, unsigned size,
-                                     MMUAccessType access_type,
-                                     int mmu_idx, MemTxAttrs attrs,
-                                     MemTxResult response, uintptr_t retaddr)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-
-    if (access_type == MMU_DATA_STORE) {
-        cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
-    } else if (access_type == MMU_DATA_LOAD) {
-        cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
-    } else {
-        cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
-    }
-
-    env->badaddr = addr;
-    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
-    env->two_stage_indirect_lookup = false;
-    cpu_loop_exit_restore(cs, retaddr);
-}
-
-void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
-                                   MMUAccessType access_type, int mmu_idx,
-                                   uintptr_t retaddr)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    switch (access_type) {
-    case MMU_INST_FETCH:
-        cs->exception_index = RISCV_EXCP_INST_ADDR_MIS;
-        break;
-    case MMU_DATA_LOAD:
-        cs->exception_index = RISCV_EXCP_LOAD_ADDR_MIS;
-        break;
-    case MMU_DATA_STORE:
-        cs->exception_index = RISCV_EXCP_STORE_AMO_ADDR_MIS;
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    env->badaddr = addr;
-    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
-    env->two_stage_indirect_lookup = false;
-    cpu_loop_exit_restore(cs, retaddr);
-}
-
-
-static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType access_type)
-{
-    enum riscv_pmu_event_idx pmu_event_type;
-
-    switch (access_type) {
-    case MMU_INST_FETCH:
-        pmu_event_type = RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS;
-        break;
-    case MMU_DATA_LOAD:
-        pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS;
-        break;
-    case MMU_DATA_STORE:
-        pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS;
-        break;
-    default:
-        return;
-    }
-
-    riscv_pmu_incr_ctr(cpu, pmu_event_type);
-}
-
-bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-                        MMUAccessType access_type, int mmu_idx,
-                        bool probe, uintptr_t retaddr)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    vaddr im_address;
-    hwaddr pa = 0;
-    int prot, prot2, prot_pmp;
-    bool pmp_violation = false;
-    bool first_stage_error = true;
-    bool two_stage_lookup = mmuidx_2stage(mmu_idx);
-    bool two_stage_indirect_error = false;
-    int ret = TRANSLATE_FAIL;
-    int mode = mmu_idx;
-    /* default TLB page size */
-    target_ulong tlb_size = TARGET_PAGE_SIZE;
-
-    env->guest_phys_fault_addr = 0;
-
-    qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
-                  __func__, address, access_type, mmu_idx);
-
-    pmu_tlb_fill_incr_ctr(cpu, access_type);
-    if (two_stage_lookup) {
-        /* Two stage lookup */
-        ret = get_physical_address(env, &pa, &prot, address,
-                                   &env->guest_phys_fault_addr, access_type,
-                                   mmu_idx, true, true, false);
-
-        /*
-         * A G-stage exception may be triggered during two state lookup.
-         * And the env->guest_phys_fault_addr has already been set in
-         * get_physical_address().
-         */
-        if (ret == TRANSLATE_G_STAGE_FAIL) {
-            first_stage_error = false;
-            two_stage_indirect_error = true;
-        }
-
-        qemu_log_mask(CPU_LOG_MMU,
-                      "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
-                      HWADDR_FMT_plx " prot %d\n",
-                      __func__, address, ret, pa, prot);
-
-        if (ret == TRANSLATE_SUCCESS) {
-            /* Second stage lookup */
-            im_address = pa;
-
-            ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
-                                       access_type, MMUIdx_U, false, true,
-                                       false);
-
-            qemu_log_mask(CPU_LOG_MMU,
-                          "%s 2nd-stage address=%" VADDR_PRIx
-                          " ret %d physical "
-                          HWADDR_FMT_plx " prot %d\n",
-                          __func__, im_address, ret, pa, prot2);
-
-            prot &= prot2;
-
-            if (ret == TRANSLATE_SUCCESS) {
-                ret = get_physical_address_pmp(env, &prot_pmp, pa,
-                                               size, access_type, mode);
-                tlb_size = pmp_get_tlb_size(env, pa);
-
-                qemu_log_mask(CPU_LOG_MMU,
-                              "%s PMP address=" HWADDR_FMT_plx " ret %d prot"
-                              " %d tlb_size " TARGET_FMT_lu "\n",
-                              __func__, pa, ret, prot_pmp, tlb_size);
-
-                prot &= prot_pmp;
-            }
-
-            if (ret != TRANSLATE_SUCCESS) {
-                /*
-                 * Guest physical address translation failed, this is a HS
-                 * level exception
-                 */
-                first_stage_error = false;
-                env->guest_phys_fault_addr = (im_address |
-                                              (address &
-                                               (TARGET_PAGE_SIZE - 1))) >> 2;
-            }
-        }
-    } else {
-        /* Single stage lookup */
-        ret = get_physical_address(env, &pa, &prot, address, NULL,
-                                   access_type, mmu_idx, true, false, false);
-
-        qemu_log_mask(CPU_LOG_MMU,
-                      "%s address=%" VADDR_PRIx " ret %d physical "
-                      HWADDR_FMT_plx " prot %d\n",
-                      __func__, address, ret, pa, prot);
-
-        if (ret == TRANSLATE_SUCCESS) {
-            ret = get_physical_address_pmp(env, &prot_pmp, pa,
-                                           size, access_type, mode);
-            tlb_size = pmp_get_tlb_size(env, pa);
-
-            qemu_log_mask(CPU_LOG_MMU,
-                          "%s PMP address=" HWADDR_FMT_plx " ret %d prot"
-                          " %d tlb_size " TARGET_FMT_lu "\n",
-                          __func__, pa, ret, prot_pmp, tlb_size);
-
-            prot &= prot_pmp;
-        }
-    }
-
-    if (ret == TRANSLATE_PMP_FAIL) {
-        pmp_violation = true;
-    }
-
-    if (ret == TRANSLATE_SUCCESS) {
-        tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
-                     prot, mmu_idx, tlb_size);
-        return true;
-    } else if (probe) {
-        return false;
-    } else {
-        raise_mmu_exception(env, address, access_type, pmp_violation,
-                            first_stage_error, two_stage_lookup,
-                            two_stage_indirect_error);
-        cpu_loop_exit_restore(cs, retaddr);
-    }
-
-    return true;
-}
-
 static target_ulong riscv_transformed_insn(CPURISCVState *env,
                                            target_ulong insn,
                                            target_ulong taddr)
diff --git a/target/riscv/tcg/sysemu/cpu_helper.c b/target/riscv/tcg/sysemu/cpu_helper.c
new file mode 100644
index 0000000000..544f489872
--- /dev/null
+++ b/target/riscv/tcg/sysemu/cpu_helper.c
@@ -0,0 +1,765 @@
+/*
+ * RISC-V CPU system helpers (TCG specific)
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "exec/exec-all.h"
+#include "cpu.h"
+#include "internals.h"
+#include "sysemu/cpu-timers.h"
+#include "sysemu/pmu.h"
+#include "sysemu/instmap.h"
+#include "semihosting/common-semi.h"
+#include "trace.h"
+
+
+static int riscv_cpu_local_irq_pending(CPURISCVState *env)
+{
+    int virq;
+    uint64_t irqs, pending, mie, hsie, vsie;
+
+    /* Determine interrupt enable state of all privilege modes */
+    if (env->virt_enabled) {
+        mie = 1;
+        hsie = 1;
+        vsie = (env->priv < PRV_S) ||
+               (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
+    } else {
+        mie = (env->priv < PRV_M) ||
+              (env->priv == PRV_M && get_field(env->mstatus, MSTATUS_MIE));
+        hsie = (env->priv < PRV_S) ||
+               (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
+        vsie = 0;
+    }
+
+    /* Determine all pending interrupts */
+    pending = riscv_cpu_all_pending(env);
+
+    /* Check M-mode interrupts */
+    irqs = pending & ~env->mideleg & -mie;
+    if (irqs) {
+        return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
+                                        irqs, env->miprio);
+    }
+
+    /* Check HS-mode interrupts */
+    irqs = pending & env->mideleg & ~env->hideleg & -hsie;
+    if (irqs) {
+        return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
+                                        irqs, env->siprio);
+    }
+
+    /* Check VS-mode interrupts */
+    irqs = pending & env->mideleg & env->hideleg & -vsie;
+    if (irqs) {
+        virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
+                                        irqs >> 1, env->hviprio);
+        return (virq <= 0) ? virq : virq + 1;
+    }
+
+    /* Indicate no pending interrupt */
+    return RISCV_EXCP_NONE;
+}
+
+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_local_irq_pending(env);
+        if (interruptno >= 0) {
+            cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
+            riscv_cpu_do_interrupt(cs);
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * get_physical_address_pmp - check PMP permission for this physical address
+ *
+ * Match the PMP region and check permission for this physical address and it's
+ * TLB page. Returns 0 if the permission checking was successful
+ *
+ * @env: CPURISCVState
+ * @prot: The returned protection attributes
+ * @addr: The physical address to be checked permission
+ * @access_type: The type of MMU access
+ * @mode: Indicates current privilege level.
+ */
+static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
+                                    int size, MMUAccessType access_type,
+                                    int mode)
+{
+    pmp_priv_t pmp_priv;
+    bool pmp_has_privs;
+
+    if (!riscv_cpu_cfg(env)->pmp) {
+        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return TRANSLATE_SUCCESS;
+    }
+
+    pmp_has_privs = pmp_hart_has_privs(env, addr, size, 1 << access_type,
+                                       &pmp_priv, mode);
+    if (!pmp_has_privs) {
+        *prot = 0;
+        return TRANSLATE_PMP_FAIL;
+    }
+
+    *prot = pmp_priv_to_page_prot(pmp_priv);
+
+    return TRANSLATE_SUCCESS;
+}
+
+/*
+ * get_physical_address - get the physical address for this virtual address
+ *
+ * Do a page table walk to obtain the physical address corresponding to a
+ * virtual address. Returns 0 if the translation was successful
+ *
+ * Adapted from Spike's mmu_t::translate and mmu_t::walk
+ *
+ * @env: CPURISCVState
+ * @physical: This will be set to the calculated physical address
+ * @prot: The returned protection attributes
+ * @addr: The virtual address or guest physical address to be translated
+ * @fault_pte_addr: If not NULL, this will be set to fault pte address
+ *                  when a error occurs on pte address translation.
+ *                  This will already be shifted to match htval.
+ * @access_type: The type of MMU access
+ * @mmu_idx: Indicates current privilege level
+ * @first_stage: Are we in first stage translation?
+ *               Second stage is used for hypervisor guest translation
+ * @two_stage: Are we going to perform two stage translation
+ * @is_debug: Is this access from a debugger or the monitor?
+ */
+static int get_physical_address(CPURISCVState *env, hwaddr *physical,
+                                int *ret_prot, vaddr addr,
+                                target_ulong *fault_pte_addr,
+                                int access_type, int mmu_idx,
+                                bool first_stage, bool two_stage,
+                                bool is_debug)
+{
+    /*
+     * NOTE: the env->pc value visible here will not be
+     * correct, but the value visible to the exception handler
+     * (riscv_cpu_do_interrupt) is correct
+     */
+    MemTxResult res;
+    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
+    int mode = mmuidx_priv(mmu_idx);
+    bool use_background = false;
+    hwaddr ppn;
+    int napot_bits = 0;
+    target_ulong napot_mask;
+
+    /*
+     * Check if we should use the background registers for the two
+     * stage translation. We don't need to check if we actually need
+     * two stage translation as that happened before this function
+     * was called. Background registers will be used if the guest has
+     * forced a two stage translation to be on (in HS or M mode).
+     */
+    if (!env->virt_enabled && two_stage) {
+        use_background = true;
+    }
+
+    if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
+        *physical = addr;
+        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return TRANSLATE_SUCCESS;
+    }
+
+    *ret_prot = 0;
+
+    hwaddr base;
+    int levels, ptidxbits, ptesize, vm, widened;
+
+    if (first_stage == true) {
+        if (use_background) {
+            if (riscv_cpu_mxl(env) == MXL_RV32) {
+                base = (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSHIFT;
+                vm = get_field(env->vsatp, SATP32_MODE);
+            } else {
+                base = (hwaddr)get_field(env->vsatp, SATP64_PPN) << PGSHIFT;
+                vm = get_field(env->vsatp, SATP64_MODE);
+            }
+        } else {
+            if (riscv_cpu_mxl(env) == MXL_RV32) {
+                base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
+                vm = get_field(env->satp, SATP32_MODE);
+            } else {
+                base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
+                vm = get_field(env->satp, SATP64_MODE);
+            }
+        }
+        widened = 0;
+    } else {
+        if (riscv_cpu_mxl(env) == MXL_RV32) {
+            base = (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT;
+            vm = get_field(env->hgatp, SATP32_MODE);
+        } else {
+            base = (hwaddr)get_field(env->hgatp, SATP64_PPN) << PGSHIFT;
+            vm = get_field(env->hgatp, SATP64_MODE);
+        }
+        widened = 2;
+    }
+
+    switch (vm) {
+    case VM_1_10_SV32:
+      levels = 2; ptidxbits = 10; ptesize = 4; break;
+    case VM_1_10_SV39:
+      levels = 3; ptidxbits = 9; ptesize = 8; break;
+    case VM_1_10_SV48:
+      levels = 4; ptidxbits = 9; ptesize = 8; break;
+    case VM_1_10_SV57:
+      levels = 5; ptidxbits = 9; ptesize = 8; break;
+    case VM_1_10_MBARE:
+        *physical = addr;
+        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return TRANSLATE_SUCCESS;
+    default:
+      g_assert_not_reached();
+    }
+
+    CPUState *cs = env_cpu(env);
+    int va_bits = PGSHIFT + levels * ptidxbits + widened;
+
+    if (first_stage == true) {
+        target_ulong mask, masked_msbs;
+
+        if (TARGET_LONG_BITS > (va_bits - 1)) {
+            mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+        } else {
+            mask = 0;
+        }
+        masked_msbs = (addr >> (va_bits - 1)) & mask;
+
+        if (masked_msbs != 0 && masked_msbs != mask) {
+            return TRANSLATE_FAIL;
+        }
+    } else {
+        if (vm != VM_1_10_SV32 && addr >> va_bits != 0) {
+            return TRANSLATE_FAIL;
+        }
+    }
+
+    bool pbmte = env->menvcfg & MENVCFG_PBMTE;
+    bool hade = env->menvcfg & MENVCFG_HADE;
+
+    if (first_stage && two_stage && env->virt_enabled) {
+        pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
+        hade = hade && (env->henvcfg & HENVCFG_HADE);
+    }
+
+    int ptshift = (levels - 1) * ptidxbits;
+    target_ulong pte;
+    hwaddr pte_addr;
+    int i;
+
+#if !TCG_OVERSIZED_GUEST
+restart:
+#endif
+    for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
+        target_ulong idx;
+        if (i == 0) {
+            idx = (addr >> (PGSHIFT + ptshift)) &
+                           ((1 << (ptidxbits + widened)) - 1);
+        } else {
+            idx = (addr >> (PGSHIFT + ptshift)) &
+                           ((1 << ptidxbits) - 1);
+        }
+
+        /* check that physical address of PTE is legal */
+
+        if (two_stage && first_stage) {
+            int vbase_prot;
+            hwaddr vbase;
+
+            /* Do the second stage translation on the base PTE address. */
+            int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
+                                                 base, NULL, MMU_DATA_LOAD,
+                                                 MMUIdx_U, false, true,
+                                                 is_debug);
+
+            if (vbase_ret != TRANSLATE_SUCCESS) {
+                if (fault_pte_addr) {
+                    *fault_pte_addr = (base + idx * ptesize) >> 2;
+                }
+                return TRANSLATE_G_STAGE_FAIL;
+            }
+
+            pte_addr = vbase + idx * ptesize;
+        } else {
+            pte_addr = base + idx * ptesize;
+        }
+
+        int pmp_prot;
+        int pmp_ret = get_physical_address_pmp(env, &pmp_prot, pte_addr,
+                                               sizeof(target_ulong),
+                                               MMU_DATA_LOAD, PRV_S);
+        if (pmp_ret != TRANSLATE_SUCCESS) {
+            return TRANSLATE_PMP_FAIL;
+        }
+
+        if (riscv_cpu_mxl(env) == MXL_RV32) {
+            pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
+        } else {
+            pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
+        }
+
+        if (res != MEMTX_OK) {
+            return TRANSLATE_FAIL;
+        }
+
+        if (riscv_cpu_sxl(env) == MXL_RV32) {
+            ppn = pte >> PTE_PPN_SHIFT;
+        } else {
+            if (pte & PTE_RESERVED) {
+                return TRANSLATE_FAIL;
+            }
+
+            if (!pbmte && (pte & PTE_PBMT)) {
+                return TRANSLATE_FAIL;
+            }
+
+            if (!riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
+                return TRANSLATE_FAIL;
+            }
+
+            ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
+        }
+
+        if (!(pte & PTE_V)) {
+            /* Invalid PTE */
+            return TRANSLATE_FAIL;
+        }
+        if (pte & (PTE_R | PTE_W | PTE_X)) {
+            goto leaf;
+        }
+
+        /* Inner PTE, continue walking */
+        if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
+            return TRANSLATE_FAIL;
+        }
+        base = ppn << PGSHIFT;
+    }
+
+    /* No leaf pte at any translation level. */
+    return TRANSLATE_FAIL;
+
+ leaf:
+    if (ppn & ((1ULL << ptshift) - 1)) {
+        /* Misaligned PPN */
+        return TRANSLATE_FAIL;
+    }
+    if (!pbmte && (pte & PTE_PBMT)) {
+        /* Reserved without Svpbmt. */
+        return TRANSLATE_FAIL;
+    }
+
+    /* Check for reserved combinations of RWX flags. */
+    switch (pte & (PTE_R | PTE_W | PTE_X)) {
+    case PTE_W:
+    case PTE_W | PTE_X:
+        return TRANSLATE_FAIL;
+    }
+
+    int prot = 0;
+    if (pte & PTE_R) {
+        prot |= PAGE_READ;
+    }
+    if (pte & PTE_W) {
+        prot |= PAGE_WRITE;
+    }
+    if (pte & PTE_X) {
+        bool mxr;
+
+        if (first_stage == true) {
+            mxr = get_field(env->mstatus, MSTATUS_MXR);
+        } else {
+            mxr = get_field(env->vsstatus, MSTATUS_MXR);
+        }
+        if (mxr) {
+            prot |= PAGE_READ;
+        }
+        prot |= PAGE_EXEC;
+    }
+
+    if (pte & PTE_U) {
+        if (mode != PRV_U) {
+            if (!mmuidx_sum(mmu_idx)) {
+                return TRANSLATE_FAIL;
+            }
+            /* SUM allows only read+write, not execute. */
+            prot &= PAGE_READ | PAGE_WRITE;
+        }
+    } else if (mode != PRV_S) {
+        /* Supervisor PTE flags when not S mode */
+        return TRANSLATE_FAIL;
+    }
+
+    if (!((prot >> access_type) & 1)) {
+        /* Access check failed */
+        return TRANSLATE_FAIL;
+    }
+
+    /* If necessary, set accessed and dirty bits. */
+    target_ulong updated_pte = pte | PTE_A |
+                (access_type == MMU_DATA_STORE ? PTE_D : 0);
+
+    /* Page table updates need to be atomic with MTTCG enabled */
+    if (updated_pte != pte && !is_debug) {
+        if (!hade) {
+            return TRANSLATE_FAIL;
+        }
+
+        /*
+         * - if accessed or dirty bits need updating, and the PTE is
+         *   in RAM, then we do so atomically with a compare and swap.
+         * - 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, MEMTXATTRS_UNSPECIFIED);
+        if (memory_region_is_ram(mr)) {
+            target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
+#if TCG_OVERSIZED_GUEST
+            /*
+             * MTTCG is not enabled on oversized TCG guests so
+             * page table updates do not need to be atomic
+             */
+            *pte_pa = pte = updated_pte;
+#else
+            target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+            if (old_pte != pte) {
+                goto restart;
+            }
+            pte = updated_pte;
+#endif
+        } else {
+            /*
+             * Misconfigured PTE in ROM (AD bits are not preset) or
+             * PTE is in IO space and can't be updated atomically.
+             */
+            return TRANSLATE_FAIL;
+        }
+    }
+
+    /* For superpage mappings, make a fake leaf PTE for the TLB's benefit. */
+    target_ulong vpn = addr >> PGSHIFT;
+
+    if (riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
+        napot_bits = ctzl(ppn) + 1;
+        if ((i != (levels - 1)) || (napot_bits != 4)) {
+            return TRANSLATE_FAIL;
+        }
+    }
+
+    napot_mask = (1 << napot_bits) - 1;
+    *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
+                  (vpn & (((target_ulong)1 << ptshift) - 1))
+                 ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
+
+    /*
+     * Remove write permission unless this is a store, or the page is
+     * already dirty, so that we TLB miss on later writes to update
+     * the dirty bit.
+     */
+    if (access_type != MMU_DATA_STORE && !(pte & PTE_D)) {
+        prot &= ~PAGE_WRITE;
+    }
+    *ret_prot = prot;
+
+    return TRANSLATE_SUCCESS;
+}
+
+static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
+                                MMUAccessType access_type, bool pmp_violation,
+                                bool first_stage, bool two_stage,
+                                bool two_stage_indirect)
+{
+    CPUState *cs = env_cpu(env);
+    int page_fault_exceptions, vm;
+    uint64_t stap_mode;
+
+    if (riscv_cpu_mxl(env) == MXL_RV32) {
+        stap_mode = SATP32_MODE;
+    } else {
+        stap_mode = SATP64_MODE;
+    }
+
+    if (first_stage) {
+        vm = get_field(env->satp, stap_mode);
+    } else {
+        vm = get_field(env->hgatp, stap_mode);
+    }
+
+    page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
+
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        if (env->virt_enabled && !first_stage) {
+            cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+        }
+        break;
+    case MMU_DATA_LOAD:
+        if (two_stage && !first_stage) {
+            cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+        }
+        break;
+    case MMU_DATA_STORE:
+        if (two_stage && !first_stage) {
+            cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
+        } else {
+            cs->exception_index = page_fault_exceptions ?
+                RISCV_EXCP_STORE_PAGE_FAULT :
+                RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    env->badaddr = address;
+    env->two_stage_lookup = two_stage;
+    env->two_stage_indirect_lookup = two_stage_indirect;
+}
+
+hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    hwaddr phys_addr;
+    int prot;
+    int mmu_idx = cpu_mmu_index(&cpu->env, false);
+
+    if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
+                             true, env->virt_enabled, true)) {
+        return -1;
+    }
+
+    if (env->virt_enabled) {
+        if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL,
+                                 0, mmu_idx, false, true, true)) {
+            return -1;
+        }
+    }
+
+    return phys_addr & TARGET_PAGE_MASK;
+}
+
+void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+                                     vaddr addr, unsigned size,
+                                     MMUAccessType access_type,
+                                     int mmu_idx, MemTxAttrs attrs,
+                                     MemTxResult response, uintptr_t retaddr)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+
+    if (access_type == MMU_DATA_STORE) {
+        cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+    } else if (access_type == MMU_DATA_LOAD) {
+        cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
+    } else {
+        cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
+    }
+
+    env->badaddr = addr;
+    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
+    env->two_stage_indirect_lookup = false;
+    cpu_loop_exit_restore(cs, retaddr);
+}
+
+void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+                                   MMUAccessType access_type, int mmu_idx,
+                                   uintptr_t retaddr)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        cs->exception_index = RISCV_EXCP_INST_ADDR_MIS;
+        break;
+    case MMU_DATA_LOAD:
+        cs->exception_index = RISCV_EXCP_LOAD_ADDR_MIS;
+        break;
+    case MMU_DATA_STORE:
+        cs->exception_index = RISCV_EXCP_STORE_AMO_ADDR_MIS;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    env->badaddr = addr;
+    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
+    env->two_stage_indirect_lookup = false;
+    cpu_loop_exit_restore(cs, retaddr);
+}
+
+static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType access_type)
+{
+    enum riscv_pmu_event_idx pmu_event_type;
+
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        pmu_event_type = RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS;
+        break;
+    case MMU_DATA_LOAD:
+        pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS;
+        break;
+    case MMU_DATA_STORE:
+        pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS;
+        break;
+    default:
+        return;
+    }
+
+    riscv_pmu_incr_ctr(cpu, pmu_event_type);
+}
+
+bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+                        MMUAccessType access_type, int mmu_idx,
+                        bool probe, uintptr_t retaddr)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    vaddr im_address;
+    hwaddr pa = 0;
+    int prot, prot2, prot_pmp;
+    bool pmp_violation = false;
+    bool first_stage_error = true;
+    bool two_stage_lookup = mmuidx_2stage(mmu_idx);
+    bool two_stage_indirect_error = false;
+    int ret = TRANSLATE_FAIL;
+    int mode = mmu_idx;
+    /* default TLB page size */
+    target_ulong tlb_size = TARGET_PAGE_SIZE;
+
+    env->guest_phys_fault_addr = 0;
+
+    qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
+                  __func__, address, access_type, mmu_idx);
+
+    pmu_tlb_fill_incr_ctr(cpu, access_type);
+    if (two_stage_lookup) {
+        /* Two stage lookup */
+        ret = get_physical_address(env, &pa, &prot, address,
+                                   &env->guest_phys_fault_addr, access_type,
+                                   mmu_idx, true, true, false);
+
+        /*
+         * A G-stage exception may be triggered during two state lookup.
+         * And the env->guest_phys_fault_addr has already been set in
+         * get_physical_address().
+         */
+        if (ret == TRANSLATE_G_STAGE_FAIL) {
+            first_stage_error = false;
+            two_stage_indirect_error = true;
+        }
+
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
+                      HWADDR_FMT_plx " prot %d\n",
+                      __func__, address, ret, pa, prot);
+
+        if (ret == TRANSLATE_SUCCESS) {
+            /* Second stage lookup */
+            im_address = pa;
+
+            ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
+                                       access_type, MMUIdx_U, false, true,
+                                       false);
+
+            qemu_log_mask(CPU_LOG_MMU,
+                          "%s 2nd-stage address=%" VADDR_PRIx
+                          " ret %d physical "
+                          HWADDR_FMT_plx " prot %d\n",
+                          __func__, im_address, ret, pa, prot2);
+
+            prot &= prot2;
+
+            if (ret == TRANSLATE_SUCCESS) {
+                ret = get_physical_address_pmp(env, &prot_pmp, pa,
+                                               size, access_type, mode);
+                tlb_size = pmp_get_tlb_size(env, pa);
+
+                qemu_log_mask(CPU_LOG_MMU,
+                              "%s PMP address=" HWADDR_FMT_plx " ret %d prot"
+                              " %d tlb_size " TARGET_FMT_lu "\n",
+                              __func__, pa, ret, prot_pmp, tlb_size);
+
+                prot &= prot_pmp;
+            }
+
+            if (ret != TRANSLATE_SUCCESS) {
+                /*
+                 * Guest physical address translation failed, this is a HS
+                 * level exception
+                 */
+                first_stage_error = false;
+                env->guest_phys_fault_addr = (im_address |
+                                              (address &
+                                               (TARGET_PAGE_SIZE - 1))) >> 2;
+            }
+        }
+    } else {
+        /* Single stage lookup */
+        ret = get_physical_address(env, &pa, &prot, address, NULL,
+                                   access_type, mmu_idx, true, false, false);
+
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s address=%" VADDR_PRIx " ret %d physical "
+                      HWADDR_FMT_plx " prot %d\n",
+                      __func__, address, ret, pa, prot);
+
+        if (ret == TRANSLATE_SUCCESS) {
+            ret = get_physical_address_pmp(env, &prot_pmp, pa,
+                                           size, access_type, mode);
+            tlb_size = pmp_get_tlb_size(env, pa);
+
+            qemu_log_mask(CPU_LOG_MMU,
+                          "%s PMP address=" HWADDR_FMT_plx " ret %d prot"
+                          " %d tlb_size " TARGET_FMT_lu "\n",
+                          __func__, pa, ret, prot_pmp, tlb_size);
+
+            prot &= prot_pmp;
+        }
+    }
+
+    if (ret == TRANSLATE_PMP_FAIL) {
+        pmp_violation = true;
+    }
+
+    if (ret == TRANSLATE_SUCCESS) {
+        tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
+                     prot, mmu_idx, tlb_size);
+        return true;
+    } else if (probe) {
+        return false;
+    } else {
+        raise_mmu_exception(env, address, access_type, pmp_violation,
+                            first_stage_error, two_stage_lookup,
+                            two_stage_indirect_error);
+        cpu_loop_exit_restore(cs, retaddr);
+    }
+
+    return true;
+}
diff --git a/target/riscv/tcg/tcg-stub.c b/target/riscv/tcg/tcg-stub.c
index dfe42ae2ac..e329d25355 100644
--- a/target/riscv/tcg/tcg-stub.c
+++ b/target/riscv/tcg/tcg-stub.c
@@ -23,3 +23,9 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
 {
     g_assert_not_reached();
 }
+
+hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+    /* XXX too many TCG code in the real riscv_cpu_get_phys_page_debug() */
+    return -1;
+}
diff --git a/target/riscv/tcg/sysemu/meson.build b/target/riscv/tcg/sysemu/meson.build
index e8e61e5784..a549e497ce 100644
--- a/target/riscv/tcg/sysemu/meson.build
+++ b/target/riscv/tcg/sysemu/meson.build
@@ -1,3 +1,4 @@
 riscv_system_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'cpu_helper.c',
   'debug.c',
 ))
-- 
2.38.1



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

* [PATCH v3 14/16] target/riscv: Move sysemu-specific code to sysemu/cpu_helper.c
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (12 preceding siblings ...)
  2023-07-11 12:14 ` [RFC PATCH v3 13/16] target/riscv: Move TCG/sysemu-specific code to tcg/sysemu/cpu_helper.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 15/16] target/riscv: Restrict TCG-specific prototype declarations Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 16/16] gitlab-ci.d/crossbuilds: Add KVM riscv64 cross-build jobs Philippe Mathieu-Daudé
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu_helper.c        | 858 +-----------------------------
 target/riscv/sysemu/cpu_helper.c | 863 +++++++++++++++++++++++++++++++
 target/riscv/sysemu/meson.build  |   1 +
 3 files changed, 865 insertions(+), 857 deletions(-)
 create mode 100644 target/riscv/sysemu/cpu_helper.c

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f1d0cd1e64..900e3c2b5c 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -18,22 +18,12 @@
  */
 
 #include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "cpu.h"
 #include "internals.h"
-#include "sysemu/pmu.h"
-#include "exec/exec-all.h"
-#include "sysemu/instmap.h"
-#include "tcg/tcg-op.h"
-#include "trace.h"
-#include "semihosting/common-semi.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/cpu-timers.h"
 #endif
-#include "cpu_bits.h"
-#include "sysemu/debug.h"
-#include "tcg/oversized-guest.h"
+
 
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 {
@@ -108,849 +98,3 @@ void riscv_cpu_update_mask(CPURISCVState *env)
         env->cur_pmbase = base;
     }
 }
-
-#ifndef CONFIG_USER_ONLY
-
-/*
- * The HS-mode is allowed to configure priority only for the
- * following VS-mode local interrupts:
- *
- * 0  (Reserved interrupt, reads as zero)
- * 1  Supervisor software interrupt
- * 4  (Reserved interrupt, reads as zero)
- * 5  Supervisor timer interrupt
- * 8  (Reserved interrupt, reads as zero)
- * 13 (Reserved interrupt)
- * 14 "
- * 15 "
- * 16 "
- * 17 "
- * 18 "
- * 19 "
- * 20 "
- * 21 "
- * 22 "
- * 23 "
- */
-
-static const int hviprio_index2irq[] = {
-    0, 1, 4, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
-static const int hviprio_index2rdzero[] = {
-    1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero)
-{
-    if (index < 0 || ARRAY_SIZE(hviprio_index2irq) <= index) {
-        return -EINVAL;
-    }
-
-    if (out_irq) {
-        *out_irq = hviprio_index2irq[index];
-    }
-
-    if (out_rdzero) {
-        *out_rdzero = hviprio_index2rdzero[index];
-    }
-
-    return 0;
-}
-
-/*
- * Default priorities of local interrupts are defined in the
- * RISC-V Advanced Interrupt Architecture specification.
- *
- * ----------------------------------------------------------------
- *  Default  |
- *  Priority | Major Interrupt Numbers
- * ----------------------------------------------------------------
- *  Highest  | 47, 23, 46, 45, 22, 44,
- *           | 43, 21, 42, 41, 20, 40
- *           |
- *           | 11 (0b),  3 (03),  7 (07)
- *           |  9 (09),  1 (01),  5 (05)
- *           | 12 (0c)
- *           | 10 (0a),  2 (02),  6 (06)
- *           |
- *           | 39, 19, 38, 37, 18, 36,
- *  Lowest   | 35, 17, 34, 33, 16, 32
- * ----------------------------------------------------------------
- */
-static const uint8_t default_iprio[64] = {
-    /* Custom interrupts 48 to 63 */
-    [63] = IPRIO_MMAXIPRIO,
-    [62] = IPRIO_MMAXIPRIO,
-    [61] = IPRIO_MMAXIPRIO,
-    [60] = IPRIO_MMAXIPRIO,
-    [59] = IPRIO_MMAXIPRIO,
-    [58] = IPRIO_MMAXIPRIO,
-    [57] = IPRIO_MMAXIPRIO,
-    [56] = IPRIO_MMAXIPRIO,
-    [55] = IPRIO_MMAXIPRIO,
-    [54] = IPRIO_MMAXIPRIO,
-    [53] = IPRIO_MMAXIPRIO,
-    [52] = IPRIO_MMAXIPRIO,
-    [51] = IPRIO_MMAXIPRIO,
-    [50] = IPRIO_MMAXIPRIO,
-    [49] = IPRIO_MMAXIPRIO,
-    [48] = IPRIO_MMAXIPRIO,
-
-    /* Custom interrupts 24 to 31 */
-    [31] = IPRIO_MMAXIPRIO,
-    [30] = IPRIO_MMAXIPRIO,
-    [29] = IPRIO_MMAXIPRIO,
-    [28] = IPRIO_MMAXIPRIO,
-    [27] = IPRIO_MMAXIPRIO,
-    [26] = IPRIO_MMAXIPRIO,
-    [25] = IPRIO_MMAXIPRIO,
-    [24] = IPRIO_MMAXIPRIO,
-
-    [47] = IPRIO_DEFAULT_UPPER,
-    [23] = IPRIO_DEFAULT_UPPER + 1,
-    [46] = IPRIO_DEFAULT_UPPER + 2,
-    [45] = IPRIO_DEFAULT_UPPER + 3,
-    [22] = IPRIO_DEFAULT_UPPER + 4,
-    [44] = IPRIO_DEFAULT_UPPER + 5,
-
-    [43] = IPRIO_DEFAULT_UPPER + 6,
-    [21] = IPRIO_DEFAULT_UPPER + 7,
-    [42] = IPRIO_DEFAULT_UPPER + 8,
-    [41] = IPRIO_DEFAULT_UPPER + 9,
-    [20] = IPRIO_DEFAULT_UPPER + 10,
-    [40] = IPRIO_DEFAULT_UPPER + 11,
-
-    [11] = IPRIO_DEFAULT_M,
-    [3]  = IPRIO_DEFAULT_M + 1,
-    [7]  = IPRIO_DEFAULT_M + 2,
-
-    [9]  = IPRIO_DEFAULT_S,
-    [1]  = IPRIO_DEFAULT_S + 1,
-    [5]  = IPRIO_DEFAULT_S + 2,
-
-    [12] = IPRIO_DEFAULT_SGEXT,
-
-    [10] = IPRIO_DEFAULT_VS,
-    [2]  = IPRIO_DEFAULT_VS + 1,
-    [6]  = IPRIO_DEFAULT_VS + 2,
-
-    [39] = IPRIO_DEFAULT_LOWER,
-    [19] = IPRIO_DEFAULT_LOWER + 1,
-    [38] = IPRIO_DEFAULT_LOWER + 2,
-    [37] = IPRIO_DEFAULT_LOWER + 3,
-    [18] = IPRIO_DEFAULT_LOWER + 4,
-    [36] = IPRIO_DEFAULT_LOWER + 5,
-
-    [35] = IPRIO_DEFAULT_LOWER + 6,
-    [17] = IPRIO_DEFAULT_LOWER + 7,
-    [34] = IPRIO_DEFAULT_LOWER + 8,
-    [33] = IPRIO_DEFAULT_LOWER + 9,
-    [16] = IPRIO_DEFAULT_LOWER + 10,
-    [32] = IPRIO_DEFAULT_LOWER + 11,
-};
-
-uint8_t riscv_cpu_default_priority(int irq)
-{
-    if (irq < 0 || irq > 63) {
-        return IPRIO_MMAXIPRIO;
-    }
-
-    return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
-};
-
-int riscv_cpu_pending_to_irq(CPURISCVState *env,
-                             int extirq, unsigned int extirq_def_prio,
-                             uint64_t pending, uint8_t *iprio)
-{
-    int irq, best_irq = RISCV_EXCP_NONE;
-    unsigned int prio, best_prio = UINT_MAX;
-
-    if (!pending) {
-        return RISCV_EXCP_NONE;
-    }
-
-    irq = ctz64(pending);
-    if (!((extirq == IRQ_M_EXT) ? riscv_cpu_cfg(env)->ext_smaia :
-                                  riscv_cpu_cfg(env)->ext_ssaia)) {
-        return irq;
-    }
-
-    pending = pending >> irq;
-    while (pending) {
-        prio = iprio[irq];
-        if (!prio) {
-            if (irq == extirq) {
-                prio = extirq_def_prio;
-            } else {
-                prio = (riscv_cpu_default_priority(irq) < extirq_def_prio) ?
-                       1 : IPRIO_MMAXIPRIO;
-            }
-        }
-        if ((pending & 0x1) && (prio <= best_prio)) {
-            best_irq = irq;
-            best_prio = prio;
-        }
-        irq++;
-        pending = pending >> 1;
-    }
-
-    return best_irq;
-}
-
-uint64_t riscv_cpu_all_pending(CPURISCVState *env)
-{
-    uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
-    uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
-    uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0;
-
-    return (env->mip | vsgein | vstip) & env->mie;
-}
-
-int riscv_cpu_mirq_pending(CPURISCVState *env)
-{
-    uint64_t irqs = riscv_cpu_all_pending(env) & ~env->mideleg &
-                    ~(MIP_SGEIP | MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
-
-    return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
-                                    irqs, env->miprio);
-}
-
-int riscv_cpu_sirq_pending(CPURISCVState *env)
-{
-    uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
-                    ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
-
-    return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
-                                    irqs, env->siprio);
-}
-
-int riscv_cpu_vsirq_pending(CPURISCVState *env)
-{
-    uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
-                    (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
-
-    return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
-                                    irqs >> 1, env->hviprio);
-}
-
-/* Return true is floating point support is currently enabled */
-bool riscv_cpu_fp_enabled(CPURISCVState *env)
-{
-    if (env->mstatus & MSTATUS_FS) {
-        if (env->virt_enabled && !(env->mstatus_hs & MSTATUS_FS)) {
-            return false;
-        }
-        return true;
-    }
-
-    return false;
-}
-
-/* Return true is vector support is currently enabled */
-bool riscv_cpu_vector_enabled(CPURISCVState *env)
-{
-    if (env->mstatus & MSTATUS_VS) {
-        if (env->virt_enabled && !(env->mstatus_hs & MSTATUS_VS)) {
-            return false;
-        }
-        return true;
-    }
-
-    return false;
-}
-
-void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
-{
-    uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM |
-                            MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
-                            MSTATUS64_UXL | MSTATUS_VS;
-
-    if (riscv_has_ext(env, RVF)) {
-        mstatus_mask |= MSTATUS_FS;
-    }
-    bool current_virt = env->virt_enabled;
-
-    g_assert(riscv_has_ext(env, RVH));
-
-    if (current_virt) {
-        /* Current V=1 and we are about to change to V=0 */
-        env->vsstatus = env->mstatus & mstatus_mask;
-        env->mstatus &= ~mstatus_mask;
-        env->mstatus |= env->mstatus_hs;
-
-        env->vstvec = env->stvec;
-        env->stvec = env->stvec_hs;
-
-        env->vsscratch = env->sscratch;
-        env->sscratch = env->sscratch_hs;
-
-        env->vsepc = env->sepc;
-        env->sepc = env->sepc_hs;
-
-        env->vscause = env->scause;
-        env->scause = env->scause_hs;
-
-        env->vstval = env->stval;
-        env->stval = env->stval_hs;
-
-        env->vsatp = env->satp;
-        env->satp = env->satp_hs;
-    } else {
-        /* Current V=0 and we are about to change to V=1 */
-        env->mstatus_hs = env->mstatus & mstatus_mask;
-        env->mstatus &= ~mstatus_mask;
-        env->mstatus |= env->vsstatus;
-
-        env->stvec_hs = env->stvec;
-        env->stvec = env->vstvec;
-
-        env->sscratch_hs = env->sscratch;
-        env->sscratch = env->vsscratch;
-
-        env->sepc_hs = env->sepc;
-        env->sepc = env->vsepc;
-
-        env->scause_hs = env->scause;
-        env->scause = env->vscause;
-
-        env->stval_hs = env->stval;
-        env->stval = env->vstval;
-
-        env->satp_hs = env->satp;
-        env->satp = env->vsatp;
-    }
-}
-
-target_ulong riscv_cpu_get_geilen(CPURISCVState *env)
-{
-    if (!riscv_has_ext(env, RVH)) {
-        return 0;
-    }
-
-    return env->geilen;
-}
-
-void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
-{
-    if (!riscv_has_ext(env, RVH)) {
-        return;
-    }
-
-    if (geilen > (TARGET_LONG_BITS - 1)) {
-        return;
-    }
-
-    env->geilen = geilen;
-}
-
-/* This function can only be called to set virt when RVH is enabled */
-void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
-{
-    /* Flush the TLB on all virt mode changes. */
-    if (env->virt_enabled != enable) {
-        tlb_flush(env_cpu(env));
-    }
-
-    env->virt_enabled = enable;
-
-    if (enable) {
-        /*
-         * The guest external interrupts from an interrupt controller are
-         * delivered only when the Guest/VM is running (i.e. V=1). This means
-         * any guest external interrupt which is triggered while the Guest/VM
-         * is not running (i.e. V=0) will be missed on QEMU resulting in guest
-         * with sluggish response to serial console input and other I/O events.
-         *
-         * To solve this, we check and inject interrupt after setting V=1.
-         */
-        riscv_cpu_update_mip(env, 0, 0);
-    }
-}
-
-int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
-{
-    CPURISCVState *env = &cpu->env;
-    if (env->miclaim & interrupts) {
-        return -1;
-    } else {
-        env->miclaim |= interrupts;
-        return 0;
-    }
-}
-
-uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
-                              uint64_t value)
-{
-    CPUState *cs = env_cpu(env);
-    uint64_t gein, vsgein = 0, vstip = 0, old = env->mip;
-
-    if (env->virt_enabled) {
-        gein = get_field(env->hstatus, HSTATUS_VGEIN);
-        vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
-    }
-
-    vstip = env->vstime_irq ? MIP_VSTIP : 0;
-
-    QEMU_IOTHREAD_LOCK_GUARD();
-
-    env->mip = (env->mip & ~mask) | (value & mask);
-
-    if (env->mip | vsgein | vstip) {
-        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-    }
-
-    return old;
-}
-
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
-                             void *arg)
-{
-    env->rdtime_fn = fn;
-    env->rdtime_fn_arg = arg;
-}
-
-void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
-                                   int (*rmw_fn)(void *arg,
-                                                 target_ulong reg,
-                                                 target_ulong *val,
-                                                 target_ulong new_val,
-                                                 target_ulong write_mask),
-                                   void *rmw_fn_arg)
-{
-    if (priv <= PRV_M) {
-        env->aia_ireg_rmw_fn[priv] = rmw_fn;
-        env->aia_ireg_rmw_fn_arg[priv] = rmw_fn_arg;
-    }
-}
-
-void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
-{
-    g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
-
-    if (icount_enabled() && newpriv != env->priv) {
-        riscv_itrigger_update_priv(env);
-    }
-    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
-    env->priv = newpriv;
-    env->xl = cpu_recompute_xl(env);
-    riscv_cpu_update_mask(env);
-
-    /*
-     * Clear the load reservation - otherwise a reservation placed in one
-     * context/process can be used by another, resulting in an SC succeeding
-     * incorrectly. Version 2.2 of the ISA specification explicitly requires
-     * this behaviour, while later revisions say that the kernel "should" use
-     * an SC instruction to force the yielding of a load reservation on a
-     * preemptive context switch. As a result, do both.
-     */
-    env->load_res = -1;
-}
-
-static target_ulong riscv_transformed_insn(CPURISCVState *env,
-                                           target_ulong insn,
-                                           target_ulong taddr)
-{
-    target_ulong xinsn = 0;
-    target_ulong access_rs1 = 0, access_imm = 0, access_size = 0;
-
-    /*
-     * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
-     * be uncompressed. The Quadrant 1 of RVC instruction space need
-     * not be transformed because these instructions won't generate
-     * any load/store trap.
-     */
-
-    if ((insn & 0x3) != 0x3) {
-        /* Transform 16bit instruction into 32bit instruction */
-        switch (GET_C_OP(insn)) {
-        case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
-            switch (GET_C_FUNC(insn)) {
-            case OPC_RISC_C_FUNC_FLD_LQ:
-                if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
-                    xinsn = OPC_RISC_FLD;
-                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_LD_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_LW: /* C.LW */
-                xinsn = OPC_RISC_LW;
-                xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
-                access_rs1 = GET_C_RS1S(insn);
-                access_imm = GET_C_LW_IMM(insn);
-                access_size = 4;
-                break;
-            case OPC_RISC_C_FUNC_FLW_LD:
-                if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
-                    xinsn = OPC_RISC_FLW;
-                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_LW_IMM(insn);
-                    access_size = 4;
-                } else { /* C.LD (RV64/RV128) */
-                    xinsn = OPC_RISC_LD;
-                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_LD_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_FSD_SQ:
-                if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */
-                    xinsn = OPC_RISC_FSD;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_SD_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_SW: /* C.SW */
-                xinsn = OPC_RISC_SW;
-                xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
-                access_rs1 = GET_C_RS1S(insn);
-                access_imm = GET_C_SW_IMM(insn);
-                access_size = 4;
-                break;
-            case OPC_RISC_C_FUNC_FSW_SD:
-                if (riscv_cpu_xlen(env) == 32) { /* C.FSW (RV32) */
-                    xinsn = OPC_RISC_FSW;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_SW_IMM(insn);
-                    access_size = 4;
-                } else { /* C.SD (RV64/RV128) */
-                    xinsn = OPC_RISC_SD;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
-                    access_rs1 = GET_C_RS1S(insn);
-                    access_imm = GET_C_SD_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            default:
-                break;
-            }
-            break;
-        case OPC_RISC_C_OP_QUAD2: /* Quadrant 2 */
-            switch (GET_C_FUNC(insn)) {
-            case OPC_RISC_C_FUNC_FLDSP_LQSP:
-                if (riscv_cpu_xlen(env) != 128) { /* C.FLDSP (RV32/64) */
-                    xinsn = OPC_RISC_FLD;
-                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_LDSP_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_LWSP: /* C.LWSP */
-                xinsn = OPC_RISC_LW;
-                xinsn = SET_RD(xinsn, GET_C_RD(insn));
-                access_rs1 = 2;
-                access_imm = GET_C_LWSP_IMM(insn);
-                access_size = 4;
-                break;
-            case OPC_RISC_C_FUNC_FLWSP_LDSP:
-                if (riscv_cpu_xlen(env) == 32) { /* C.FLWSP (RV32) */
-                    xinsn = OPC_RISC_FLW;
-                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_LWSP_IMM(insn);
-                    access_size = 4;
-                } else { /* C.LDSP (RV64/RV128) */
-                    xinsn = OPC_RISC_LD;
-                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_LDSP_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_FSDSP_SQSP:
-                if (riscv_cpu_xlen(env) != 128) { /* C.FSDSP (RV32/64) */
-                    xinsn = OPC_RISC_FSD;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_SDSP_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            case OPC_RISC_C_FUNC_SWSP: /* C.SWSP */
-                xinsn = OPC_RISC_SW;
-                xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
-                access_rs1 = 2;
-                access_imm = GET_C_SWSP_IMM(insn);
-                access_size = 4;
-                break;
-            case 7:
-                if (riscv_cpu_xlen(env) == 32) { /* C.FSWSP (RV32) */
-                    xinsn = OPC_RISC_FSW;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_SWSP_IMM(insn);
-                    access_size = 4;
-                } else { /* C.SDSP (RV64/RV128) */
-                    xinsn = OPC_RISC_SD;
-                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
-                    access_rs1 = 2;
-                    access_imm = GET_C_SDSP_IMM(insn);
-                    access_size = 8;
-                }
-                break;
-            default:
-                break;
-            }
-            break;
-        default:
-            break;
-        }
-
-        /*
-         * Clear Bit1 of transformed instruction to indicate that
-         * original insruction was a 16bit instruction
-         */
-        xinsn &= ~((target_ulong)0x2);
-    } else {
-        /* Transform 32bit (or wider) instructions */
-        switch (MASK_OP_MAJOR(insn)) {
-        case OPC_RISC_ATOMIC:
-            xinsn = insn;
-            access_rs1 = GET_RS1(insn);
-            access_size = 1 << GET_FUNCT3(insn);
-            break;
-        case OPC_RISC_LOAD:
-        case OPC_RISC_FP_LOAD:
-            xinsn = SET_I_IMM(insn, 0);
-            access_rs1 = GET_RS1(insn);
-            access_imm = GET_IMM(insn);
-            access_size = 1 << GET_FUNCT3(insn);
-            break;
-        case OPC_RISC_STORE:
-        case OPC_RISC_FP_STORE:
-            xinsn = SET_S_IMM(insn, 0);
-            access_rs1 = GET_RS1(insn);
-            access_imm = GET_STORE_IMM(insn);
-            access_size = 1 << GET_FUNCT3(insn);
-            break;
-        case OPC_RISC_SYSTEM:
-            if (MASK_OP_SYSTEM(insn) == OPC_RISC_HLVHSV) {
-                xinsn = insn;
-                access_rs1 = GET_RS1(insn);
-                access_size = 1 << ((GET_FUNCT7(insn) >> 1) & 0x3);
-                access_size = 1 << access_size;
-            }
-            break;
-        default:
-            break;
-        }
-    }
-
-    if (access_size) {
-        xinsn = SET_RS1(xinsn, (taddr - (env->gpr[access_rs1] + access_imm)) &
-                               (access_size - 1));
-    }
-
-    return xinsn;
-}
-
-/*
- * Handle Traps
- *
- * Adapted from Spike's processor_t::take_trap.
- *
- */
-void riscv_cpu_do_interrupt(CPUState *cs)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    bool write_gva = false;
-    uint64_t s;
-
-    /*
-     * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
-     * so we mask off the MSB and separate into trap type and cause.
-     */
-    bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
-    target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
-    uint64_t deleg = async ? env->mideleg : env->medeleg;
-    target_ulong tval = 0;
-    target_ulong tinst = 0;
-    target_ulong htval = 0;
-    target_ulong mtval2 = 0;
-
-    if  (cause == RISCV_EXCP_SEMIHOST) {
-        do_common_semihosting(cs);
-        env->pc += 4;
-        return;
-    }
-
-    if (!async) {
-        /* set tval to badaddr for traps with address information */
-        switch (cause) {
-        case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
-        case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
-        case RISCV_EXCP_LOAD_ADDR_MIS:
-        case RISCV_EXCP_STORE_AMO_ADDR_MIS:
-        case RISCV_EXCP_LOAD_ACCESS_FAULT:
-        case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
-        case RISCV_EXCP_LOAD_PAGE_FAULT:
-        case RISCV_EXCP_STORE_PAGE_FAULT:
-            write_gva = env->two_stage_lookup;
-            tval = env->badaddr;
-            if (env->two_stage_indirect_lookup) {
-                /*
-                 * special pseudoinstruction for G-stage fault taken while
-                 * doing VS-stage page table walk.
-                 */
-                tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000;
-            } else {
-                /*
-                 * The "Addr. Offset" field in transformed instruction is
-                 * non-zero only for misaligned access.
-                 */
-                tinst = riscv_transformed_insn(env, env->bins, tval);
-            }
-            break;
-        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
-        case RISCV_EXCP_INST_ADDR_MIS:
-        case RISCV_EXCP_INST_ACCESS_FAULT:
-        case RISCV_EXCP_INST_PAGE_FAULT:
-            write_gva = env->two_stage_lookup;
-            tval = env->badaddr;
-            if (env->two_stage_indirect_lookup) {
-                /*
-                 * special pseudoinstruction for G-stage fault taken while
-                 * doing VS-stage page table walk.
-                 */
-                tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000;
-            }
-            break;
-        case RISCV_EXCP_ILLEGAL_INST:
-        case RISCV_EXCP_VIRT_INSTRUCTION_FAULT:
-            tval = env->bins;
-            break;
-        case RISCV_EXCP_BREAKPOINT:
-            if (cs->watchpoint_hit) {
-                tval = cs->watchpoint_hit->hitaddr;
-                cs->watchpoint_hit = NULL;
-            }
-            break;
-        default:
-            break;
-        }
-        /* ecall is dispatched as one cause so translate based on mode */
-        if (cause == RISCV_EXCP_U_ECALL) {
-            assert(env->priv <= 3);
-
-            if (env->priv == PRV_M) {
-                cause = RISCV_EXCP_M_ECALL;
-            } else if (env->priv == PRV_S && env->virt_enabled) {
-                cause = RISCV_EXCP_VS_ECALL;
-            } else if (env->priv == PRV_S && !env->virt_enabled) {
-                cause = RISCV_EXCP_S_ECALL;
-            } else if (env->priv == PRV_U) {
-                cause = RISCV_EXCP_U_ECALL;
-            }
-        }
-    }
-
-    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval,
-                     riscv_cpu_get_trap_name(cause, async));
-
-    qemu_log_mask(CPU_LOG_INT,
-                  "%s: hart:"TARGET_FMT_ld", async:%d, cause:"TARGET_FMT_lx", "
-                  "epc:0x"TARGET_FMT_lx", tval:0x"TARGET_FMT_lx", desc=%s\n",
-                  __func__, env->mhartid, async, cause, env->pc, tval,
-                  riscv_cpu_get_trap_name(cause, async));
-
-    if (env->priv <= PRV_S &&
-            cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
-        /* handle the trap in S-mode */
-        if (riscv_has_ext(env, RVH)) {
-            uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
-
-            if (env->virt_enabled && ((hdeleg >> cause) & 1)) {
-                /* Trap to VS mode */
-                /*
-                 * See if we need to adjust cause. Yes if its VS mode interrupt
-                 * no if hypervisor has delegated one of hs mode's interrupt
-                 */
-                if (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT ||
-                    cause == IRQ_VS_EXT) {
-                    cause = cause - 1;
-                }
-                write_gva = false;
-            } else if (env->virt_enabled) {
-                /* Trap into HS mode, from virt */
-                riscv_cpu_swap_hypervisor_regs(env);
-                env->hstatus = set_field(env->hstatus, HSTATUS_SPVP,
-                                         env->priv);
-                env->hstatus = set_field(env->hstatus, HSTATUS_SPV, true);
-
-                htval = env->guest_phys_fault_addr;
-
-                riscv_cpu_set_virt_enabled(env, 0);
-            } else {
-                /* Trap into HS mode */
-                env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
-                htval = env->guest_phys_fault_addr;
-            }
-            env->hstatus = set_field(env->hstatus, HSTATUS_GVA, write_gva);
-        }
-
-        s = env->mstatus;
-        s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
-        s = set_field(s, MSTATUS_SPP, env->priv);
-        s = set_field(s, MSTATUS_SIE, 0);
-        env->mstatus = s;
-        env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
-        env->sepc = env->pc;
-        env->stval = tval;
-        env->htval = htval;
-        env->htinst = tinst;
-        env->pc = (env->stvec >> 2 << 2) +
-                  ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
-        riscv_cpu_set_mode(env, PRV_S);
-    } else {
-        /* handle the trap in M-mode */
-        if (riscv_has_ext(env, RVH)) {
-            if (env->virt_enabled) {
-                riscv_cpu_swap_hypervisor_regs(env);
-            }
-            env->mstatus = set_field(env->mstatus, MSTATUS_MPV,
-                                     env->virt_enabled);
-            if (env->virt_enabled && tval) {
-                env->mstatus = set_field(env->mstatus, MSTATUS_GVA, 1);
-            }
-
-            mtval2 = env->guest_phys_fault_addr;
-
-            /* Trapping to M mode, virt is disabled */
-            riscv_cpu_set_virt_enabled(env, 0);
-        }
-
-        s = env->mstatus;
-        s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
-        s = set_field(s, MSTATUS_MPP, env->priv);
-        s = set_field(s, MSTATUS_MIE, 0);
-        env->mstatus = s;
-        env->mcause = cause | ~(((target_ulong)-1) >> async);
-        env->mepc = env->pc;
-        env->mtval = tval;
-        env->mtval2 = mtval2;
-        env->mtinst = tinst;
-        env->pc = (env->mtvec >> 2 << 2) +
-                  ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
-        riscv_cpu_set_mode(env, PRV_M);
-    }
-
-    /*
-     * NOTE: it is not necessary to yield load reservations here. It is only
-     * necessary for an SC from "another hart" to cause a load reservation
-     * to be yielded. Refer to the memory consistency model section of the
-     * RISC-V ISA Specification.
-     */
-
-    env->two_stage_lookup = false;
-    env->two_stage_indirect_lookup = false;
-}
-
-#endif /* !CONFIG_USER_ONLY */
diff --git a/target/riscv/sysemu/cpu_helper.c b/target/riscv/sysemu/cpu_helper.c
new file mode 100644
index 0000000000..05a6b834fa
--- /dev/null
+++ b/target/riscv/sysemu/cpu_helper.c
@@ -0,0 +1,863 @@
+/*
+ * RISC-V CPU system helpers for QEMU.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "exec/exec-all.h"
+#include "cpu.h"
+#include "internals.h"
+#include "sysemu/cpu-timers.h"
+#include "sysemu/pmu.h"
+#include "sysemu/instmap.h"
+#include "semihosting/common-semi.h"
+#include "trace.h"
+
+
+/*
+ * The HS-mode is allowed to configure priority only for the
+ * following VS-mode local interrupts:
+ *
+ * 0  (Reserved interrupt, reads as zero)
+ * 1  Supervisor software interrupt
+ * 4  (Reserved interrupt, reads as zero)
+ * 5  Supervisor timer interrupt
+ * 8  (Reserved interrupt, reads as zero)
+ * 13 (Reserved interrupt)
+ * 14 "
+ * 15 "
+ * 16 "
+ * 17 "
+ * 18 "
+ * 19 "
+ * 20 "
+ * 21 "
+ * 22 "
+ * 23 "
+ */
+
+static const int hviprio_index2irq[] = {
+    0, 1, 4, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
+static const int hviprio_index2rdzero[] = {
+    1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero)
+{
+    if (index < 0 || ARRAY_SIZE(hviprio_index2irq) <= index) {
+        return -EINVAL;
+    }
+
+    if (out_irq) {
+        *out_irq = hviprio_index2irq[index];
+    }
+
+    if (out_rdzero) {
+        *out_rdzero = hviprio_index2rdzero[index];
+    }
+
+    return 0;
+}
+
+/*
+ * Default priorities of local interrupts are defined in the
+ * RISC-V Advanced Interrupt Architecture specification.
+ *
+ * ----------------------------------------------------------------
+ *  Default  |
+ *  Priority | Major Interrupt Numbers
+ * ----------------------------------------------------------------
+ *  Highest  | 47, 23, 46, 45, 22, 44,
+ *           | 43, 21, 42, 41, 20, 40
+ *           |
+ *           | 11 (0b),  3 (03),  7 (07)
+ *           |  9 (09),  1 (01),  5 (05)
+ *           | 12 (0c)
+ *           | 10 (0a),  2 (02),  6 (06)
+ *           |
+ *           | 39, 19, 38, 37, 18, 36,
+ *  Lowest   | 35, 17, 34, 33, 16, 32
+ * ----------------------------------------------------------------
+ */
+static const uint8_t default_iprio[64] = {
+    /* Custom interrupts 48 to 63 */
+    [63] = IPRIO_MMAXIPRIO,
+    [62] = IPRIO_MMAXIPRIO,
+    [61] = IPRIO_MMAXIPRIO,
+    [60] = IPRIO_MMAXIPRIO,
+    [59] = IPRIO_MMAXIPRIO,
+    [58] = IPRIO_MMAXIPRIO,
+    [57] = IPRIO_MMAXIPRIO,
+    [56] = IPRIO_MMAXIPRIO,
+    [55] = IPRIO_MMAXIPRIO,
+    [54] = IPRIO_MMAXIPRIO,
+    [53] = IPRIO_MMAXIPRIO,
+    [52] = IPRIO_MMAXIPRIO,
+    [51] = IPRIO_MMAXIPRIO,
+    [50] = IPRIO_MMAXIPRIO,
+    [49] = IPRIO_MMAXIPRIO,
+    [48] = IPRIO_MMAXIPRIO,
+
+    /* Custom interrupts 24 to 31 */
+    [31] = IPRIO_MMAXIPRIO,
+    [30] = IPRIO_MMAXIPRIO,
+    [29] = IPRIO_MMAXIPRIO,
+    [28] = IPRIO_MMAXIPRIO,
+    [27] = IPRIO_MMAXIPRIO,
+    [26] = IPRIO_MMAXIPRIO,
+    [25] = IPRIO_MMAXIPRIO,
+    [24] = IPRIO_MMAXIPRIO,
+
+    [47] = IPRIO_DEFAULT_UPPER,
+    [23] = IPRIO_DEFAULT_UPPER + 1,
+    [46] = IPRIO_DEFAULT_UPPER + 2,
+    [45] = IPRIO_DEFAULT_UPPER + 3,
+    [22] = IPRIO_DEFAULT_UPPER + 4,
+    [44] = IPRIO_DEFAULT_UPPER + 5,
+
+    [43] = IPRIO_DEFAULT_UPPER + 6,
+    [21] = IPRIO_DEFAULT_UPPER + 7,
+    [42] = IPRIO_DEFAULT_UPPER + 8,
+    [41] = IPRIO_DEFAULT_UPPER + 9,
+    [20] = IPRIO_DEFAULT_UPPER + 10,
+    [40] = IPRIO_DEFAULT_UPPER + 11,
+
+    [11] = IPRIO_DEFAULT_M,
+    [3]  = IPRIO_DEFAULT_M + 1,
+    [7]  = IPRIO_DEFAULT_M + 2,
+
+    [9]  = IPRIO_DEFAULT_S,
+    [1]  = IPRIO_DEFAULT_S + 1,
+    [5]  = IPRIO_DEFAULT_S + 2,
+
+    [12] = IPRIO_DEFAULT_SGEXT,
+
+    [10] = IPRIO_DEFAULT_VS,
+    [2]  = IPRIO_DEFAULT_VS + 1,
+    [6]  = IPRIO_DEFAULT_VS + 2,
+
+    [39] = IPRIO_DEFAULT_LOWER,
+    [19] = IPRIO_DEFAULT_LOWER + 1,
+    [38] = IPRIO_DEFAULT_LOWER + 2,
+    [37] = IPRIO_DEFAULT_LOWER + 3,
+    [18] = IPRIO_DEFAULT_LOWER + 4,
+    [36] = IPRIO_DEFAULT_LOWER + 5,
+
+    [35] = IPRIO_DEFAULT_LOWER + 6,
+    [17] = IPRIO_DEFAULT_LOWER + 7,
+    [34] = IPRIO_DEFAULT_LOWER + 8,
+    [33] = IPRIO_DEFAULT_LOWER + 9,
+    [16] = IPRIO_DEFAULT_LOWER + 10,
+    [32] = IPRIO_DEFAULT_LOWER + 11,
+};
+
+uint8_t riscv_cpu_default_priority(int irq)
+{
+    if (irq < 0 || irq > 63) {
+        return IPRIO_MMAXIPRIO;
+    }
+
+    return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
+};
+
+int riscv_cpu_pending_to_irq(CPURISCVState *env,
+                             int extirq, unsigned int extirq_def_prio,
+                             uint64_t pending, uint8_t *iprio)
+{
+    int irq, best_irq = RISCV_EXCP_NONE;
+    unsigned int prio, best_prio = UINT_MAX;
+
+    if (!pending) {
+        return RISCV_EXCP_NONE;
+    }
+
+    irq = ctz64(pending);
+    if (!((extirq == IRQ_M_EXT) ? riscv_cpu_cfg(env)->ext_smaia :
+                                  riscv_cpu_cfg(env)->ext_ssaia)) {
+        return irq;
+    }
+
+    pending = pending >> irq;
+    while (pending) {
+        prio = iprio[irq];
+        if (!prio) {
+            if (irq == extirq) {
+                prio = extirq_def_prio;
+            } else {
+                prio = (riscv_cpu_default_priority(irq) < extirq_def_prio) ?
+                       1 : IPRIO_MMAXIPRIO;
+            }
+        }
+        if ((pending & 0x1) && (prio <= best_prio)) {
+            best_irq = irq;
+            best_prio = prio;
+        }
+        irq++;
+        pending = pending >> 1;
+    }
+
+    return best_irq;
+}
+
+uint64_t riscv_cpu_all_pending(CPURISCVState *env)
+{
+    uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
+    uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
+    uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0;
+
+    return (env->mip | vsgein | vstip) & env->mie;
+}
+
+int riscv_cpu_mirq_pending(CPURISCVState *env)
+{
+    uint64_t irqs = riscv_cpu_all_pending(env) & ~env->mideleg &
+                    ~(MIP_SGEIP | MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
+
+    return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
+                                    irqs, env->miprio);
+}
+
+int riscv_cpu_sirq_pending(CPURISCVState *env)
+{
+    uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
+                    ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
+
+    return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
+                                    irqs, env->siprio);
+}
+
+int riscv_cpu_vsirq_pending(CPURISCVState *env)
+{
+    uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
+                    (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
+
+    return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
+                                    irqs >> 1, env->hviprio);
+}
+
+/* Return true is floating point support is currently enabled */
+bool riscv_cpu_fp_enabled(CPURISCVState *env)
+{
+    if (env->mstatus & MSTATUS_FS) {
+        if (env->virt_enabled && !(env->mstatus_hs & MSTATUS_FS)) {
+            return false;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+/* Return true is vector support is currently enabled */
+bool riscv_cpu_vector_enabled(CPURISCVState *env)
+{
+    if (env->mstatus & MSTATUS_VS) {
+        if (env->virt_enabled && !(env->mstatus_hs & MSTATUS_VS)) {
+            return false;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
+{
+    uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM |
+                            MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
+                            MSTATUS64_UXL | MSTATUS_VS;
+
+    if (riscv_has_ext(env, RVF)) {
+        mstatus_mask |= MSTATUS_FS;
+    }
+    bool current_virt = env->virt_enabled;
+
+    g_assert(riscv_has_ext(env, RVH));
+
+    if (current_virt) {
+        /* Current V=1 and we are about to change to V=0 */
+        env->vsstatus = env->mstatus & mstatus_mask;
+        env->mstatus &= ~mstatus_mask;
+        env->mstatus |= env->mstatus_hs;
+
+        env->vstvec = env->stvec;
+        env->stvec = env->stvec_hs;
+
+        env->vsscratch = env->sscratch;
+        env->sscratch = env->sscratch_hs;
+
+        env->vsepc = env->sepc;
+        env->sepc = env->sepc_hs;
+
+        env->vscause = env->scause;
+        env->scause = env->scause_hs;
+
+        env->vstval = env->stval;
+        env->stval = env->stval_hs;
+
+        env->vsatp = env->satp;
+        env->satp = env->satp_hs;
+    } else {
+        /* Current V=0 and we are about to change to V=1 */
+        env->mstatus_hs = env->mstatus & mstatus_mask;
+        env->mstatus &= ~mstatus_mask;
+        env->mstatus |= env->vsstatus;
+
+        env->stvec_hs = env->stvec;
+        env->stvec = env->vstvec;
+
+        env->sscratch_hs = env->sscratch;
+        env->sscratch = env->vsscratch;
+
+        env->sepc_hs = env->sepc;
+        env->sepc = env->vsepc;
+
+        env->scause_hs = env->scause;
+        env->scause = env->vscause;
+
+        env->stval_hs = env->stval;
+        env->stval = env->vstval;
+
+        env->satp_hs = env->satp;
+        env->satp = env->vsatp;
+    }
+}
+
+target_ulong riscv_cpu_get_geilen(CPURISCVState *env)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return 0;
+    }
+
+    return env->geilen;
+}
+
+void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return;
+    }
+
+    if (geilen > (TARGET_LONG_BITS - 1)) {
+        return;
+    }
+
+    env->geilen = geilen;
+}
+
+/* This function can only be called to set virt when RVH is enabled */
+void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
+{
+    /* Flush the TLB on all virt mode changes. */
+    if (env->virt_enabled != enable) {
+        tlb_flush(env_cpu(env));
+    }
+
+    env->virt_enabled = enable;
+
+    if (enable) {
+        /*
+         * The guest external interrupts from an interrupt controller are
+         * delivered only when the Guest/VM is running (i.e. V=1). This means
+         * any guest external interrupt which is triggered while the Guest/VM
+         * is not running (i.e. V=0) will be missed on QEMU resulting in guest
+         * with sluggish response to serial console input and other I/O events.
+         *
+         * To solve this, we check and inject interrupt after setting V=1.
+         */
+        riscv_cpu_update_mip(env, 0, 0);
+    }
+}
+
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
+{
+    CPURISCVState *env = &cpu->env;
+    if (env->miclaim & interrupts) {
+        return -1;
+    } else {
+        env->miclaim |= interrupts;
+        return 0;
+    }
+}
+
+uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
+                              uint64_t value)
+{
+    CPUState *cs = env_cpu(env);
+    uint64_t gein, vsgein = 0, vstip = 0, old = env->mip;
+
+    if (env->virt_enabled) {
+        gein = get_field(env->hstatus, HSTATUS_VGEIN);
+        vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
+    }
+
+    vstip = env->vstime_irq ? MIP_VSTIP : 0;
+
+    QEMU_IOTHREAD_LOCK_GUARD();
+
+    env->mip = (env->mip & ~mask) | (value & mask);
+
+    if (env->mip | vsgein | vstip) {
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
+
+    return old;
+}
+
+void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
+                             void *arg)
+{
+    env->rdtime_fn = fn;
+    env->rdtime_fn_arg = arg;
+}
+
+void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
+                                   int (*rmw_fn)(void *arg,
+                                                 target_ulong reg,
+                                                 target_ulong *val,
+                                                 target_ulong new_val,
+                                                 target_ulong write_mask),
+                                   void *rmw_fn_arg)
+{
+    if (priv <= PRV_M) {
+        env->aia_ireg_rmw_fn[priv] = rmw_fn;
+        env->aia_ireg_rmw_fn_arg[priv] = rmw_fn_arg;
+    }
+}
+
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
+{
+    g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
+
+    if (icount_enabled() && newpriv != env->priv) {
+        riscv_itrigger_update_priv(env);
+    }
+    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
+    env->priv = newpriv;
+    env->xl = cpu_recompute_xl(env);
+    riscv_cpu_update_mask(env);
+
+    /*
+     * Clear the load reservation - otherwise a reservation placed in one
+     * context/process can be used by another, resulting in an SC succeeding
+     * incorrectly. Version 2.2 of the ISA specification explicitly requires
+     * this behaviour, while later revisions say that the kernel "should" use
+     * an SC instruction to force the yielding of a load reservation on a
+     * preemptive context switch. As a result, do both.
+     */
+    env->load_res = -1;
+}
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+                                           target_ulong insn,
+                                           target_ulong taddr)
+{
+    target_ulong xinsn = 0;
+    target_ulong access_rs1 = 0, access_imm = 0, access_size = 0;
+
+    /*
+     * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+     * be uncompressed. The Quadrant 1 of RVC instruction space need
+     * not be transformed because these instructions won't generate
+     * any load/store trap.
+     */
+
+    if ((insn & 0x3) != 0x3) {
+        /* Transform 16bit instruction into 32bit instruction */
+        switch (GET_C_OP(insn)) {
+        case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+            switch (GET_C_FUNC(insn)) {
+            case OPC_RISC_C_FUNC_FLD_LQ:
+                if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+                    xinsn = OPC_RISC_FLD;
+                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_LD_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_LW: /* C.LW */
+                xinsn = OPC_RISC_LW;
+                xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+                access_rs1 = GET_C_RS1S(insn);
+                access_imm = GET_C_LW_IMM(insn);
+                access_size = 4;
+                break;
+            case OPC_RISC_C_FUNC_FLW_LD:
+                if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
+                    xinsn = OPC_RISC_FLW;
+                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_LW_IMM(insn);
+                    access_size = 4;
+                } else { /* C.LD (RV64/RV128) */
+                    xinsn = OPC_RISC_LD;
+                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_LD_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_FSD_SQ:
+                if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */
+                    xinsn = OPC_RISC_FSD;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_SD_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_SW: /* C.SW */
+                xinsn = OPC_RISC_SW;
+                xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
+                access_rs1 = GET_C_RS1S(insn);
+                access_imm = GET_C_SW_IMM(insn);
+                access_size = 4;
+                break;
+            case OPC_RISC_C_FUNC_FSW_SD:
+                if (riscv_cpu_xlen(env) == 32) { /* C.FSW (RV32) */
+                    xinsn = OPC_RISC_FSW;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_SW_IMM(insn);
+                    access_size = 4;
+                } else { /* C.SD (RV64/RV128) */
+                    xinsn = OPC_RISC_SD;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
+                    access_rs1 = GET_C_RS1S(insn);
+                    access_imm = GET_C_SD_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        case OPC_RISC_C_OP_QUAD2: /* Quadrant 2 */
+            switch (GET_C_FUNC(insn)) {
+            case OPC_RISC_C_FUNC_FLDSP_LQSP:
+                if (riscv_cpu_xlen(env) != 128) { /* C.FLDSP (RV32/64) */
+                    xinsn = OPC_RISC_FLD;
+                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_LDSP_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_LWSP: /* C.LWSP */
+                xinsn = OPC_RISC_LW;
+                xinsn = SET_RD(xinsn, GET_C_RD(insn));
+                access_rs1 = 2;
+                access_imm = GET_C_LWSP_IMM(insn);
+                access_size = 4;
+                break;
+            case OPC_RISC_C_FUNC_FLWSP_LDSP:
+                if (riscv_cpu_xlen(env) == 32) { /* C.FLWSP (RV32) */
+                    xinsn = OPC_RISC_FLW;
+                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_LWSP_IMM(insn);
+                    access_size = 4;
+                } else { /* C.LDSP (RV64/RV128) */
+                    xinsn = OPC_RISC_LD;
+                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_LDSP_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_FSDSP_SQSP:
+                if (riscv_cpu_xlen(env) != 128) { /* C.FSDSP (RV32/64) */
+                    xinsn = OPC_RISC_FSD;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_SDSP_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            case OPC_RISC_C_FUNC_SWSP: /* C.SWSP */
+                xinsn = OPC_RISC_SW;
+                xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
+                access_rs1 = 2;
+                access_imm = GET_C_SWSP_IMM(insn);
+                access_size = 4;
+                break;
+            case 7:
+                if (riscv_cpu_xlen(env) == 32) { /* C.FSWSP (RV32) */
+                    xinsn = OPC_RISC_FSW;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_SWSP_IMM(insn);
+                    access_size = 4;
+                } else { /* C.SDSP (RV64/RV128) */
+                    xinsn = OPC_RISC_SD;
+                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
+                    access_rs1 = 2;
+                    access_imm = GET_C_SDSP_IMM(insn);
+                    access_size = 8;
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+
+        /*
+         * Clear Bit1 of transformed instruction to indicate that
+         * original insruction was a 16bit instruction
+         */
+        xinsn &= ~((target_ulong)0x2);
+    } else {
+        /* Transform 32bit (or wider) instructions */
+        switch (MASK_OP_MAJOR(insn)) {
+        case OPC_RISC_ATOMIC:
+            xinsn = insn;
+            access_rs1 = GET_RS1(insn);
+            access_size = 1 << GET_FUNCT3(insn);
+            break;
+        case OPC_RISC_LOAD:
+        case OPC_RISC_FP_LOAD:
+            xinsn = SET_I_IMM(insn, 0);
+            access_rs1 = GET_RS1(insn);
+            access_imm = GET_IMM(insn);
+            access_size = 1 << GET_FUNCT3(insn);
+            break;
+        case OPC_RISC_STORE:
+        case OPC_RISC_FP_STORE:
+            xinsn = SET_S_IMM(insn, 0);
+            access_rs1 = GET_RS1(insn);
+            access_imm = GET_STORE_IMM(insn);
+            access_size = 1 << GET_FUNCT3(insn);
+            break;
+        case OPC_RISC_SYSTEM:
+            if (MASK_OP_SYSTEM(insn) == OPC_RISC_HLVHSV) {
+                xinsn = insn;
+                access_rs1 = GET_RS1(insn);
+                access_size = 1 << ((GET_FUNCT7(insn) >> 1) & 0x3);
+                access_size = 1 << access_size;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (access_size) {
+        xinsn = SET_RS1(xinsn, (taddr - (env->gpr[access_rs1] + access_imm)) &
+                               (access_size - 1));
+    }
+
+    return xinsn;
+}
+
+/*
+ * Handle Traps
+ *
+ * Adapted from Spike's processor_t::take_trap.
+ *
+ */
+void riscv_cpu_do_interrupt(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    bool write_gva = false;
+    uint64_t s;
+
+    /*
+     * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
+     * so we mask off the MSB and separate into trap type and cause.
+     */
+    bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
+    target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
+    uint64_t deleg = async ? env->mideleg : env->medeleg;
+    target_ulong tval = 0;
+    target_ulong tinst = 0;
+    target_ulong htval = 0;
+    target_ulong mtval2 = 0;
+
+    if  (cause == RISCV_EXCP_SEMIHOST) {
+        do_common_semihosting(cs);
+        env->pc += 4;
+        return;
+    }
+
+    if (!async) {
+        /* set tval to badaddr for traps with address information */
+        switch (cause) {
+        case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
+        case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
+        case RISCV_EXCP_LOAD_ADDR_MIS:
+        case RISCV_EXCP_STORE_AMO_ADDR_MIS:
+        case RISCV_EXCP_LOAD_ACCESS_FAULT:
+        case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
+        case RISCV_EXCP_LOAD_PAGE_FAULT:
+        case RISCV_EXCP_STORE_PAGE_FAULT:
+            write_gva = env->two_stage_lookup;
+            tval = env->badaddr;
+            if (env->two_stage_indirect_lookup) {
+                /*
+                 * special pseudoinstruction for G-stage fault taken while
+                 * doing VS-stage page table walk.
+                 */
+                tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000;
+            } else {
+                /*
+                 * The "Addr. Offset" field in transformed instruction is
+                 * non-zero only for misaligned access.
+                 */
+                tinst = riscv_transformed_insn(env, env->bins, tval);
+            }
+            break;
+        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
+        case RISCV_EXCP_INST_ADDR_MIS:
+        case RISCV_EXCP_INST_ACCESS_FAULT:
+        case RISCV_EXCP_INST_PAGE_FAULT:
+            write_gva = env->two_stage_lookup;
+            tval = env->badaddr;
+            if (env->two_stage_indirect_lookup) {
+                /*
+                 * special pseudoinstruction for G-stage fault taken while
+                 * doing VS-stage page table walk.
+                 */
+                tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000;
+            }
+            break;
+        case RISCV_EXCP_ILLEGAL_INST:
+        case RISCV_EXCP_VIRT_INSTRUCTION_FAULT:
+            tval = env->bins;
+            break;
+        case RISCV_EXCP_BREAKPOINT:
+            if (cs->watchpoint_hit) {
+                tval = cs->watchpoint_hit->hitaddr;
+                cs->watchpoint_hit = NULL;
+            }
+            break;
+        default:
+            break;
+        }
+        /* ecall is dispatched as one cause so translate based on mode */
+        if (cause == RISCV_EXCP_U_ECALL) {
+            assert(env->priv <= 3);
+
+            if (env->priv == PRV_M) {
+                cause = RISCV_EXCP_M_ECALL;
+            } else if (env->priv == PRV_S && env->virt_enabled) {
+                cause = RISCV_EXCP_VS_ECALL;
+            } else if (env->priv == PRV_S && !env->virt_enabled) {
+                cause = RISCV_EXCP_S_ECALL;
+            } else if (env->priv == PRV_U) {
+                cause = RISCV_EXCP_U_ECALL;
+            }
+        }
+    }
+
+    trace_riscv_trap(env->mhartid, async, cause, env->pc, tval,
+                     riscv_cpu_get_trap_name(cause, async));
+
+    qemu_log_mask(CPU_LOG_INT,
+                  "%s: hart:"TARGET_FMT_ld", async:%d, cause:"TARGET_FMT_lx", "
+                  "epc:0x"TARGET_FMT_lx", tval:0x"TARGET_FMT_lx", desc=%s\n",
+                  __func__, env->mhartid, async, cause, env->pc, tval,
+                  riscv_cpu_get_trap_name(cause, async));
+
+    if (env->priv <= PRV_S &&
+            cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
+        /* handle the trap in S-mode */
+        if (riscv_has_ext(env, RVH)) {
+            uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
+
+            if (env->virt_enabled && ((hdeleg >> cause) & 1)) {
+                /* Trap to VS mode */
+                /*
+                 * See if we need to adjust cause. Yes if its VS mode interrupt
+                 * no if hypervisor has delegated one of hs mode's interrupt
+                 */
+                if (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT ||
+                    cause == IRQ_VS_EXT) {
+                    cause = cause - 1;
+                }
+                write_gva = false;
+            } else if (env->virt_enabled) {
+                /* Trap into HS mode, from virt */
+                riscv_cpu_swap_hypervisor_regs(env);
+                env->hstatus = set_field(env->hstatus, HSTATUS_SPVP,
+                                         env->priv);
+                env->hstatus = set_field(env->hstatus, HSTATUS_SPV, true);
+
+                htval = env->guest_phys_fault_addr;
+
+                riscv_cpu_set_virt_enabled(env, 0);
+            } else {
+                /* Trap into HS mode */
+                env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
+                htval = env->guest_phys_fault_addr;
+            }
+            env->hstatus = set_field(env->hstatus, HSTATUS_GVA, write_gva);
+        }
+
+        s = env->mstatus;
+        s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
+        s = set_field(s, MSTATUS_SPP, env->priv);
+        s = set_field(s, MSTATUS_SIE, 0);
+        env->mstatus = s;
+        env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+        env->sepc = env->pc;
+        env->stval = tval;
+        env->htval = htval;
+        env->htinst = tinst;
+        env->pc = (env->stvec >> 2 << 2) +
+                  ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
+        riscv_cpu_set_mode(env, PRV_S);
+    } else {
+        /* handle the trap in M-mode */
+        if (riscv_has_ext(env, RVH)) {
+            if (env->virt_enabled) {
+                riscv_cpu_swap_hypervisor_regs(env);
+            }
+            env->mstatus = set_field(env->mstatus, MSTATUS_MPV,
+                                     env->virt_enabled);
+            if (env->virt_enabled && tval) {
+                env->mstatus = set_field(env->mstatus, MSTATUS_GVA, 1);
+            }
+
+            mtval2 = env->guest_phys_fault_addr;
+
+            /* Trapping to M mode, virt is disabled */
+            riscv_cpu_set_virt_enabled(env, 0);
+        }
+
+        s = env->mstatus;
+        s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
+        s = set_field(s, MSTATUS_MPP, env->priv);
+        s = set_field(s, MSTATUS_MIE, 0);
+        env->mstatus = s;
+        env->mcause = cause | ~(((target_ulong)-1) >> async);
+        env->mepc = env->pc;
+        env->mtval = tval;
+        env->mtval2 = mtval2;
+        env->mtinst = tinst;
+        env->pc = (env->mtvec >> 2 << 2) +
+                  ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+        riscv_cpu_set_mode(env, PRV_M);
+    }
+
+    /*
+     * NOTE: it is not necessary to yield load reservations here. It is only
+     * necessary for an SC from "another hart" to cause a load reservation
+     * to be yielded. Refer to the memory consistency model section of the
+     * RISC-V ISA Specification.
+     */
+
+    env->two_stage_lookup = false;
+    env->two_stage_indirect_lookup = false;
+}
diff --git a/target/riscv/sysemu/meson.build b/target/riscv/sysemu/meson.build
index e902ba2dad..3573fdbe1f 100644
--- a/target/riscv/sysemu/meson.build
+++ b/target/riscv/sysemu/meson.build
@@ -1,5 +1,6 @@
 riscv_system_ss.add(files(
   'arch_dump.c',
+  'cpu_helper.c',
   'debug.c',
   'machine.c',
   'monitor.c',
-- 
2.38.1



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

* [PATCH v3 15/16] target/riscv: Restrict TCG-specific prototype declarations
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (13 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 14/16] target/riscv: Move sysemu-specific code to sysemu/cpu_helper.c Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  2023-07-11 12:14 ` [PATCH v3 16/16] gitlab-ci.d/crossbuilds: Add KVM riscv64 cross-build jobs Philippe Mathieu-Daudé
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu.h |  3 +++
 target/riscv/cpu.c | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6d78e59214..d2a9764317 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -479,7 +479,10 @@ RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
 
 void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
 
+#ifdef CONFIG_TCG
 void riscv_translate_init(void);
+#endif
+
 G_NORETURN void riscv_raise_exception(CPURISCVState *env,
                                       uint32_t exception, uintptr_t pc);
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 91433f3041..c96819daf7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -38,7 +38,9 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "fpu/softfloat-helpers.h"
+#ifdef CONFIG_TCG
 #include "tcg/tcg.h"
+#endif
 
 /* RISC-V CPU definitions */
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
@@ -782,6 +784,7 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
     return env->pc;
 }
 
+#ifdef CONFIG_TCG
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
                                           const TranslationBlock *tb)
 {
@@ -799,6 +802,7 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs,
         }
     }
 }
+#endif
 
 static bool riscv_cpu_has_work(CPUState *cs)
 {
@@ -815,6 +819,7 @@ static bool riscv_cpu_has_work(CPUState *cs)
 #endif
 }
 
+#ifdef CONFIG_TCG
 static void riscv_restore_state_to_opc(CPUState *cs,
                                        const TranslationBlock *tb,
                                        const uint64_t *data)
@@ -837,6 +842,7 @@ static void riscv_restore_state_to_opc(CPUState *cs,
     }
     env->bins = data[1];
 }
+#endif
 
 static void riscv_cpu_reset_hold(Object *obj)
 {
@@ -1991,6 +1997,8 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
 };
 #endif
 
+#ifdef CONFIG_TCG
+
 #include "hw/core/tcg-cpu-ops.h"
 
 static const struct TCGCPUOps riscv_tcg_ops = {
@@ -2009,6 +2017,7 @@ static const struct TCGCPUOps riscv_tcg_ops = {
     .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
 #endif /* !CONFIG_USER_ONLY */
 };
+#endif /* CONFIG_TCG */
 
 static bool riscv_cpu_is_dynamic(Object *cpu_obj)
 {
@@ -2152,7 +2161,9 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
 #endif
     cc->gdb_arch_name = riscv_gdb_arch_name;
     cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
+#ifdef CONFIG_TCG
     cc->tcg_ops = &riscv_tcg_ops;
+#endif /* CONFIG_TCG */
 
     object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid,
                               cpu_set_mvendorid, NULL, NULL);
-- 
2.38.1



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

* [PATCH v3 16/16] gitlab-ci.d/crossbuilds: Add KVM riscv64 cross-build jobs
  2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
                   ` (14 preceding siblings ...)
  2023-07-11 12:14 ` [PATCH v3 15/16] target/riscv: Restrict TCG-specific prototype declarations Philippe Mathieu-Daudé
@ 2023-07-11 12:14 ` Philippe Mathieu-Daudé
  15 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-11 12:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Daniel Henrique Barboza, Philippe Mathieu-Daudé

Add a new job to cross-build the riscv64 target without
the TCG accelerator (IOW: only KVM accelerator enabled).

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 .gitlab-ci.d/crossbuilds.yml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
index 84ff2f6d2b..e311744880 100644
--- a/.gitlab-ci.d/crossbuilds.yml
+++ b/.gitlab-ci.d/crossbuilds.yml
@@ -129,6 +129,14 @@ cross-riscv64-user:
   variables:
     IMAGE: debian-riscv64-cross
 
+cross-riscv64-kvm-only:
+  extends: .cross_accel_build_job
+  needs:
+    job: riscv64-debian-cross-container
+  variables:
+    IMAGE: debian-riscv64-cross
+    EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
+
 cross-s390x-system:
   extends: .cross_system_build_job
   needs:
-- 
2.38.1



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

* Re: [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation
  2023-07-11 12:14 ` [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation Philippe Mathieu-Daudé
@ 2023-07-12 15:18   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-12 15:18 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: qemu-riscv, Alistair Francis

Phil,


This patch breaks the build for me. Applied on top of master:


FAILED: libqemu-riscv64-linux-user.fa.p/target_riscv_cpu.c.o
cc -m64 -mcx16 -Ilibqemu-riscv64-linux-user.fa.p -I. -I.. -Itarget/riscv -I../target/riscv -I../common-user/host/x86_64 -I../linux-user/include/host/x86_64 -I../linux-user/include -Ilinux-user -I../linux-user -I../linux-user/riscv -Iqapi -Itrace -Iui -Iui/shader -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -fdiagnostics-color=auto -Wall -Winvalid-pch -Werror -std=gnu11 -O2 -g -fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Wundef -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wold-style-declaration -Wold-style-definition -Wtype-limits -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wempty-body -Wnested-externs -Wendif-labels -Wexpansion-to-defined -Wimplicit-fallthrough=2 -Wmissing-format-attribute -Wno-missing-include-dirs -Wno-shift-negative-value -Wno-psabi -isystem /home/danielhb/work/qemu/linux-headers -isystem linux-headers -iquote . -iquote /home/danielhb/work/qemu -iquote /home/danielhb/work/qemu/include -iquote /home/danielhb/work/qemu/host/include/x86_64 -iquote /home/danielhb/work/qemu/host/include/generic -iquote /home/danielhb/work/qemu/tcg/i386 -pthread -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fno-common -fwrapv -fPIE -isystem../linux-headers -isystemlinux-headers -DNEED_CPU_H '-DCONFIG_TARGET="riscv64-linux-user-config-target.h"' '-DCONFIG_DEVICES="riscv64-linux-user-config-devices.h"' -MD -MQ libqemu-riscv64-linux-user.fa.p/target_riscv_cpu.c.o -MF libqemu-riscv64-linux-user.fa.p/target_riscv_cpu.c.o.d -o libqemu-riscv64-linux-user.fa.p/target_riscv_cpu.c.o -c ../target/riscv/cpu.c
../target/riscv/cpu.c: In function ‘riscv_cpu_realize’:
../target/riscv/cpu.c:1461:9: error: implicit declaration of function ‘tcg_enabled’ [-Werror=implicit-function-declaration]
  1461 |     if (tcg_enabled()) {
       |         ^~~~~~~~~~~
../target/riscv/cpu.c:1461:9: error: nested extern declaration of ‘tcg_enabled’ [-Werror=nested-externs]
cc1: all warnings being treated as errors


I added this 'tcg_enabled()' call in commit eddabb6b8, "target/riscv: skip
features setup for KVM CPUs", back in that review where we discussed whether
this should be a kvm_enabled() check or not.

The build breaks because we're moving the "sysemu/kvm.h" include away from the
file.

I added a patch on top of the series to fix the break:

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c96819daf7..78feb68e86 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -26,7 +26,6 @@
  #ifndef CONFIG_USER_ONLY
  #include "sysemu/pmu.h"
  #include "sysemu/time_helper.h"
-#include "sysemu/tcg.h"
  #include "sysemu/kvm.h"
  #include "sysemu/kvm_riscv.h"
  #endif
@@ -39,6 +38,7 @@
  #include "migration/vmstate.h"
  #include "fpu/softfloat-helpers.h"
  #ifdef CONFIG_TCG
+#include "sysemu/tcg.h"
  #include "tcg/tcg.h"
  #endif
  
@@ -1468,6 +1468,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
          return;
      }
  
+#ifdef CONFIG_TCG
      if (tcg_enabled()) {
          riscv_cpu_realize_tcg(dev, &local_err);
          if (local_err != NULL) {
@@ -1475,6 +1476,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
              return;
          }
      }
+#endif
  
      riscv_cpu_finalize_features(cpu, &local_err);

I'm unsure if this is the right fix for what you're aiming to do here though.


Thanks,


Daniel


On 7/11/23 09:14, Philippe Mathieu-Daudé wrote:
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> Acked-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>   target/riscv/cpu.c        | 10 ++++++----
>   target/riscv/cpu_helper.c |  2 ++
>   target/riscv/csr.c        |  2 ++
>   3 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 9339c0241d..5712a54404 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -23,9 +23,14 @@
>   #include "qemu/log.h"
>   #include "cpu.h"
>   #include "cpu_vendorid.h"
> +#ifndef CONFIG_USER_ONLY
>   #include "pmu.h"
> -#include "internals.h"
>   #include "time_helper.h"
> +#include "sysemu/tcg.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_riscv.h"
> +#endif
> +#include "internals.h"
>   #include "exec/exec-all.h"
>   #include "qapi/error.h"
>   #include "qapi/visitor.h"
> @@ -33,9 +38,6 @@
>   #include "hw/qdev-properties.h"
>   #include "migration/vmstate.h"
>   #include "fpu/softfloat-helpers.h"
> -#include "sysemu/kvm.h"
> -#include "sysemu/tcg.h"
> -#include "kvm_riscv.h"
>   #include "tcg/tcg.h"
>   
>   /* RISC-V CPU definitions */
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 9f611d89bb..e8b7f70be3 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -28,7 +28,9 @@
>   #include "tcg/tcg-op.h"
>   #include "trace.h"
>   #include "semihosting/common-semi.h"
> +#ifndef CONFIG_USER_ONLY
>   #include "sysemu/cpu-timers.h"
> +#endif
>   #include "cpu_bits.h"
>   #include "debug.h"
>   #include "tcg/oversized-guest.h"
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index ea7585329e..e5737dcf58 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -21,8 +21,10 @@
>   #include "qemu/log.h"
>   #include "qemu/timer.h"
>   #include "cpu.h"
> +#ifndef CONFIG_USER_ONLY
>   #include "pmu.h"
>   #include "time_helper.h"
> +#endif
>   #include "qemu/main-loop.h"
>   #include "exec/exec-all.h"
>   #include "exec/tb-flush.h"

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

* Re: [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu
  2023-07-11 12:14 ` [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu Philippe Mathieu-Daudé
@ 2023-07-14  3:17   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-14  3:17 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:20 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> riscv_cpu_do_interrupt() is not reachable on user emulation.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/cpu.h        | 5 +++--
>  target/riscv/cpu_helper.c | 7 ++-----
>  2 files changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index dba78db644..0602b948d4 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -416,7 +416,6 @@ extern const char * const riscv_int_regnamesh[];
>  extern const char * const riscv_fpr_regnames[];
>
>  const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
> -void riscv_cpu_do_interrupt(CPUState *cpu);
>  int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
>                                 int cpuid, DumpState *s);
>  int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
> @@ -449,6 +448,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
>  #define cpu_mmu_index riscv_cpu_mmu_index
>
>  #ifndef CONFIG_USER_ONLY
> +void riscv_cpu_do_interrupt(CPUState *cpu);
>  void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
>                                       vaddr addr, unsigned size,
>                                       MMUAccessType access_type,
> @@ -472,7 +472,8 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
>                                     void *rmw_fn_arg);
>
>  RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
> -#endif
> +#endif /* !CONFIG_USER_ONLY */
> +
>  void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
>
>  void riscv_translate_init(void);
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 0adde26321..597c47bc56 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1579,7 +1579,6 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env,
>
>      return xinsn;
>  }
> -#endif /* !CONFIG_USER_ONLY */
>
>  /*
>   * Handle Traps
> @@ -1589,8 +1588,6 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env,
>   */
>  void riscv_cpu_do_interrupt(CPUState *cs)
>  {
> -#if !defined(CONFIG_USER_ONLY)
> -
>      RISCVCPU *cpu = RISCV_CPU(cs);
>      CPURISCVState *env = &cpu->env;
>      bool write_gva = false;
> @@ -1783,6 +1780,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>
>      env->two_stage_lookup = false;
>      env->two_stage_indirect_lookup = false;
> -#endif
> -    cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */
>  }
> +
> +#endif /* !CONFIG_USER_ONLY */
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/
  2023-07-11 12:14 ` [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/ Philippe Mathieu-Daudé
@ 2023-07-19  1:00   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:00 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:21 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> Move TCG-specific files to the a new 'tcg' sub-directory. Add
> stubs for riscv_cpu_[get/set]_fflags and riscv_raise_exception().
> Adapt meson rules.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/{ => tcg}/XVentanaCondOps.decode |  0
>  target/riscv/{ => tcg}/insn16.decode          |  0
>  target/riscv/{ => tcg}/insn32.decode          |  0
>  target/riscv/{ => tcg}/xthead.decode          |  0
>  target/riscv/{ => tcg}/bitmanip_helper.c      |  0
>  target/riscv/{ => tcg}/crypto_helper.c        |  0
>  target/riscv/{ => tcg}/fpu_helper.c           |  0
>  target/riscv/{ => tcg}/m128_helper.c          |  0
>  target/riscv/{ => tcg}/op_helper.c            |  0
>  target/riscv/tcg/tcg-stub.c                   | 25 +++++++++++++++++++
>  target/riscv/{ => tcg}/translate.c            |  0
>  target/riscv/{ => tcg}/vector_helper.c        |  0
>  target/riscv/{ => tcg}/zce_helper.c           |  0
>  target/riscv/meson.build                      | 18 +------------
>  target/riscv/tcg/meson.build                  | 19 ++++++++++++++
>  15 files changed, 45 insertions(+), 17 deletions(-)
>  rename target/riscv/{ => tcg}/XVentanaCondOps.decode (100%)
>  rename target/riscv/{ => tcg}/insn16.decode (100%)
>  rename target/riscv/{ => tcg}/insn32.decode (100%)
>  rename target/riscv/{ => tcg}/xthead.decode (100%)
>  rename target/riscv/{ => tcg}/bitmanip_helper.c (100%)
>  rename target/riscv/{ => tcg}/crypto_helper.c (100%)
>  rename target/riscv/{ => tcg}/fpu_helper.c (100%)
>  rename target/riscv/{ => tcg}/m128_helper.c (100%)
>  rename target/riscv/{ => tcg}/op_helper.c (100%)
>  create mode 100644 target/riscv/tcg/tcg-stub.c
>  rename target/riscv/{ => tcg}/translate.c (100%)
>  rename target/riscv/{ => tcg}/vector_helper.c (100%)
>  rename target/riscv/{ => tcg}/zce_helper.c (100%)
>  create mode 100644 target/riscv/tcg/meson.build
>
> diff --git a/target/riscv/XVentanaCondOps.decode b/target/riscv/tcg/XVentanaCondOps.decode
> similarity index 100%
> rename from target/riscv/XVentanaCondOps.decode
> rename to target/riscv/tcg/XVentanaCondOps.decode
> diff --git a/target/riscv/insn16.decode b/target/riscv/tcg/insn16.decode
> similarity index 100%
> rename from target/riscv/insn16.decode
> rename to target/riscv/tcg/insn16.decode
> diff --git a/target/riscv/insn32.decode b/target/riscv/tcg/insn32.decode
> similarity index 100%
> rename from target/riscv/insn32.decode
> rename to target/riscv/tcg/insn32.decode
> diff --git a/target/riscv/xthead.decode b/target/riscv/tcg/xthead.decode
> similarity index 100%
> rename from target/riscv/xthead.decode
> rename to target/riscv/tcg/xthead.decode
> diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/tcg/bitmanip_helper.c
> similarity index 100%
> rename from target/riscv/bitmanip_helper.c
> rename to target/riscv/tcg/bitmanip_helper.c
> diff --git a/target/riscv/crypto_helper.c b/target/riscv/tcg/crypto_helper.c
> similarity index 100%
> rename from target/riscv/crypto_helper.c
> rename to target/riscv/tcg/crypto_helper.c
> diff --git a/target/riscv/fpu_helper.c b/target/riscv/tcg/fpu_helper.c
> similarity index 100%
> rename from target/riscv/fpu_helper.c
> rename to target/riscv/tcg/fpu_helper.c
> diff --git a/target/riscv/m128_helper.c b/target/riscv/tcg/m128_helper.c
> similarity index 100%
> rename from target/riscv/m128_helper.c
> rename to target/riscv/tcg/m128_helper.c
> diff --git a/target/riscv/op_helper.c b/target/riscv/tcg/op_helper.c
> similarity index 100%
> rename from target/riscv/op_helper.c
> rename to target/riscv/tcg/op_helper.c
> diff --git a/target/riscv/tcg/tcg-stub.c b/target/riscv/tcg/tcg-stub.c
> new file mode 100644
> index 0000000000..dfe42ae2ac
> --- /dev/null
> +++ b/target/riscv/tcg/tcg-stub.c
> @@ -0,0 +1,25 @@
> +/*
> + * QEMU RISC-V TCG stubs
> + *
> + * Copyright (c) 2023 Linaro
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
> +{
> +    g_assert_not_reached();
> +}
> +
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong)
> +{
> +    g_assert_not_reached();
> +}
> +
> +G_NORETURN void riscv_raise_exception(CPURISCVState *env,
> +                                      uint32_t exception, uintptr_t pc)
> +{
> +    g_assert_not_reached();
> +}
> diff --git a/target/riscv/translate.c b/target/riscv/tcg/translate.c
> similarity index 100%
> rename from target/riscv/translate.c
> rename to target/riscv/tcg/translate.c
> diff --git a/target/riscv/vector_helper.c b/target/riscv/tcg/vector_helper.c
> similarity index 100%
> rename from target/riscv/vector_helper.c
> rename to target/riscv/tcg/vector_helper.c
> diff --git a/target/riscv/zce_helper.c b/target/riscv/tcg/zce_helper.c
> similarity index 100%
> rename from target/riscv/zce_helper.c
> rename to target/riscv/tcg/zce_helper.c
> diff --git a/target/riscv/meson.build b/target/riscv/meson.build
> index 8967dfaded..8ef47f43f9 100644
> --- a/target/riscv/meson.build
> +++ b/target/riscv/meson.build
> @@ -1,34 +1,18 @@
> -# FIXME extra_args should accept files()
> -gen = [
> -  decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
> -  decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
> -  decodetree.process('xthead.decode', extra_args: '--static-decode=decode_xthead'),
> -  decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
> -]
> -
>  riscv_ss = ss.source_set()
>  riscv_system_ss = ss.source_set()
>
> -riscv_ss.add(gen)
>  riscv_ss.add(files(
>    'cpu.c',
>    'cpu_helper.c',
>    'csr.c',
> -  'fpu_helper.c',
>    'gdbstub.c',
> -  'op_helper.c',
> -  'vector_helper.c',
> -  'bitmanip_helper.c',
> -  'translate.c',
> -  'm128_helper.c',
> -  'crypto_helper.c',
> -  'zce_helper.c'
>  ))
>
>  riscv_system_ss.add(files(
>    'debug.c',
>  ))
>
> +subdir('tcg')
>  subdir('sysemu')
>
>  target_arch += {'riscv': riscv_ss}
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> new file mode 100644
> index 0000000000..65670493b1
> --- /dev/null
> +++ b/target/riscv/tcg/meson.build
> @@ -0,0 +1,19 @@
> +# FIXME extra_args should accept files()
> +gen = [
> +  decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
> +  decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
> +  decodetree.process('xthead.decode', extra_args: '--static-decode=decode_xthead'),
> +  decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
> +]
> +riscv_ss.add(when: 'CONFIG_TCG', if_true: gen)
> +
> +riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
> +  'fpu_helper.c',
> +  'op_helper.c',
> +  'vector_helper.c',
> +  'bitmanip_helper.c',
> +  'translate.c',
> +  'm128_helper.c',
> +  'crypto_helper.c',
> +  'zce_helper.c',
> +), if_false: files('tcg-stub.c'))
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c
  2023-07-11 12:14 ` [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c Philippe Mathieu-Daudé
@ 2023-07-19  1:01   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:01 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:18 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/cpu_helper.c    | 84 -------------------------------
>  target/riscv/tcg/cpu.c       | 98 ++++++++++++++++++++++++++++++++++++
>  target/riscv/tcg/meson.build |  1 +
>  3 files changed, 99 insertions(+), 84 deletions(-)
>  create mode 100644 target/riscv/tcg/cpu.c
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 597c47bc56..6f8778c6d3 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -64,90 +64,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  #endif
>  }
>
> -void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
> -                          uint64_t *cs_base, uint32_t *pflags)
> -{
> -    CPUState *cs = env_cpu(env);
> -    RISCVCPU *cpu = RISCV_CPU(cs);
> -    RISCVExtStatus fs, vs;
> -    uint32_t flags = 0;
> -
> -    *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
> -    *cs_base = 0;
> -
> -    if (cpu->cfg.ext_zve32f) {
> -        /*
> -         * If env->vl equals to VLMAX, we can use generic vector operation
> -         * expanders (GVEC) to accerlate the vector operations.
> -         * However, as LMUL could be a fractional number. The maximum
> -         * vector size can be operated might be less than 8 bytes,
> -         * which is not supported by GVEC. So we set vl_eq_vlmax flag to true
> -         * only when maxsz >= 8 bytes.
> -         */
> -        uint32_t vlmax = vext_get_vlmax(cpu, env->vtype);
> -        uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW);
> -        uint32_t maxsz = vlmax << sew;
> -        bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
> -                           (maxsz >= 8);
> -        flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
> -        flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew);
> -        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
> -                           FIELD_EX64(env->vtype, VTYPE, VLMUL));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
> -        flags = FIELD_DP32(flags, TB_FLAGS, VTA,
> -                           FIELD_EX64(env->vtype, VTYPE, VTA));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VMA,
> -                           FIELD_EX64(env->vtype, VTYPE, VMA));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
> -    } else {
> -        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
> -    }
> -
> -#ifdef CONFIG_USER_ONLY
> -    fs = EXT_STATUS_DIRTY;
> -    vs = EXT_STATUS_DIRTY;
> -#else
> -    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
> -
> -    flags |= cpu_mmu_index(env, 0);
> -    fs = get_field(env->mstatus, MSTATUS_FS);
> -    vs = get_field(env->mstatus, MSTATUS_VS);
> -
> -    if (env->virt_enabled) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> -        /*
> -         * Merge DISABLED and !DIRTY states using MIN.
> -         * We will set both fields when dirtying.
> -         */
> -        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> -        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> -    }
> -
> -    /* With Zfinx, floating point is enabled/disabled by Smstateen. */
> -    if (!riscv_has_ext(env, RVF)) {
> -        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
> -             ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
> -    }
> -
> -    if (cpu->cfg.debug && !icount_enabled()) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> -    }
> -#endif
> -
> -    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> -    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
> -    flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
> -    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
> -    if (env->cur_pmmask != 0) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
> -    }
> -    if (env->cur_pmbase != 0) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1);
> -    }
> -
> -    *pflags = flags;
> -}
> -
>  void riscv_cpu_update_mask(CPURISCVState *env)
>  {
>      target_ulong mask = 0, base = 0;
> diff --git a/target/riscv/tcg/cpu.c b/target/riscv/tcg/cpu.c
> new file mode 100644
> index 0000000000..2ae6919b80
> --- /dev/null
> +++ b/target/riscv/tcg/cpu.c
> @@ -0,0 +1,98 @@
> +/*
> + * RISC-V CPU helpers (TCG specific)
> + *
> + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
> + * Copyright (c) 2017-2018 SiFive, Inc.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#ifndef CONFIG_USER_ONLY
> +#include "sysemu/cpu-timers.h"
> +#endif
> +
> +void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
> +                          uint64_t *cs_base, uint32_t *pflags)
> +{
> +    CPUState *cs = env_cpu(env);
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    RISCVExtStatus fs, vs;
> +    uint32_t flags = 0;
> +
> +    *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
> +    *cs_base = 0;
> +
> +    if (cpu->cfg.ext_zve32f) {
> +        /*
> +         * If env->vl equals to VLMAX, we can use generic vector operation
> +         * expanders (GVEC) to accerlate the vector operations.
> +         * However, as LMUL could be a fractional number. The maximum
> +         * vector size can be operated might be less than 8 bytes,
> +         * which is not supported by GVEC. So we set vl_eq_vlmax flag to true
> +         * only when maxsz >= 8 bytes.
> +         */
> +        uint32_t vlmax = vext_get_vlmax(cpu, env->vtype);
> +        uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW);
> +        uint32_t maxsz = vlmax << sew;
> +        bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
> +                           (maxsz >= 8);
> +        flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
> +        flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew);
> +        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
> +                           FIELD_EX64(env->vtype, VTYPE, VLMUL));
> +        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
> +        flags = FIELD_DP32(flags, TB_FLAGS, VTA,
> +                           FIELD_EX64(env->vtype, VTYPE, VTA));
> +        flags = FIELD_DP32(flags, TB_FLAGS, VMA,
> +                           FIELD_EX64(env->vtype, VTYPE, VMA));
> +        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
> +    } else {
> +        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
> +    }
> +
> +#ifdef CONFIG_USER_ONLY
> +    fs = EXT_STATUS_DIRTY;
> +    vs = EXT_STATUS_DIRTY;
> +#else
> +    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
> +
> +    flags |= cpu_mmu_index(env, 0);
> +    fs = get_field(env->mstatus, MSTATUS_FS);
> +    vs = get_field(env->mstatus, MSTATUS_VS);
> +
> +    if (env->virt_enabled) {
> +        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +        /*
> +         * Merge DISABLED and !DIRTY states using MIN.
> +         * We will set both fields when dirtying.
> +         */
> +        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> +        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> +    }
> +
> +    /* With Zfinx, floating point is enabled/disabled by Smstateen. */
> +    if (!riscv_has_ext(env, RVF)) {
> +        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
> +             ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
> +    }
> +
> +    if (cpu->cfg.debug && !icount_enabled()) {
> +        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> +    }
> +#endif
> +
> +    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
> +    flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
> +    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
> +    if (env->cur_pmmask != 0) {
> +        flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
> +    }
> +    if (env->cur_pmbase != 0) {
> +        flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1);
> +    }
> +
> +    *pflags = flags;
> +}
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> index 65670493b1..a615aafd9a 100644
> --- a/target/riscv/tcg/meson.build
> +++ b/target/riscv/tcg/meson.build
> @@ -8,6 +8,7 @@ gen = [
>  riscv_ss.add(when: 'CONFIG_TCG', if_true: gen)
>
>  riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
> +  'cpu.c',
>    'fpu_helper.c',
>    'op_helper.c',
>    'vector_helper.c',
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c
  2023-07-11 12:14 ` [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c Philippe Mathieu-Daudé
@ 2023-07-19  1:01   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:01 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:16 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> We want to extract TCG-specific code from debug.c, but some
> functions call get_trigger_type() / do_trigger_action().
> Expose these prototypes in "debug.h".
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/debug.h | 4 ++++
>  target/riscv/debug.c | 5 ++---
>  2 files changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/debug.h b/target/riscv/debug.h
> index c471748d5a..65cd45b8f3 100644
> --- a/target/riscv/debug.h
> +++ b/target/riscv/debug.h
> @@ -147,4 +147,8 @@ void riscv_trigger_init(CPURISCVState *env);
>
>  bool riscv_itrigger_enabled(CPURISCVState *env);
>  void riscv_itrigger_update_priv(CPURISCVState *env);
> +
> +target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index);
> +void do_trigger_action(CPURISCVState *env, target_ulong trigger_index);
> +
>  #endif /* RISCV_DEBUG_H */
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 75ee1c4971..5676f2c57e 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -88,8 +88,7 @@ static inline target_ulong extract_trigger_type(CPURISCVState *env,
>      }
>  }
>
> -static inline target_ulong get_trigger_type(CPURISCVState *env,
> -                                            target_ulong trigger_index)
> +target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index)
>  {
>      return extract_trigger_type(env, env->tdata1[trigger_index]);
>  }
> @@ -217,7 +216,7 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask,
>      }
>  }
>
> -static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
> +void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
>  {
>      trigger_action_t action = get_trigger_action(env, trigger_index);
>
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 10/16] target/riscv: Extract TCG-specific code from debug.c
  2023-07-11 12:14 ` [PATCH v3 10/16] target/riscv: Extract TCG-specific code " Philippe Mathieu-Daudé
@ 2023-07-19  1:03   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:03 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:21 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> Extract TCG-specific code from debug.c to tcg/sysemu/debug.c,
> restrict the prototypes to TCG, adapt meson rules.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/debug.h                |   2 +
>  target/riscv/debug.c                | 148 -------------------------
>  target/riscv/tcg/sysemu/debug.c     | 165 ++++++++++++++++++++++++++++
>  target/riscv/tcg/meson.build        |   2 +
>  target/riscv/tcg/sysemu/meson.build |   3 +
>  5 files changed, 172 insertions(+), 148 deletions(-)
>  create mode 100644 target/riscv/tcg/sysemu/debug.c
>  create mode 100644 target/riscv/tcg/sysemu/meson.build
>
> diff --git a/target/riscv/debug.h b/target/riscv/debug.h
> index 65cd45b8f3..0b3bdd5be1 100644
> --- a/target/riscv/debug.h
> +++ b/target/riscv/debug.h
> @@ -139,9 +139,11 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val);
>
>  target_ulong tinfo_csr_read(CPURISCVState *env);
>
> +#ifdef CONFIG_TCG
>  void riscv_cpu_debug_excp_handler(CPUState *cs);
>  bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
>  bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
> +#endif
>
>  void riscv_trigger_init(CPURISCVState *env);
>
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 5676f2c57e..45a2605d8a 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -754,154 +754,6 @@ target_ulong tinfo_csr_read(CPURISCVState *env)
>             BIT(TRIGGER_TYPE_AD_MATCH6);
>  }
>
> -void riscv_cpu_debug_excp_handler(CPUState *cs)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(cs);
> -    CPURISCVState *env = &cpu->env;
> -
> -    if (cs->watchpoint_hit) {
> -        if (cs->watchpoint_hit->flags & BP_CPU) {
> -            do_trigger_action(env, DBG_ACTION_BP);
> -        }
> -    } else {
> -        if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
> -            do_trigger_action(env, DBG_ACTION_BP);
> -        }
> -    }
> -}
> -
> -bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(cs);
> -    CPURISCVState *env = &cpu->env;
> -    CPUBreakpoint *bp;
> -    target_ulong ctrl;
> -    target_ulong pc;
> -    int trigger_type;
> -    int i;
> -
> -    QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
> -        for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> -            trigger_type = get_trigger_type(env, i);
> -
> -            switch (trigger_type) {
> -            case TRIGGER_TYPE_AD_MATCH:
> -                /* type 2 trigger cannot be fired in VU/VS mode */
> -                if (env->virt_enabled) {
> -                    return false;
> -                }
> -
> -                ctrl = env->tdata1[i];
> -                pc = env->tdata2[i];
> -
> -                if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
> -                    /* check U/S/M bit against current privilege level */
> -                    if ((ctrl >> 3) & BIT(env->priv)) {
> -                        return true;
> -                    }
> -                }
> -                break;
> -            case TRIGGER_TYPE_AD_MATCH6:
> -                ctrl = env->tdata1[i];
> -                pc = env->tdata2[i];
> -
> -                if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) {
> -                    if (env->virt_enabled) {
> -                        /* check VU/VS bit against current privilege level */
> -                        if ((ctrl >> 23) & BIT(env->priv)) {
> -                            return true;
> -                        }
> -                    } else {
> -                        /* check U/S/M bit against current privilege level */
> -                        if ((ctrl >> 3) & BIT(env->priv)) {
> -                            return true;
> -                        }
> -                    }
> -                }
> -                break;
> -            default:
> -                /* other trigger types are not supported or irrelevant */
> -                break;
> -            }
> -        }
> -    }
> -
> -    return false;
> -}
> -
> -bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(cs);
> -    CPURISCVState *env = &cpu->env;
> -    target_ulong ctrl;
> -    target_ulong addr;
> -    int trigger_type;
> -    int flags;
> -    int i;
> -
> -    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> -        trigger_type = get_trigger_type(env, i);
> -
> -        switch (trigger_type) {
> -        case TRIGGER_TYPE_AD_MATCH:
> -            /* type 2 trigger cannot be fired in VU/VS mode */
> -            if (env->virt_enabled) {
> -                return false;
> -            }
> -
> -            ctrl = env->tdata1[i];
> -            addr = env->tdata2[i];
> -            flags = 0;
> -
> -            if (ctrl & TYPE2_LOAD) {
> -                flags |= BP_MEM_READ;
> -            }
> -            if (ctrl & TYPE2_STORE) {
> -                flags |= BP_MEM_WRITE;
> -            }
> -
> -            if ((wp->flags & flags) && (wp->vaddr == addr)) {
> -                /* check U/S/M bit against current privilege level */
> -                if ((ctrl >> 3) & BIT(env->priv)) {
> -                    return true;
> -                }
> -            }
> -            break;
> -        case TRIGGER_TYPE_AD_MATCH6:
> -            ctrl = env->tdata1[i];
> -            addr = env->tdata2[i];
> -            flags = 0;
> -
> -            if (ctrl & TYPE6_LOAD) {
> -                flags |= BP_MEM_READ;
> -            }
> -            if (ctrl & TYPE6_STORE) {
> -                flags |= BP_MEM_WRITE;
> -            }
> -
> -            if ((wp->flags & flags) && (wp->vaddr == addr)) {
> -                if (env->virt_enabled) {
> -                    /* check VU/VS bit against current privilege level */
> -                    if ((ctrl >> 23) & BIT(env->priv)) {
> -                        return true;
> -                    }
> -                } else {
> -                    /* check U/S/M bit against current privilege level */
> -                    if ((ctrl >> 3) & BIT(env->priv)) {
> -                        return true;
> -                    }
> -                }
> -            }
> -            break;
> -        default:
> -            /* other trigger types are not supported */
> -            break;
> -        }
> -    }
> -
> -    return false;
> -}
> -
>  void riscv_trigger_init(CPURISCVState *env)
>  {
>      target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
> diff --git a/target/riscv/tcg/sysemu/debug.c b/target/riscv/tcg/sysemu/debug.c
> new file mode 100644
> index 0000000000..cdd6744b3a
> --- /dev/null
> +++ b/target/riscv/tcg/sysemu/debug.c
> @@ -0,0 +1,165 @@
> +/*
> + * QEMU RISC-V Native Debug Support (TCG specific)
> + *
> + * Copyright (c) 2022 Wind River Systems, Inc.
> + *
> + * Author:
> + *   Bin Meng <bin.meng@windriver.com>
> + *
> + * This provides the native debug support via the Trigger Module, as defined
> + * in the RISC-V Debug Specification:
> + * https://github.com/riscv/riscv-debug-spec/raw/master/riscv-debug-stable.pdf
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +
> +void riscv_cpu_debug_excp_handler(CPUState *cs)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +
> +    if (cs->watchpoint_hit) {
> +        if (cs->watchpoint_hit->flags & BP_CPU) {
> +            do_trigger_action(env, DBG_ACTION_BP);
> +        }
> +    } else {
> +        if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
> +            do_trigger_action(env, DBG_ACTION_BP);
> +        }
> +    }
> +}
> +
> +bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +    CPUBreakpoint *bp;
> +    target_ulong ctrl;
> +    target_ulong pc;
> +    int trigger_type;
> +    int i;
> +
> +    QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
> +        for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> +            trigger_type = get_trigger_type(env, i);
> +
> +            switch (trigger_type) {
> +            case TRIGGER_TYPE_AD_MATCH:
> +                /* type 2 trigger cannot be fired in VU/VS mode */
> +                if (env->virt_enabled) {
> +                    return false;
> +                }
> +
> +                ctrl = env->tdata1[i];
> +                pc = env->tdata2[i];
> +
> +                if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
> +                    /* check U/S/M bit against current privilege level */
> +                    if ((ctrl >> 3) & BIT(env->priv)) {
> +                        return true;
> +                    }
> +                }
> +                break;
> +            case TRIGGER_TYPE_AD_MATCH6:
> +                ctrl = env->tdata1[i];
> +                pc = env->tdata2[i];
> +
> +                if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) {
> +                    if (env->virt_enabled) {
> +                        /* check VU/VS bit against current privilege level */
> +                        if ((ctrl >> 23) & BIT(env->priv)) {
> +                            return true;
> +                        }
> +                    } else {
> +                        /* check U/S/M bit against current privilege level */
> +                        if ((ctrl >> 3) & BIT(env->priv)) {
> +                            return true;
> +                        }
> +                    }
> +                }
> +                break;
> +            default:
> +                /* other trigger types are not supported or irrelevant */
> +                break;
> +            }
> +        }
> +    }
> +
> +    return false;
> +}
> +
> +bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +    target_ulong ctrl;
> +    target_ulong addr;
> +    int trigger_type;
> +    int flags;
> +    int i;
> +
> +    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> +        trigger_type = get_trigger_type(env, i);
> +
> +        switch (trigger_type) {
> +        case TRIGGER_TYPE_AD_MATCH:
> +            /* type 2 trigger cannot be fired in VU/VS mode */
> +            if (env->virt_enabled) {
> +                return false;
> +            }
> +
> +            ctrl = env->tdata1[i];
> +            addr = env->tdata2[i];
> +            flags = 0;
> +
> +            if (ctrl & TYPE2_LOAD) {
> +                flags |= BP_MEM_READ;
> +            }
> +            if (ctrl & TYPE2_STORE) {
> +                flags |= BP_MEM_WRITE;
> +            }
> +
> +            if ((wp->flags & flags) && (wp->vaddr == addr)) {
> +                /* check U/S/M bit against current privilege level */
> +                if ((ctrl >> 3) & BIT(env->priv)) {
> +                    return true;
> +                }
> +            }
> +            break;
> +        case TRIGGER_TYPE_AD_MATCH6:
> +            ctrl = env->tdata1[i];
> +            addr = env->tdata2[i];
> +            flags = 0;
> +
> +            if (ctrl & TYPE6_LOAD) {
> +                flags |= BP_MEM_READ;
> +            }
> +            if (ctrl & TYPE6_STORE) {
> +                flags |= BP_MEM_WRITE;
> +            }
> +
> +            if ((wp->flags & flags) && (wp->vaddr == addr)) {
> +                if (env->virt_enabled) {
> +                    /* check VU/VS bit against current privilege level */
> +                    if ((ctrl >> 23) & BIT(env->priv)) {
> +                        return true;
> +                    }
> +                } else {
> +                    /* check U/S/M bit against current privilege level */
> +                    if ((ctrl >> 3) & BIT(env->priv)) {
> +                        return true;
> +                    }
> +                }
> +            }
> +            break;
> +        default:
> +            /* other trigger types are not supported */
> +            break;
> +        }
> +    }
> +
> +    return false;
> +}
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> index a615aafd9a..933d340799 100644
> --- a/target/riscv/tcg/meson.build
> +++ b/target/riscv/tcg/meson.build
> @@ -18,3 +18,5 @@ riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
>    'crypto_helper.c',
>    'zce_helper.c',
>  ), if_false: files('tcg-stub.c'))
> +
> +subdir('sysemu')
> diff --git a/target/riscv/tcg/sysemu/meson.build b/target/riscv/tcg/sysemu/meson.build
> new file mode 100644
> index 0000000000..e8e61e5784
> --- /dev/null
> +++ b/target/riscv/tcg/sysemu/meson.build
> @@ -0,0 +1,3 @@
> +riscv_system_ss.add(when: 'CONFIG_TCG', if_true: files(
> +  'debug.c',
> +))
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/
  2023-07-11 12:14 ` [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/ Philippe Mathieu-Daudé
@ 2023-07-19  1:04   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:04 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:22 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/cpu.h                | 2 +-
>  target/riscv/{ => sysemu}/debug.h | 0
>  target/riscv/cpu_helper.c         | 2 +-
>  target/riscv/{ => sysemu}/debug.c | 0
>  target/riscv/meson.build          | 4 ----
>  target/riscv/sysemu/meson.build   | 1 +
>  6 files changed, 3 insertions(+), 6 deletions(-)
>  rename target/riscv/{ => sysemu}/debug.h (100%)
>  rename target/riscv/{ => sysemu}/debug.c (100%)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 0602b948d4..8d8e30d6c1 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -94,7 +94,7 @@ typedef enum {
>
>  #if !defined(CONFIG_USER_ONLY)
>  #include "sysemu/pmp.h"
> -#include "debug.h"
> +#include "sysemu/debug.h"
>  #endif
>
>  #define RV_VLEN_MAX 1024
> diff --git a/target/riscv/debug.h b/target/riscv/sysemu/debug.h
> similarity index 100%
> rename from target/riscv/debug.h
> rename to target/riscv/sysemu/debug.h
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6f8778c6d3..6c773000a5 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -32,7 +32,7 @@
>  #include "sysemu/cpu-timers.h"
>  #endif
>  #include "cpu_bits.h"
> -#include "debug.h"
> +#include "sysemu/debug.h"
>  #include "tcg/oversized-guest.h"
>
>  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
> diff --git a/target/riscv/debug.c b/target/riscv/sysemu/debug.c
> similarity index 100%
> rename from target/riscv/debug.c
> rename to target/riscv/sysemu/debug.c
> diff --git a/target/riscv/meson.build b/target/riscv/meson.build
> index 8ef47f43f9..49cdcde679 100644
> --- a/target/riscv/meson.build
> +++ b/target/riscv/meson.build
> @@ -8,10 +8,6 @@ riscv_ss.add(files(
>    'gdbstub.c',
>  ))
>
> -riscv_system_ss.add(files(
> -  'debug.c',
> -))
> -
>  subdir('tcg')
>  subdir('sysemu')
>
> diff --git a/target/riscv/sysemu/meson.build b/target/riscv/sysemu/meson.build
> index 64de0256a5..e902ba2dad 100644
> --- a/target/riscv/sysemu/meson.build
> +++ b/target/riscv/sysemu/meson.build
> @@ -1,5 +1,6 @@
>  riscv_system_ss.add(files(
>    'arch_dump.c',
> +  'debug.c',
>    'machine.c',
>    'monitor.c',
>    'pmp.c',
> --
> 2.38.1
>
>


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

* Re: [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c
  2023-07-11 12:14 ` [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c Philippe Mathieu-Daudé
@ 2023-07-19  1:04   ` Alistair Francis
  0 siblings, 0 replies; 25+ messages in thread
From: Alistair Francis @ 2023-07-19  1:04 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-riscv, Daniel Henrique Barboza

On Tue, Jul 11, 2023 at 10:22 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> We want to extract TCG/sysemu-specific code from cpu_helper.c,
> but some functions call riscv_cpu_pending_to_irq(). Expose the
> prototype in "internals.h".
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

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

Alistair

> ---
>  target/riscv/internals.h  | 4 ++++
>  target/riscv/cpu_helper.c | 6 +++---
>  2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index b5f823c7ec..b6881b4815 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -72,6 +72,10 @@ target_ulong fclass_d(uint64_t frs1);
>
>  #ifndef CONFIG_USER_ONLY
>  extern const VMStateDescription vmstate_riscv_cpu;
> +
> +int riscv_cpu_pending_to_irq(CPURISCVState *env,
> +                             int extirq, unsigned int extirq_def_prio,
> +                             uint64_t pending, uint8_t *iprio);
>  #endif
>
>  enum {
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6c773000a5..e73cf56e5c 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -256,9 +256,9 @@ uint8_t riscv_cpu_default_priority(int irq)
>      return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
>  };
>
> -static int riscv_cpu_pending_to_irq(CPURISCVState *env,
> -                                    int extirq, unsigned int extirq_def_prio,
> -                                    uint64_t pending, uint8_t *iprio)
> +int riscv_cpu_pending_to_irq(CPURISCVState *env,
> +                             int extirq, unsigned int extirq_def_prio,
> +                             uint64_t pending, uint8_t *iprio)
>  {
>      int irq, best_irq = RISCV_EXCP_NONE;
>      unsigned int prio, best_prio = UINT_MAX;
> --
> 2.38.1
>
>


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

end of thread, other threads:[~2023-07-19  1:05 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-11 12:14 [PATCH-for-8.2 v3 00/16] target/riscv: Allow building without TCG (KVM-only so far) Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 01/16] target/riscv: Remove unuseful KVM stubs Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 02/16] target/riscv: Remove unused 'instmap.h' header in translate.c Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 03/16] target/riscv: Restrict sysemu specific header to user emulation Philippe Mathieu-Daudé
2023-07-12 15:18   ` Daniel Henrique Barboza
2023-07-11 12:14 ` [PATCH v3 04/16] target/riscv: Restrict 'rv128' machine to TCG accelerator Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 05/16] target/riscv: Move sysemu-specific files to target/riscv/sysemu/ Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 06/16] target/riscv: Restrict riscv_cpu_do_interrupt() to sysemu Philippe Mathieu-Daudé
2023-07-14  3:17   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/ Philippe Mathieu-Daudé
2023-07-19  1:00   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c Philippe Mathieu-Daudé
2023-07-19  1:01   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c Philippe Mathieu-Daudé
2023-07-19  1:01   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 10/16] target/riscv: Extract TCG-specific code " Philippe Mathieu-Daudé
2023-07-19  1:03   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/ Philippe Mathieu-Daudé
2023-07-19  1:04   ` Alistair Francis
2023-07-11 12:14 ` [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c Philippe Mathieu-Daudé
2023-07-19  1:04   ` Alistair Francis
2023-07-11 12:14 ` [RFC PATCH v3 13/16] target/riscv: Move TCG/sysemu-specific code to tcg/sysemu/cpu_helper.c Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 14/16] target/riscv: Move sysemu-specific code to sysemu/cpu_helper.c Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 15/16] target/riscv: Restrict TCG-specific prototype declarations Philippe Mathieu-Daudé
2023-07-11 12:14 ` [PATCH v3 16/16] gitlab-ci.d/crossbuilds: Add KVM riscv64 cross-build jobs Philippe Mathieu-Daudé

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