Browse Source

linux-user/riscv: Propagate fault address

The CPU loop tagged all the queued signals as QEMU_SI_KILL while it was
filling the `_sigfault` part of `siginfo`: this caused QEMU to copy the
wrong fields over to the userspace program.

Make sure the fault address recorded by the MMU is is stored in the CPU
environment structure.

In case of memory faults store the exception address into `siginfo`.

Signed-off-by: Giuseppe Musacchio <thatlemon@gmail.com>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Giuseppe Musacchio 5 years ago
parent
commit
2921343b3d
2 changed files with 6 additions and 2 deletions
  1. 2 1
      linux-user/riscv/cpu_loop.c
  2. 4 1
      target/riscv/cpu_helper.c

+ 2 - 1
linux-user/riscv/cpu_loop.c

@@ -89,6 +89,7 @@ void cpu_loop(CPURISCVState *env)
         case RISCV_EXCP_STORE_PAGE_FAULT:
         case RISCV_EXCP_STORE_PAGE_FAULT:
             signum = TARGET_SIGSEGV;
             signum = TARGET_SIGSEGV;
             sigcode = TARGET_SEGV_MAPERR;
             sigcode = TARGET_SEGV_MAPERR;
+            sigaddr = env->badaddr;
             break;
             break;
         case EXCP_DEBUG:
         case EXCP_DEBUG:
         gdbstep:
         gdbstep:
@@ -108,7 +109,7 @@ void cpu_loop(CPURISCVState *env)
                 .si_code = sigcode,
                 .si_code = sigcode,
                 ._sifields._sigfault._addr = sigaddr
                 ._sifields._sigfault._addr = sigaddr
             };
             };
-            queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
+            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
         }
         }
 
 
         process_pending_signals(env);
         process_pending_signals(env);

+ 4 - 1
target/riscv/cpu_helper.c

@@ -455,9 +455,9 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                         MMUAccessType access_type, int mmu_idx,
                         MMUAccessType access_type, int mmu_idx,
                         bool probe, uintptr_t retaddr)
                         bool probe, uintptr_t retaddr)
 {
 {
-#ifndef CONFIG_USER_ONLY
     RISCVCPU *cpu = RISCV_CPU(cs);
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     CPURISCVState *env = &cpu->env;
+#ifndef CONFIG_USER_ONLY
     hwaddr pa = 0;
     hwaddr pa = 0;
     int prot;
     int prot;
     bool pmp_violation = false;
     bool pmp_violation = false;
@@ -508,7 +508,10 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     case MMU_DATA_STORE:
     case MMU_DATA_STORE:
         cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
         cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
         break;
         break;
+    default:
+        g_assert_not_reached();
     }
     }
+    env->badaddr = address;
     cpu_loop_exit_restore(cs, retaddr);
     cpu_loop_exit_restore(cs, retaddr);
 #endif
 #endif
 }
 }