Comparing the least optimized, debuginfo enabled cases with minimal difference
between good and bad case.
Selecting those two:
# single 3 => /usr/bin/qemu-system-riscv64.gcc15.debug.bad
# fails export CC=gcc-15 CXX=g++-15 CFLAGS="-O1 -g -fgcse
-fgcse-lm"
# single 4 => /usr/bin/qemu-system-riscv64.gcc15.debug.good
# works export CC=gcc-15 CXX=g++-15 CFLAGS="-O1 -g -fgcse-lm"
We know pretty much where it fails:
ERROR:../target/riscv/pmu.c:216:riscv_pmu_icount_update_priv: assertion
failed: (newpriv <= PRV_S)
Throwing it into gdb and breaking on `riscv_pmu_icount_update_priv`:
$ gdb --args /usr/bin/qemu-system-riscv64.gcc15.debug.good -no-user-
config -nodefaults -m 256 -display 'none' -serial 'stdio' -machine
'virt'
## bad case ##
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
## good case ##
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
219 snapshot_new = env->pmu_fixed_ctrs[1].counter_prev;
(gdb) n
226 delta = current_icount - snapshot_prev[env->priv];
(gdb) p new_virt
$1 = false
## code ##
qemu.git/target/riscv/pmu.c
192 static void riscv_pmu_icount_update_priv(CPURISCVState *env,
193 target_ulong newpriv, bool
new_virt)
194 {
195 uint64_t *snapshot_prev, *snapshot_new;
196 uint64_t current_icount;
197 uint64_t *counter_arr;
198 uint64_t delta;
199
200 if (icount_enabled()) {
201 current_icount = icount_get_raw();
202 } else {
203 current_icount = cpu_get_host_ticks();
204 }
205
206 if (env->virt_enabled) {
207 g_assert(env->priv <= PRV_S);
208 counter_arr = env->pmu_fixed_ctrs[1].counter_virt;
209 snapshot_prev = env->pmu_fixed_ctrs[1].counter_virt_prev;
210 } else {
211 counter_arr = env->pmu_fixed_ctrs[1].counter;
212 snapshot_prev = env->pmu_fixed_ctrs[1].counter_prev;
213 }
214
215 if (new_virt) {
216 g_assert(newpriv <= PRV_S);
217 snapshot_new = env->pmu_fixed_ctrs[1].counter_virt_prev;
218 } else {
219 snapshot_new = env->pmu_fixed_ctrs[1].counter_prev;
220 }
## assessment ##
We see in both cases the function is called with `new_virt=false`
But the bad case enters line 216 which is inside a `if (new_virt)`.
That is wrong, the assert should only be run if that is true.
So the gcc optimization breaks this.
Yes only in the lovely combination of emulating riscv on ppc64, but it does
change the code flow to what seems to be obviously wrong at first.
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2120835
Title:
EDK2 tests for riscv emulation fail against qemu 10.1 on ppc64el
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/edk2/+bug/2120835/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs