Hi,
in testing qemu 10.1 since rc levels I've found yet another odd
behavior. As far as I can tell it's not your fault, but I wanted to
tell you for awareness and potentially to help me get the right debug
data.
A test that triggered when checking Ubuntu was the one of EDK2,
emulating riscv when running on ppc64, example log [1]. Yep, yet again
not the most common setup :-) and the same emulation in all other
Ubuntu architectures as host works fine.
Gladly this was reproducible and it eventually led me to a wild
journey which now makes me consider gcc-15 (15.2.0-1ubuntu1) as the
suspect here.
After confirming that I spotted that it only happens if qemu is
compiled with a particular optimization option.
The issue itself is as weird as jumping into an if, despite the
condition not being met :-/
Thread 3 "qemu-system-ris" hit Breakpoint 1,
riscv_pmu_icount_update_priv (env=0x10147c310, newpriv=1,
new_virt=false) at ../target/riscv/pmu.c:200
200 if (icount_enabled()) {
(gdb) n
203 current_icount = cpu_get_host_ticks();
(gdb) n
206 if (env->virt_enabled) {
(gdb) n
211 counter_arr = env->pmu_fixed_ctrs[1].counter;
(gdb) n
212 snapshot_prev = env->pmu_fixed_ctrs[1].counter_prev;
(gdb) n
215 if (new_virt) {
(gdb) n
216 g_assert(newpriv <= PRV_S);
(gdb) p new_virt
$1 = false
Since I know the arch, the function and the tunable - I can use a
rather surgical mitigation like this.
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index a68809eef3..5317d8be57 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -189,6 +189,13 @@ static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu,
uint32_t ctr_idx)
* env->priv and env->virt_enabled contain old priv and old virt and
* new priv and new virt values are passed in as arguments.
*/
+#if defined(__powerpc64__) || defined(__ppc64__)
+ #define NO_GCSE_ATTR __attribute__((optimize("no-gcse")))
+#else
+ #define NO_GCSE_ATTR
+#endif
+
+NO_GCSE_ATTR
static void riscv_pmu_icount_update_priv(CPURISCVState *env,
target_ulong newpriv, bool new_virt)
{
But a mitigation is all that it is, ideally, I'd report this as a gcc bug.
Yet the - understandable - hard requirement of getting the
pre-processed files makes this quite complex. As I can't even exactly
point to where exactly things go wrong.
I'd ask if one of you has experience in providing gcc-bugs out of a
qemu build. Is it as obvious as throwing -save-temps into *flags or is
there more to consider get what would be needed?
P.S. If you are curious and want debug binaries and the journey to
find this, it is all at the related Ubuntu bug [2]
[1]: https://autopkgtest.ubuntu.com/results/autopkgtest-questing/questing/ppc64el/e/edk2/20250818_045238_153f0@/log.gz
[2]: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/2120835
--
Christian Ehrhardt
Director of Engineering, Ubuntu Server
Canonical Ltd
On 8/27/25 10:26, Christian Ehrhardt wrote: > Hi, > in testing qemu 10.1 since rc levels I've found yet another odd > behavior. As far as I can tell it's not your fault, but I wanted to > tell you for awareness and potentially to help me get the right debug > data. > > A test that triggered when checking Ubuntu was the one of EDK2, > emulating riscv when running on ppc64, example log [1]. Yep, yet again > not the most common setup :-) and the same emulation in all other > Ubuntu architectures as host works fine. > Gladly this was reproducible and it eventually led me to a wild > journey which now makes me consider gcc-15 (15.2.0-1ubuntu1) as the > suspect here. > > Since I know the arch, the function and the tunable - I can use a > rather surgical mitigation like this. > > diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c > index a68809eef3..5317d8be57 100644 > --- a/target/riscv/pmu.c > +++ b/target/riscv/pmu.c > @@ -189,6 +189,13 @@ static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, > uint32_t ctr_idx) > * env->priv and env->virt_enabled contain old priv and old virt and > * new priv and new virt values are passed in as arguments. > */ > +#if defined(__powerpc64__) || defined(__ppc64__) > + #define NO_GCSE_ATTR __attribute__((optimize("no-gcse"))) > +#else > + #define NO_GCSE_ATTR > +#endif > + > +NO_GCSE_ATTR > static void riscv_pmu_icount_update_priv(CPURISCVState *env, > target_ulong newpriv, bool new_virt) > { > > But a mitigation is all that it is, ideally, I'd report this as a gcc bug. > Yet the - understandable - hard requirement of getting the > pre-processed files makes this quite complex. As I can't even exactly > point to where exactly things go wrong. > I'd ask if one of you has experience in providing gcc-bugs out of a > qemu build. Is it as obvious as throwing -save-temps into *flags or is > there more to consider get what would be needed? Yes, it's like that. Run "ninja -v ./libqemu-riscv64-softmmu.a.p/target_riscv_pmu.c.o", stick -save-temps at the end and submit the resulting .i file as an attachment to the GCC bug. Paolo
On Wed, Aug 27, 2025 at 10:47 AM Paolo Bonzini <pbonzini@redhat.com> wrote: > > On 8/27/25 10:26, Christian Ehrhardt wrote: > > Hi, > > in testing qemu 10.1 since rc levels I've found yet another odd > > behavior. As far as I can tell it's not your fault, but I wanted to > > tell you for awareness and potentially to help me get the right debug > > data. > > > > A test that triggered when checking Ubuntu was the one of EDK2, > > emulating riscv when running on ppc64, example log [1]. Yep, yet again > > not the most common setup :-) and the same emulation in all other > > Ubuntu architectures as host works fine. > > Gladly this was reproducible and it eventually led me to a wild > > journey which now makes me consider gcc-15 (15.2.0-1ubuntu1) as the > > suspect here. > > > > Since I know the arch, the function and the tunable - I can use a > > rather surgical mitigation like this. > > > > diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c > > index a68809eef3..5317d8be57 100644 > > --- a/target/riscv/pmu.c > > +++ b/target/riscv/pmu.c > > @@ -189,6 +189,13 @@ static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, > > uint32_t ctr_idx) > > * env->priv and env->virt_enabled contain old priv and old virt and > > * new priv and new virt values are passed in as arguments. > > */ > > +#if defined(__powerpc64__) || defined(__ppc64__) > > + #define NO_GCSE_ATTR __attribute__((optimize("no-gcse"))) > > +#else > > + #define NO_GCSE_ATTR > > +#endif > > + > > +NO_GCSE_ATTR > > static void riscv_pmu_icount_update_priv(CPURISCVState *env, > > target_ulong newpriv, bool new_virt) > > { > > > > But a mitigation is all that it is, ideally, I'd report this as a gcc bug. > > Yet the - understandable - hard requirement of getting the > > pre-processed files makes this quite complex. As I can't even exactly > > point to where exactly things go wrong. > > I'd ask if one of you has experience in providing gcc-bugs out of a > > qemu build. Is it as obvious as throwing -save-temps into *flags or is > > there more to consider get what would be needed? > > Yes, it's like that. Run "ninja -v > ./libqemu-riscv64-softmmu.a.p/target_riscv_pmu.c.o", stick -save-temps > at the end and submit the resulting .i file as an attachment to the GCC bug. Thanks for confirming, that allowed me to report it to gcc upstream as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121689 Let us see what they say, and if anyone else is affected I hope you can use the mitigation I shared until then. > Paolo > -- Christian Ehrhardt Director of Engineering, Ubuntu Server Canonical Ltd
© 2016 - 2025 Red Hat, Inc.