[PATCH] target/riscv: Fix no-TCG build

Zephyr Li posted 1 patch 4 days, 14 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260526024851.2014325-1-fritchleybohrer@gmail.com
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu.zevorn@gmail.com>
There is a newer version of this series
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(-)
[PATCH] target/riscv: Fix no-TCG build
Posted by Zephyr Li 4 days, 14 hours ago
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
Re: [PATCH] target/riscv: Fix no-TCG build
Posted by Philippe Mathieu-Daudé 4 days, 9 hours ago
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 "