All of lore.kernel.org
 help / color / mirror / Atom feed
From: Warner Losh <imp@bsdimp.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: Kyle Evans <kevans@freebsd.org>, Stacey Son <sson@freebsd.org>,
	QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [PATCH 18/30] bsd-user/signal.c: Implement host_signal_handler
Date: Sun, 16 Jan 2022 13:52:38 -0700	[thread overview]
Message-ID: <CANCZdfrNHuoUY4M--O3qTSK2OwA_p=fjisvuMLq8S==+sNXN9Q@mail.gmail.com> (raw)
In-Reply-To: <CAFEAcA9RLjFON6A89j+gVoiRxehiwNpbsF5GpPL3z1EFhrHw1Q@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9051 bytes --]

On Thu, Jan 13, 2022 at 1:17 PM Peter Maydell <peter.maydell@linaro.org>
wrote:

> On Sun, 9 Jan 2022 at 16:40, Warner Losh <imp@bsdimp.com> wrote:
> >
> > Implement host_signal_handler to handle signals generated by the host
> > and to do safe system calls.
> >
> > Signed-off-by: Stacey Son <sson@FreeBSD.org>
> > Signed-off-by: Kyle Evans <kevans@freebsd.org>
> > Signed-off-by: Warner Losh <imp@bsdimp.com>
> > ---
> >  bsd-user/signal.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 105 insertions(+)
> >
> > diff --git a/bsd-user/signal.c b/bsd-user/signal.c
> > index b1331f63d61..a6e07277fb2 100644
> > --- a/bsd-user/signal.c
> > +++ b/bsd-user/signal.c
> > @@ -142,6 +142,111 @@ void force_sig_fault(int sig, int code, abi_ulong
> addr)
> >
> >  static void host_signal_handler(int host_sig, siginfo_t *info, void
> *puc)
> >  {
> > +    CPUState *cpu = thread_cpu;
> > +    CPUArchState *env = cpu->env_ptr;
> > +    int sig;
> > +    target_siginfo_t tinfo;
> > +    ucontext_t *uc = puc;
> > +    uintptr_t pc = 0;
> > +    bool sync_sig = false;
> > +
> > +    /*
> > +     * Non-spoofed SIGSEGV and SIGBUS are synchronous, and need special
> > +     * handling wrt signal blocking and unwinding.
> > +     */
> > +    if ((host_sig == SIGSEGV || host_sig == SIGBUS) && info->si_code >
> 0) {
> > +        MMUAccessType access_type;
> > +        uintptr_t host_addr;
> > +        abi_ptr guest_addr;
> > +        bool is_write;
> > +
> > +        host_addr = (uintptr_t)info->si_addr;
> > +
> > +        /*
> > +         * Convert forcefully to guest address space: addresses outside
> > +         * reserved_va are still valid to report via SEGV_MAPERR.
> > +         */
> > +        guest_addr = h2g_nocheck(host_addr);
> > +
> > +        pc = host_signal_pc(uc);
> > +        is_write = host_signal_write(info, uc);
> > +        access_type = adjust_signal_pc(&pc, is_write);
> > +
> > +        if (host_sig == SIGSEGV) {
> > +            bool maperr = true;
> > +
> > +            if (info->si_code == SEGV_ACCERR && h2g_valid(host_addr)) {
> > +                /* If this was a write to a TB protected page, restart.
> */
> > +                if (is_write &&
> > +                    handle_sigsegv_accerr_write(cpu, &uc->uc_sigmask,
> > +                                                pc, guest_addr)) {
> > +                    return;
> > +                }
> > +
> > +                /*
> > +                 * With reserved_va, the whole address space is
> PROT_NONE,
> > +                 * which means that we may get ACCERR when we want
> MAPERR.
> > +                 */
> > +                if (page_get_flags(guest_addr) & PAGE_VALID) {
> > +                    maperr = false;
> > +                } else {
> > +                    info->si_code = SEGV_MAPERR;
> > +                }
> > +            }
> > +
> > +            sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
> > +            cpu_loop_exit_sigsegv(cpu, guest_addr, access_type, maperr,
> pc);
> > +        } else {
> > +            sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
> > +            if (info->si_code == BUS_ADRALN) {
> > +                cpu_loop_exit_sigbus(cpu, guest_addr, access_type, pc);
> > +            }
> > +        }
> > +
> > +        sync_sig = true;
> > +    }
> > +
> > +    /* Get the target signal number. */
> > +    sig = host_to_target_signal(host_sig);
> > +    if (sig < 1 || sig > TARGET_NSIG) {
> > +        return;
> > +    }
> > +    trace_user_host_signal(cpu, host_sig, sig);
> > +
> > +    host_to_target_siginfo_noswap(&tinfo, info);
> > +
> > +    queue_signal(env, sig, &tinfo);       /* XXX how to cope with
> failure? */
>
> queue_signal() can't fail, so there is nothing to cope with.
> (Your bsd-user version even has the right 'void' type --
> linux-user's returns 1 always and we never look at the return
> value, so we should really switch that to void return too.)
>

Submitted a patch to that last bit. I'll remove this comment in the rework
I'm doing.


> > +    /*
> > +     * Linux does something else here -> the queue signal may be wrong,
> but
> > +     * maybe not.  And then it does the rewind_if_in_safe_syscall
> > +     */
>
> I think you have here a bit of a mix of linux-user's current design
> and some older (broken) version. This is how linux-user works today:
>

Yes. I think we forked bsd-user from linux-user around 2015 and the old
design dropped signal queueing in 2016 if I'm reading git log correctly.


>  * queue_signal() is a little bit misnamed, because there is no
>    "queue" here: there can only be at most one "queued" signal,
>    and it lives in the TaskState struct (which is user-only specific
>    information that hangs off the guest CPU struct) as the
>    TaskState::sync_signal field. The reason
>    we only have one at once is that queue_signal() is used only
>    for signals generated by QEMU itself by calling queue_signal()
>    directly or indirectly from the cpu_loop() code. The cpu loop
>    always calls process_pending_signals() at the end of its loop,
>    which will pick up a queued signal. We never call queue_signal()
>    twice in a row before getting back to process_pending_signals(),
>    so there's only ever at most one thing in the "queue".
>  * for all signals we get from the host except SIGSEGV/SIGBUS,
>    we track whether there's a host signal pending in the
>    TaskState::sigtab[] array (which is indexed by signal number).
>    We block all host signals except SIGSEGV/SIGBUS before calling
>    cpu_exit(), so we know we're not going to get more than one
>    of these at once (and it won't clash with a queue_signal()
>    signal either, as those use the sync_signal field, not the
>    sigtab[]).
>  * for host-sent non-spoofed (ie not sent via 'kill()') SIGSEGV/SIGBUS,
>    we know this was caused by a bit of generated code, so we just
>    use cpu_loop_exit_restore() to turn this into an EXCP_INTERRUPT
>    at the right guest PC
>
> I feel fairly strongly that you definitely want to use the same
> design as current linux-user does for signals:
>  * getting this right is pretty tricky, and even if we get two
>    different designs to both have the same semantics it's going
>    to be pretty confusing
>  * we thought quite hard about the linux-user code at the time
>    and it's definitely less buggy than the previous design
>  * It's much easier to review the bsd-user code as "yes this is
>    doing the same thing linux-user does" than working through
>    a different approach from first principles
>

I agree. I like that design better than what's in bsd-user today and
seems simpler to implement and get right. I'd add a 4th bullet point
"It's easier to share code, either directly or via copying"


> I don't have as strong an opinion on whether we should try to get
> it into the tree that way from the start, or to put in whatever
> you have currently and then fix it later. (More accurately,
> I would prefer to review patches which use the same design
> as linux-user but if that's going to be massively painful/slow
> for you to get something upstream doing it that way around
> I can probably live with the other approach...)
>

I'm going to start down that path and see if I can rework the patches
and see if it solves some of the regressions we've seen in bsd-user
between 6.1 and 6.2 as the signal stuff was reworked in linux-user
to cope better with sigsegv and sigbus. If that works out OK, then
I'll move forward with adjusting the fork and reflect that back into
this patch series.


> > +    /*
> > +     * For synchronous signals, unwind the cpu state to the faulting
> > +     * insn and then exit back to the main loop so that the signal
> > +     * is delivered immediately.
> > +     XXXX Should this be in queue_signal?
>
> No, because queue_signal() is called for lots of ways to pend
> a signal, most of which aren't real host signals.
>

OK. I now agree after reading the code.


> > +     */
> > +    if (sync_sig) {
> > +        cpu->exception_index = EXCP_INTERRUPT;
> > +        cpu_loop_exit_restore(cpu, pc);
> > +    }
> > +
> > +    rewind_if_in_safe_syscall(puc);
> > +
> > +    /*
> > +     * Block host signals until target signal handler entered. We
> > +     * can't block SIGSEGV or SIGBUS while we're executing guest
> > +     * code in case the guest code provokes one in the window between
> > +     * now and it getting out to the main loop. Signals will be
> > +     * unblocked again in process_pending_signals().
> > +     */
> > +    sigfillset(&uc->uc_sigmask);
> > +    sigdelset(&uc->uc_sigmask, SIGSEGV);
> > +    sigdelset(&uc->uc_sigmask, SIGBUS);
> > +
> > +    /* Interrupt the virtual CPU as soon as possible. */
> > +    cpu_exit(thread_cpu);
> >  }
> >
> >  void signal_init(void)
>
> thanks
>

