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