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

Reply via email to