On Thu, Oct 14, 2021 at 10:11 PM Richard Henderson < [email protected]> wrote:
> Split host_signal_pc and host_signal_write out of user-exec.c. > > Reviewed-by: Alistair Francis <[email protected]> > Signed-off-by: Richard Henderson <[email protected]> > --- > linux-user/host/riscv/host-signal.h | 85 +++++++++++++++++- > accel/tcg/user-exec.c | 134 ---------------------------- > 2 files changed, 84 insertions(+), 135 deletions(-) > Reviewed-by: Warner Losh <[email protected]> > diff --git a/linux-user/host/riscv/host-signal.h > b/linux-user/host/riscv/host-signal.h > index f4b4d65031..5860dce7d7 100644 > --- a/linux-user/host/riscv/host-signal.h > +++ b/linux-user/host/riscv/host-signal.h > @@ -1 +1,84 @@ > -#define HOST_SIGNAL_PLACEHOLDER > +/* > + * host-signal.h: signal info dependent on the host architecture > + * > + * Copyright (C) 2021 Linaro Limited > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or > later. > + * See the COPYING file in the top-level directory. > + */ > + > +#ifndef RISCV_HOST_SIGNAL_H > +#define RISCV_HOST_SIGNAL_H > + > +static inline uintptr_t host_signal_pc(ucontext_t *uc) > +{ > + return uc->uc_mcontext.__gregs[REG_PC]; > +} > + > +static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) > +{ > + uint32_t insn = *(uint32_t *)host_signal_pc(uc); > + > + /* > + * Detect store by reading the instruction at the program > + * counter. Note: we currently only generate 32-bit > + * instructions so we thus only detect 32-bit stores > + */ > + switch (((insn >> 0) & 0b11)) { > + case 3: > + switch (((insn >> 2) & 0b11111)) { > + case 8: > + switch (((insn >> 12) & 0b111)) { > + case 0: /* sb */ > + case 1: /* sh */ > + case 2: /* sw */ > + case 3: /* sd */ > + case 4: /* sq */ > + return true; > + default: > + break; > + } > + break; > + case 9: > + switch (((insn >> 12) & 0b111)) { > + case 2: /* fsw */ > + case 3: /* fsd */ > + case 4: /* fsq */ > + return true; > + default: > + break; > + } > + break; > + default: > + break; > + } > + } > + > + /* Check for compressed instructions */ > + switch (((insn >> 13) & 0b111)) { > + case 7: > + switch (insn & 0b11) { > + case 0: /*c.sd */ > + case 2: /* c.sdsp */ > + return true; > + default: > + break; > + } > + break; > + case 6: > + switch (insn & 0b11) { > + case 0: /* c.sw */ > + case 3: /* c.swsp */ > + return true; > + default: > + break; > + } > + break; > + default: > + break; > + } > + > + return false; > +} > + > +#endif > diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c > index 287f03dac5..2d9ab0a8b8 100644 > --- a/accel/tcg/user-exec.c > +++ b/accel/tcg/user-exec.c > @@ -139,64 +139,6 @@ bool handle_sigsegv_accerr_write(CPUState *cpu, > sigset_t *old_set, > } > } > > -/* > - * 'pc' is the host PC at which the exception was raised. > - * 'address' is the effective address of the memory exception. > - * 'is_write' is 1 if a write caused the exception and otherwise 0. > - * 'old_set' is the signal set which should be restored. > - */ > -static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info, > - int is_write, sigset_t *old_set) > -{ > - CPUState *cpu = current_cpu; > - CPUClass *cc; > - unsigned long host_addr = (unsigned long)info->si_addr; > - MMUAccessType access_type = adjust_signal_pc(&pc, is_write); > - abi_ptr guest_addr; > - > - /* For synchronous signals we expect to be coming from the vCPU > - * thread (so current_cpu should be valid) and either from running > - * code or during translation which can fault as we cross pages. > - * > - * If neither is true then something has gone wrong and we should > - * abort rather than try and restart the vCPU execution. > - */ > - if (!cpu || !cpu->running) { > - printf("qemu:%s received signal outside vCPU context @ pc=0x%" > - PRIxPTR "\n", __func__, pc); > - abort(); > - } > - > -#if defined(DEBUG_SIGNAL) > - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", > - pc, host_addr, is_write, *(unsigned long *)old_set); > -#endif > - > - /* Convert forcefully to guest address space, invalid addresses > - are still valid segv ones */ > - guest_addr = h2g_nocheck(host_addr); > - > - /* XXX: locking issue */ > - if (is_write && > - info->si_signo == SIGSEGV && > - info->si_code == SEGV_ACCERR && > - h2g_valid(host_addr) && > - handle_sigsegv_accerr_write(cpu, old_set, pc, guest_addr)) { > - return 1; > - } > - > - /* > - * There is no way the target can handle this other than raising > - * an exception. Undo signal and retaddr state prior to longjmp. > - */ > - sigprocmask(SIG_SETMASK, old_set, NULL); > - > - cc = CPU_GET_CLASS(cpu); > - cc->tcg_ops->tlb_fill(cpu, guest_addr, 0, access_type, > - MMU_USER_IDX, false, pc); > - g_assert_not_reached(); > -} > - > static int probe_access_internal(CPUArchState *env, target_ulong addr, > int fault_size, MMUAccessType > access_type, > bool nonfault, uintptr_t ra) > @@ -255,82 +197,6 @@ void *probe_access(CPUArchState *env, target_ulong > addr, int size, > return size ? g2h(env_cpu(env), addr) : NULL; > } > > -#if defined(__riscv) > - > -int cpu_signal_handler(int host_signum, void *pinfo, > - void *puc) > -{ > - siginfo_t *info = pinfo; > - ucontext_t *uc = puc; > - greg_t pc = uc->uc_mcontext.__gregs[REG_PC]; > - uint32_t insn = *(uint32_t *)pc; > - int is_write = 0; > - > - /* Detect store by reading the instruction at the program > - counter. Note: we currently only generate 32-bit > - instructions so we thus only detect 32-bit stores */ > - switch (((insn >> 0) & 0b11)) { > - case 3: > - switch (((insn >> 2) & 0b11111)) { > - case 8: > - switch (((insn >> 12) & 0b111)) { > - case 0: /* sb */ > - case 1: /* sh */ > - case 2: /* sw */ > - case 3: /* sd */ > - case 4: /* sq */ > - is_write = 1; > - break; > - default: > - break; > - } > - break; > - case 9: > - switch (((insn >> 12) & 0b111)) { > - case 2: /* fsw */ > - case 3: /* fsd */ > - case 4: /* fsq */ > - is_write = 1; > - break; > - default: > - break; > - } > - break; > - default: > - break; > - } > - } > - > - /* Check for compressed instructions */ > - switch (((insn >> 13) & 0b111)) { > - case 7: > - switch (insn & 0b11) { > - case 0: /*c.sd */ > - case 2: /* c.sdsp */ > - is_write = 1; > - break; > - default: > - break; > - } > - break; > - case 6: > - switch (insn & 0b11) { > - case 0: /* c.sw */ > - case 3: /* c.swsp */ > - is_write = 1; > - break; > - default: > - break; > - } > - break; > - default: > - break; > - } > - > - return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); > -} > -#endif > - > /* The softmmu versions of these helpers are in cputlb.c. */ > > /* > -- > 2.25.1 > >
