target/riscv/cpu.c | 9 +++++++ target/riscv/cpu_helper.c | 53 +++++++++++++++++++++++++++++++++++++++ target/riscv/csr.c | 18 +++++++++++-- target/riscv/fpu_helper.c | 27 -------------------- target/riscv/meson.build | 9 ++++--- target/riscv/op_helper.c | 15 ----------- 6 files changed, 84 insertions(+), 47 deletions(-)
Building riscv64-softmmu with --disable-tcg currently fails because
RISC-V still builds or references TCG-only sources and helpers in the
no-TCG configuration.
Move TCG-only helper and translator sources under CONFIG_TCG, guard the
remaining TCG-only code in common files, and move common CSR helpers out
of TCG-only helper files.
misa writes still rely on the TCG extension validation path. Since
x-misa-w is a TCG-only experimental property, reject it during CPU
realize when TCG is not available.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3483
Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
---
Testing:
- riscv64-softmmu --enable-kvm --disable-tcg --enable-debug builds
successfully.
- riscv64-softmmu --enable-debug builds successfully.
- qemu-system-riscv64 -M virt,accel=qtest -cpu rv64,x-misa-w=true \
-S -nographic reports "x-misa-w requires TCG".
target/riscv/cpu.c | 9 +++++++
target/riscv/cpu_helper.c | 53 +++++++++++++++++++++++++++++++++++++++
target/riscv/csr.c | 18 +++++++++++--
target/riscv/fpu_helper.c | 27 --------------------
target/riscv/meson.build | 9 ++++---
target/riscv/op_helper.c | 15 -----------
6 files changed, 84 insertions(+), 47 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 862834b480..3f4563fce2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -36,7 +36,9 @@
#include "system/tcg.h"
#include "kvm/kvm_riscv.h"
#include "tcg/tcg-cpu.h"
+#ifdef CONFIG_TCG
#include "tcg/tcg.h"
+#endif
/* RISC-V CPU definitions */
static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
@@ -956,6 +958,13 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
Error *local_err = NULL;
+#ifndef CONFIG_TCG
+ if (cpu->cfg.misa_w) {
+ error_setg(errp, "x-misa-w requires TCG");
+ return;
+ }
+#endif
+
cpu_exec_realizefn(cs, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 17305e1bb7..e53a5d567d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -21,6 +21,7 @@
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "cpu.h"
+#include "fpu/softfloat.h"
#include "internals.h"
#include "pmu.h"
#include "exec/cputlb.h"
@@ -28,8 +29,10 @@
#include "exec/target_page.h"
#include "system/memory.h"
#include "instmap.h"
+#ifdef CONFIG_TCG
#include "tcg/tcg-op.h"
#include "accel/tcg/cpu-ops.h"
+#endif
#include "trace.h"
#include "semihosting/common-semi.h"
#include "exec/icount.h"
@@ -38,6 +41,52 @@
#include "pmp.h"
#include "qemu/plugin.h"
+/* Exceptions processing helpers */
+G_NORETURN void riscv_raise_exception(CPURISCVState *env,
+ RISCVException exception,
+ uintptr_t pc)
+{
+ CPUState *cs = env_cpu(env);
+
+ trace_riscv_exception(exception,
+ riscv_cpu_get_trap_name(exception, false),
+ env->pc);
+
+ cs->exception_index = exception;
+#ifdef CONFIG_TCG
+ cpu_loop_exit_restore(cs, pc);
+#else
+ qemu_build_not_reached();
+#endif
+}
+
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
+{
+ int soft = get_float_exception_flags(&env->fp_status);
+ target_ulong hard = 0;
+
+ hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
+ hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
+ hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
+ hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
+ hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
+
+ return hard;
+}
+
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
+{
+ int soft = 0;
+
+ soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
+ soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
+ soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
+ soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
+ soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
+
+ set_float_exception_flags(soft, &env->fp_status);
+}
+
int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
{
#ifdef CONFIG_USER_ONLY
@@ -1667,6 +1716,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
return TRANSLATE_SUCCESS;
}
+#ifdef CONFIG_TCG
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
MMUAccessType access_type, bool pmp_violation,
bool first_stage, bool two_stage,
@@ -1709,6 +1759,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
env->two_stage_lookup = two_stage;
env->two_stage_indirect_lookup = two_stage_indirect;
}
+#endif
hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr)
{
@@ -1733,6 +1784,7 @@ hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr)
return phys_addr;
}
+#ifdef CONFIG_TCG
void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
@@ -1957,6 +2009,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
return true;
}
+#endif
static target_ulong riscv_transformed_insn(CPURISCVState *env,
target_ulong insn,
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5514e0f455..04fa320ff8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2135,21 +2135,31 @@ static RISCVException read_misa(CPURISCVState *env, int csrno,
static target_ulong get_next_pc(CPURISCVState *env, uintptr_t ra)
{
+ /* Outside of a running cpu, env contains the next pc. */
+ if (ra == 0) {
+ return env->pc;
+ }
+
+#ifdef CONFIG_TCG
uint64_t data[INSN_START_WORDS];
- /* Outside of a running cpu, env contains the next pc. */
- if (ra == 0 || !cpu_unwind_state_data(env_cpu(env), ra, data)) {
+ if (!cpu_unwind_state_data(env_cpu(env), ra, data)) {
return env->pc;
}
/* Within unwind data, [0] is pc and [1] is the opcode. */
return data[0] + insn_len(data[1]);
+#else
+ qemu_build_not_reached();
+#endif
}
static RISCVException write_misa(CPURISCVState *env, int csrno,
target_ulong val, uintptr_t ra)
{
+#ifdef CONFIG_TCG
RISCVCPU *cpu = env_archcpu(env);
+#endif
uint32_t orig_misa_ext = env->misa_ext;
Error *local_err = NULL;
@@ -2178,7 +2188,11 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
}
env->misa_ext = val;
+#ifdef CONFIG_TCG
riscv_cpu_validate_set_extensions(cpu, &local_err);
+#else
+ qemu_build_not_reached();
+#endif
if (local_err != NULL) {
/* Rollback on validation error */
qemu_log_mask(LOG_GUEST_ERROR, "Unable to write MISA ext value "
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index af40561b31..eec6328281 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -23,33 +23,6 @@
#include "fpu/softfloat.h"
#include "internals.h"
-target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
-{
- int soft = get_float_exception_flags(&env->fp_status);
- target_ulong hard = 0;
-
- hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
- hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
- hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
- hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
- hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
-
- return hard;
-}
-
-void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
-{
- int soft = 0;
-
- soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
- soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
- soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
- soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
- soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
-
- set_float_exception_flags(soft, &env->fp_status);
-}
-
void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
{
int softrm;
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 79f36abd63..c2b2f61ad9 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -9,7 +9,7 @@ gen = [
]
riscv_ss = ss.source_set()
-riscv_ss.add(gen)
+riscv_ss.add(when: 'CONFIG_TCG', if_true: gen)
riscv_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
if_true: files('common-semi-target.c'))
@@ -18,11 +18,14 @@ riscv_ss.add(files(
'cpu.c',
'cpu_helper.c',
'csr.c',
- 'fpu_helper.c',
'gdbstub.c',
+ 'vector_internals.c',
+))
+
+riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
+ 'fpu_helper.c',
'op_helper.c',
'vector_helper.c',
- 'vector_internals.c',
'bitmanip_helper.c',
'translate.c',
'm128_helper.c',
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 81873014cb..d17a8bbf10 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -28,21 +28,6 @@
#include "exec/tlb-flags.h"
#include "trace.h"
-/* Exceptions processing helpers */
-G_NORETURN void riscv_raise_exception(CPURISCVState *env,
- RISCVException exception,
- uintptr_t pc)
-{
- CPUState *cs = env_cpu(env);
-
- trace_riscv_exception(exception,
- riscv_cpu_get_trap_name(exception, false),
- env->pc);
-
- cs->exception_index = exception;
- cpu_loop_exit_restore(cs, pc);
-}
-
void helper_raise_exception(CPURISCVState *env, uint32_t exception)
{
riscv_raise_exception(env, exception, 0);
--
2.43.0
Hi,
On 26/5/26 04:48, Zephyr Li wrote:
> Building riscv64-softmmu with --disable-tcg currently fails because
> RISC-V still builds or references TCG-only sources and helpers in the
> no-TCG configuration.
>
> Move TCG-only helper and translator sources under CONFIG_TCG, guard the
> remaining TCG-only code in common files, and move common CSR helpers out
> of TCG-only helper files.
>
> misa writes still rely on the TCG extension validation path. Since
> x-misa-w is a TCG-only experimental property, reject it during CPU
> realize when TCG is not available.
Please split as one logical change per patch (i.e. moving FPU flags
in one, exception path in another, ...).
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3483
>
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
> ---
> Testing:
> - riscv64-softmmu --enable-kvm --disable-tcg --enable-debug builds
> successfully.
> - riscv64-softmmu --enable-debug builds successfully.
> - qemu-system-riscv64 -M virt,accel=qtest -cpu rv64,x-misa-w=true \
> -S -nographic reports "x-misa-w requires TCG".
>
> target/riscv/cpu.c | 9 +++++++
> target/riscv/cpu_helper.c | 53 +++++++++++++++++++++++++++++++++++++++
> target/riscv/csr.c | 18 +++++++++++--
> target/riscv/fpu_helper.c | 27 --------------------
> target/riscv/meson.build | 9 ++++---
> target/riscv/op_helper.c | 15 -----------
> 6 files changed, 84 insertions(+), 47 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 862834b480..3f4563fce2 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -36,7 +36,9 @@
> #include "system/tcg.h"
> #include "kvm/kvm_riscv.h"
> #include "tcg/tcg-cpu.h"
> +#ifdef CONFIG_TCG
> #include "tcg/tcg.h"
Apparently this header isn't needed at all.
> +#endif
>
> /* RISC-V CPU definitions */
> static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
> @@ -956,6 +958,13 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
> RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
> Error *local_err = NULL;
>
> +#ifndef CONFIG_TCG
> + if (cpu->cfg.misa_w) {
> + error_setg(errp, "x-misa-w requires TCG");
> + return;
> + }
> +#endif
> +
> cpu_exec_realizefn(cs, &local_err);
> if (local_err != NULL) {
> error_propagate(errp, local_err);
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 17305e1bb7..e53a5d567d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -21,6 +21,7 @@
> #include "qemu/log.h"
> #include "qemu/main-loop.h"
> #include "cpu.h"
> +#include "fpu/softfloat.h"
> #include "internals.h"
> #include "pmu.h"
> #include "exec/cputlb.h"
> @@ -28,8 +29,10 @@
> #include "exec/target_page.h"
> #include "system/memory.h"
> #include "instmap.h"
> +#ifdef CONFIG_TCG
> #include "tcg/tcg-op.h"
> #include "accel/tcg/cpu-ops.h"
> +#endif
> #include "trace.h"
> #include "semihosting/common-semi.h"
> #include "exec/icount.h"
> @@ -38,6 +41,52 @@
> #include "pmp.h"
> #include "qemu/plugin.h"
>
> +/* Exceptions processing helpers */
> +G_NORETURN void riscv_raise_exception(CPURISCVState *env,
> + RISCVException exception,
> + uintptr_t pc)
> +{
> + CPUState *cs = env_cpu(env);
> +
> + trace_riscv_exception(exception,
> + riscv_cpu_get_trap_name(exception, false),
> + env->pc);
> +
> + cs->exception_index = exception;
> +#ifdef CONFIG_TCG
> + cpu_loop_exit_restore(cs, pc);
> +#else
> + qemu_build_not_reached();
> +#endif
> +}
> +
> +target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
> +{
> + int soft = get_float_exception_flags(&env->fp_status);
> + target_ulong hard = 0;
> +
> + hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
> + hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
> + hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
> + hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
> + hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
> +
> + return hard;
> +}
> +
> +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
> +{
> + int soft = 0;
> +
> + soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
> + soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
> + soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
> + soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
> + soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
> +
> + set_float_exception_flags(soft, &env->fp_status);
> +}
> +
> int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
> {
> #ifdef CONFIG_USER_ONLY
> @@ -1667,6 +1716,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> return TRANSLATE_SUCCESS;
> }
>
> +#ifdef CONFIG_TCG
> static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> MMUAccessType access_type, bool pmp_violation,
> bool first_stage, bool two_stage,
> @@ -1709,6 +1759,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> env->two_stage_lookup = two_stage;
> env->two_stage_indirect_lookup = two_stage_indirect;
> }
> +#endif
>
> hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr)
> {
> @@ -1733,6 +1784,7 @@ hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr)
> return phys_addr;
> }
>
> +#ifdef CONFIG_TCG
> void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
> vaddr addr, unsigned size,
> MMUAccessType access_type,
> @@ -1957,6 +2009,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>
> return true;
> }
> +#endif
>
> static target_ulong riscv_transformed_insn(CPURISCVState *env,
> target_ulong insn,
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 5514e0f455..04fa320ff8 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -2135,21 +2135,31 @@ static RISCVException read_misa(CPURISCVState *env, int csrno,
>
> static target_ulong get_next_pc(CPURISCVState *env, uintptr_t ra)
> {
> + /* Outside of a running cpu, env contains the next pc. */
> + if (ra == 0) {
> + return env->pc;
> + }
> +
> +#ifdef CONFIG_TCG
> uint64_t data[INSN_START_WORDS];
>
> - /* Outside of a running cpu, env contains the next pc. */
> - if (ra == 0 || !cpu_unwind_state_data(env_cpu(env), ra, data)) {
> + if (!cpu_unwind_state_data(env_cpu(env), ra, data)) {
> return env->pc;
> }
>
> /* Within unwind data, [0] is pc and [1] is the opcode. */
> return data[0] + insn_len(data[1]);
> +#else
> + qemu_build_not_reached();
> +#endif
> }
>
> static RISCVException write_misa(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> +#ifdef CONFIG_TCG
> RISCVCPU *cpu = env_archcpu(env);
> +#endif
> uint32_t orig_misa_ext = env->misa_ext;
> Error *local_err = NULL;
>
> @@ -2178,7 +2188,11 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
> }
>
> env->misa_ext = val;
> +#ifdef CONFIG_TCG
> riscv_cpu_validate_set_extensions(cpu, &local_err);
Maybe clearer to add as a stub?
> +#else
> + qemu_build_not_reached();
> +#endif
> if (local_err != NULL) {
> /* Rollback on validation error */
> qemu_log_mask(LOG_GUEST_ERROR, "Unable to write MISA ext value "
© 2016 - 2026 Red Hat, Inc.