Message ID | 20210822035537.283193-6-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | linux-user: Clean up siginfo_t handling | expand |
On 8/22/21 5:55 AM, Richard Henderson wrote: > From: Peter Maydell <peter.maydell@linaro.org> > > In many places in the linux-user code we need to queue a signal for > the guest using the QEMU_SI_FAULT si_type. This requires that the > caller sets up and passes us a target_siginfo, including setting the > appropriate part of the _sifields union for the si_type. In a number > of places the code forgets to set the _sifields union field. > > Provide a new force_sig_fault() function, which does the same thing > as the Linux kernel function of that name -- it takes the signal > number, the si_code value and the address to use in > _sifields._sigfault, and assembles the target_siginfo itself. This > makes the callsites simpler and means it's harder to forget to pass > in an address value. > > We follow force_sig() and the kernel's force_sig_fault() in not > requiring the caller to pass in the CPU pointer but always acting > on the CPU of the current thread. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > Message-Id: <20210813131809.28655-6-peter.maydell@linaro.org> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > linux-user/signal-common.h | 1 + > linux-user/signal.c | 17 +++++++++++++++++ > 2 files changed, 18 insertions(+) > > diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h > index ea86328b28..536c7ac2c2 100644 > --- a/linux-user/signal-common.h > +++ b/linux-user/signal-common.h > @@ -40,6 +40,7 @@ void tswap_siginfo(target_siginfo_t *tinfo, > void set_sigmask(const sigset_t *set); > void force_sig(int sig); > void force_sigsegv(int oldsig); > +void force_sig_fault(int sig, int code, abi_ulong addr); > #if defined(TARGET_ARCH_HAS_SETUP_FRAME) > void setup_frame(int sig, struct target_sigaction *ka, > target_sigset_t *set, CPUArchState *env); > diff --git a/linux-user/signal.c b/linux-user/signal.c > index fd3c6a3e60..5ea8e4584a 100644 > --- a/linux-user/signal.c > +++ b/linux-user/signal.c > @@ -646,6 +646,23 @@ void force_sig(int sig) > queue_signal(env, info.si_signo, QEMU_SI_KILL, &info); > } > > +/* > + * Force a synchronously taken QEMU_SI_FAULT signal. For QEMU the > + * 'force' part is handled in process_pending_signals(). > + */ > +void force_sig_fault(int sig, int code, abi_ulong addr) > +{ > + CPUState *cpu = thread_cpu; > + CPUArchState *env = cpu->env_ptr; > + target_siginfo_t info = {}; > + > + info.si_signo = sig; > + info.si_errno = 0; > + info.si_code = code; > + info._sifields._sigfault._addr = addr; Maybe assign the members directly upon declaration? (to ease readability...) Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > + queue_signal(env, sig, QEMU_SI_FAULT, &info); > +} > + > /* Force a SIGSEGV if we couldn't write to memory trying to set > * up the signal frame. oldsig is the signal we were trying to handle > * at the point of failure. >
diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index ea86328b28..536c7ac2c2 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -40,6 +40,7 @@ void tswap_siginfo(target_siginfo_t *tinfo, void set_sigmask(const sigset_t *set); void force_sig(int sig); void force_sigsegv(int oldsig); +void force_sig_fault(int sig, int code, abi_ulong addr); #if defined(TARGET_ARCH_HAS_SETUP_FRAME) void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUArchState *env); diff --git a/linux-user/signal.c b/linux-user/signal.c index fd3c6a3e60..5ea8e4584a 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -646,6 +646,23 @@ void force_sig(int sig) queue_signal(env, info.si_signo, QEMU_SI_KILL, &info); } +/* + * Force a synchronously taken QEMU_SI_FAULT signal. For QEMU the + * 'force' part is handled in process_pending_signals(). + */ +void force_sig_fault(int sig, int code, abi_ulong addr) +{ + CPUState *cpu = thread_cpu; + CPUArchState *env = cpu->env_ptr; + target_siginfo_t info = {}; + + info.si_signo = sig; + info.si_errno = 0; + info.si_code = code; + info._sifields._sigfault._addr = addr; + queue_signal(env, sig, QEMU_SI_FAULT, &info); +} + /* Force a SIGSEGV if we couldn't write to memory trying to set * up the signal frame. oldsig is the signal we were trying to handle * at the point of failure.