linux-user/host/riscv: Populate host_signal.h

Split host_signal_pc and host_signal_write out of user-exec.c.

Reviewed-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-09-17 10:57:06 -07:00
parent b12161120a
commit 97be8c6a95
2 changed files with 85 additions and 135 deletions

View File

@ -137,64 +137,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)
@ -253,82 +195,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. */
/*

View File

@ -1 +1,85 @@
#define HOST_SIGNAL_PLACEHOLDER
/*
* host-signal.h: signal info dependent on the host architecture
*
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2021 Linaro Limited
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 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