Thank you for the insight and places to focus on making this code better.
It's
a bit hard to discover all this just from reading code in any sane amount
of time
and it is both quite helpful and much appreciated.

Warner

[-- Attachment #2: Type: text/html, Size: 12181 bytes --]

  reply	other threads:[~2022-01-16 20:54 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-09 16:18 [PATCH 00/30] bsd-user: upstream our signal implementation Warner Losh
2022-01-09 16:18 ` [PATCH 01/30] bsd-user/arm/target_arch_cpu.h: Move EXCP_ATOMIC to match linux-user Warner Losh
2022-01-13 15:47   ` Peter Maydell
2022-01-23 21:30   ` Richard Henderson
2022-01-09 16:18 ` [PATCH 02/30] bsd-user/signal.c: implement force_sig_fault Warner Losh
2022-01-13 16:43   ` Peter Maydell
2022-01-23 21:36   ` Richard Henderson
2022-01-09 16:18 ` [PATCH 03/30] bsd-user/signal.c: Implement cpu_loop_exit_sigsegv Warner Losh
2022-01-13 17:00   ` Peter Maydell
2022-01-23 21:38   ` Richard Henderson
2022-01-09 16:18 ` [PATCH 04/30] bsd-user/signal.c: implement cpu_loop_exit_sigbus Warner Losh
2022-01-13 17:00   ` Peter Maydell
2022-01-23 21:38   ` Richard Henderson
2022-01-09 16:18 ` [PATCH 05/30] bsd-user/arm/arget_arch_cpu.h: Move EXCP_DEBUG and EXCP_BKPT together Warner Losh
2022-01-13 17:13   ` Peter Maydell
2022-01-14  6:33     ` Warner Losh
2022-01-23 21:40   ` Richard Henderson
2022-01-09 16:18 ` [PATCH 06/30] bsd-user/arm/target_arch_cpu.h: Correct code pointer Warner Losh
2022-01-13 17:15   ` Peter Maydell
2022-01-14  6:38     ` Warner Losh
2022-01-14 10:22       ` Peter Maydell
2022-01-17  4:12         ` Warner Losh
2022-01-23 21:43   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 07/30] bsd-user/arm/target_arch_cpu.h: Use force_sig_fault for EXCP_UDEF Warner Losh
2022-01-13 17:19   ` Peter Maydell
2022-01-23 22:07     ` Richard Henderson
2022-01-09 16:19 ` [PATCH 08/30] bsd-user/arm/target_arch_cpu.h: Implement data faults Warner Losh
2022-01-13 17:40   ` Peter Maydell
2022-01-14 18:13     ` Warner Losh
2022-01-14 18:21       ` Peter Maydell
2022-01-24  1:12   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 09/30] bsd-user/signal.c: implement abstract target / host signal translation Warner Losh
2022-01-13 17:44   ` Peter Maydell
2022-01-14 18:27     ` Warner Losh
2022-01-09 16:19 ` [PATCH 10/30] bsd-user/signal.c: Implement signal_init() Warner Losh
2022-01-13 19:28   ` Peter Maydell
2022-01-14 18:51     ` Warner Losh
2022-01-24  1:38   ` Richard Henderson
2022-01-24 21:35     ` Warner Losh
2022-01-09 16:19 ` [PATCH 11/30] bsd-user/host/arm/host-signal.h: Implement host_signal_* Warner Losh
2022-01-13 19:32   ` Peter Maydell
2022-01-17  3:53     ` Warner Losh
2022-01-09 16:19 ` [PATCH 12/30] bsd-user/host/i386/host-signal.h: " Warner Losh
2022-01-13 19:33   ` Peter Maydell
2022-01-24  1:49   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 13/30] bsd-user/host/x86_64/host-signal.h: " Warner Losh
2022-01-13 19:33   ` Peter Maydell
2022-01-24  1:52   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 14/30] bsd-user: Add host signals to the build Warner Losh
2022-01-13 19:35   ` Peter Maydell
2022-01-24  1:56   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 15/30] bsd-user: Add trace events for bsd-usr Warner Losh
2022-01-13 19:37   ` Peter Maydell
2022-01-24  1:57   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 16/30] bsd-user/signal.c: host_to_target_siginfo_noswap Warner Losh
2022-01-13 19:43   ` Peter Maydell
2022-01-15  6:19     ` Warner Losh
2022-01-15 11:08       ` Peter Maydell
2022-01-24  2:05   ` Richard Henderson
2022-01-24 21:45     ` Warner Losh
2022-01-09 16:19 ` [PATCH 17/30] bsd-user/signal.c: Implement rewind_if_in_safe_syscall Warner Losh
2022-01-13 19:44   ` Peter Maydell
2022-01-24  2:09   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 18/30] bsd-user/signal.c: Implement host_signal_handler Warner Losh
2022-01-13 20:17   ` Peter Maydell
2022-01-16 20:52     ` Warner Losh [this message]
2022-01-09 16:19 ` [PATCH 19/30] bsd-user/strace.c: print_taken_signal Warner Losh
2022-01-13 20:20   ` Peter Maydell
2022-01-24  2:45   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 20/30] bsd-user/signal.c: core_dump_signal Warner Losh
2022-01-13 20:22   ` Peter Maydell
2022-01-13 20:28     ` Warner Losh
2022-01-13 20:40       ` Peter Maydell
2022-01-24  3:01   ` Richard Henderson
2022-01-09 16:19 ` [PATCH 21/30] bsd-user/signal.c: force_sig Warner Losh
2022-01-13 20:29   ` Peter Maydell
2022-01-13 20:53     ` Peter Maydell
2022-01-13 23:04       ` Kyle Evans
2022-01-18 22:27         ` Warner Losh
2022-01-09 16:19 ` [PATCH 22/30] bsd-user/signal.c: Fill in queue_signal Warner Losh
2022-01-13 20:37   ` Peter Maydell
2022-01-17 16:22     ` Warner Losh
2022-01-17 16:33       ` Peter Maydell
2022-01-09 16:19 ` [PATCH 23/30] bsd-user/signal.c: sigset manipulation routines Warner Losh
2022-01-14 11:13   ` Peter Maydell
2022-01-22 16:44     ` Warner Losh
2022-01-22 18:00       ` Kyle Evans
2022-01-09 16:19 ` [PATCH 24/30] bsd-user/signal.c: setup_frame Warner Losh
2022-01-14 11:40   ` Peter Maydell
2022-01-17  6:58     ` Warner Losh
2022-01-17  7:24       ` Warner Losh
2022-01-09 16:19 ` [PATCH 25/30] bsd-user/signal.c: handle_pending_signal Warner Losh
2022-01-14 11:50   ` Peter Maydell
2022-01-09 16:19 ` [PATCH 26/30] bsd-user/signal.c: tswap_siginfo Warner Losh
2022-01-14 11:54   ` Peter Maydell
2022-01-09 16:19 ` [PATCH 27/30] bsd-user/signal.c: process_pending_signals Warner Losh
2022-01-14 11:55   ` Peter Maydell
2022-01-17  2:09     ` Warner Losh
2022-01-09 16:19 ` [PATCH 28/30] bsd-user/signal.c: implement do_sigreturn Warner Losh
2022-01-14 12:12   ` Peter Maydell
2022-01-09 16:19 ` [PATCH 29/30] bsd-user/signal.c: implement do_sigaction Warner Losh
2022-01-14 13:13   ` Peter Maydell
2022-01-09 16:19 ` [PATCH 30/30] bsd-user/signal.c: do_sigaltstack Warner Losh
2022-01-14 13:18   ` Peter Maydell
2022-01-22 22:20     ` Warner Losh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CANCZdfrNHuoUY4M--O3qTSK2OwA_p=fjisvuMLq8S==+sNXN9Q@mail.gmail.com' \
    --to=imp@bsdimp.com \
    --cc=kevans@freebsd.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sson@freebsd.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.