From patchwork Mon Jan 23 02:17:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 718338 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3v6Fk13mWyz9s5g for ; Mon, 23 Jan 2017 13:33:45 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ATprO1rZ"; dkim-atps=neutral Received: from localhost ([::1]:38707 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cVURy-0004Jk-SX for incoming@patchwork.ozlabs.org; Sun, 22 Jan 2017 21:33:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46649) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cVUD0-0007o0-92 for qemu-devel@nongnu.org; Sun, 22 Jan 2017 21:18:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cVUCz-0004vM-0A for qemu-devel@nongnu.org; Sun, 22 Jan 2017 21:18:14 -0500 Received: from mail-qt0-x242.google.com ([2607:f8b0:400d:c0d::242]:35579) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cVUCy-0004vH-RL for qemu-devel@nongnu.org; Sun, 22 Jan 2017 21:18:12 -0500 Received: by mail-qt0-x242.google.com with SMTP id f4so14077454qte.2 for ; Sun, 22 Jan 2017 18:18:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=2bC8a9/rGn+luCT59gAIeEgKIlcksXC/VsqG6CJ3mLo=; b=ATprO1rZdqkiJfGTYR1hnkpWKhIrtHoPLB5EKlOoo5PYnjz3WbUblw2jWZcRiIEykm MZReRp01tA5ffJ5k5+rlz57JC75PRYrWPaAXFzEVOCskV7AvnsvgpMVYMaeIyHoITrSI LO0KQewKcABfmioZ5/FUV+IcIt3ygWNALCoaXmW/R+G+LgllFl1qnuMhu1s9N5ZT1AHZ 1OswqmZK52dcLgTiu9c9Q9JiN9tGdfe+9cXEl2Uo9TWKtbAJ+JkpmA572+Bo29ketYgn m2tHUDEXBTlEByusDzDDEdzREi3TxhDPMPLCCnGLd18xXIpylihPoyJC0VeX9DhQPuIq AMHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=2bC8a9/rGn+luCT59gAIeEgKIlcksXC/VsqG6CJ3mLo=; b=aVbgHYCD9sAiXQz2lpIACSd3otyvAHdmfCUhrSNCPPLpURuOkjVWgwoiEcpmQP7ECH 49HcgPTZe9oweN6TNgtCo+1oQ3FH4dwKKhUT7KMb0qaDTSAXbkymW7lsqXMiy7j3fDxx nwfakYL29e62a2UV1Zkbm9TS78Ss/4ywJJZSIHStAEUdgAZQQJsX3zfnrEbMw1QpD0um sWjGX0v8Yi0n5f5QllYHFVZQbZunpZ/wPxZknCib+I90AE5pSM0D302SgXekBsX9YF7q 5WHLPCisXkS44nmbWnjapIYyoyc0ZAQ19eJVdxujVr6I+Y8hc4OzGZm0BxASNggKVcHO pjRA== X-Gm-Message-State: AIkVDXIeozvFxrdj3fYb6NdeyHiqcoST6Q1gwwVKXrjTFGIVlkZZaf4zvknWCUPXL87+Aw== X-Received: by 10.200.37.183 with SMTP id e52mr22655408qte.166.1485137892231; Sun, 22 Jan 2017 18:18:12 -0800 (PST) Received: from bigtime.twiddle.net.com ([2602:47:d954:1500:5e51:4fff:fe40:9c64]) by smtp.gmail.com with ESMTPSA id m85sm12097734qkl.28.2017.01.22.18.18.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 22 Jan 2017 18:18:11 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sun, 22 Jan 2017 18:17:37 -0800 Message-Id: <20170123021748.13170-16-rth@twiddle.net> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170123021748.13170-1-rth@twiddle.net> References: <20170123021748.13170-1-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400d:c0d::242 Subject: [Qemu-devel] [PULL 15/26] linux-user: Add HPPA signal handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- linux-user/signal.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 1 deletion(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index c750053..0a5bb4e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5888,6 +5888,195 @@ long do_rt_sigreturn(CPUTLGState *env) return -TARGET_QEMU_ESIGRETURN; } +#elif defined(TARGET_HPPA) + +struct target_sigcontext { + abi_ulong sc_flags; + abi_ulong sc_gr[32]; + uint64_t sc_fr[32]; + abi_ulong sc_iasq[2]; + abi_ulong sc_iaoq[2]; + abi_ulong sc_sar; +}; + +struct target_ucontext { + abi_uint tuc_flags; + abi_ulong tuc_link; + target_stack_t tuc_stack; + abi_uint pad[1]; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + abi_uint tramp[9]; + target_siginfo_t info; + struct target_ucontext uc; + /* hidden location of upper halves of pa2.0 64-bit gregs */ +}; + +static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env) +{ + int flags = 0; + int i; + + /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */ + + if (env->iaoq_f < TARGET_PAGE_SIZE) { + /* In the gateway page, executing a syscall. */ + flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */ + __put_user(env->gr[31], &sc->sc_iaoq[0]); + __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]); + } else { + __put_user(env->iaoq_f, &sc->sc_iaoq[0]); + __put_user(env->iaoq_b, &sc->sc_iaoq[1]); + } + __put_user(0, &sc->sc_iasq[0]); + __put_user(0, &sc->sc_iasq[1]); + __put_user(flags, &sc->sc_flags); + + __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]); + for (i = 1; i < 32; ++i) { + __put_user(env->gr[i], &sc->sc_gr[i]); + } + + __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]); + for (i = 1; i < 32; ++i) { + __put_user(env->fr[i], &sc->sc_fr[i]); + } + + __put_user(env->sar, &sc->sc_sar); +} + +static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc) +{ + target_ulong psw; + int i; + + __get_user(psw, &sc->sc_gr[0]); + cpu_hppa_put_psw(env, psw); + + for (i = 1; i < 32; ++i) { + __get_user(env->gr[i], &sc->sc_gr[i]); + } + for (i = 0; i < 32; ++i) { + __get_user(env->fr[i], &sc->sc_fr[i]); + } + cpu_hppa_loaded_fr0(env); + + __get_user(env->iaoq_f, &sc->sc_iaoq[0]); + __get_user(env->iaoq_b, &sc->sc_iaoq[1]); + __get_user(env->sar, &sc->sc_sar); +} + +/* No, this doesn't look right, but it's copied straight from the kernel. */ +#define PARISC_RT_SIGFRAME_SIZE32 \ + ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64) + +static void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env) +{ + abi_ulong frame_addr, sp, haddr; + struct target_rt_sigframe *frame; + int i; + + sp = env->gr[30]; + if (ka->sa_flags & TARGET_SA_ONSTACK) { + if (sas_ss_flags(sp) == 0) { + sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f; + } + } + frame_addr = QEMU_ALIGN_UP(sp, 64); + sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32; + + trace_user_setup_rt_frame(env, frame_addr); + + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + tswap_siginfo(&frame->info, info); + frame->uc.tuc_flags = 0; + frame->uc.tuc_link = 0; + + __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); + __put_user(sas_ss_flags(get_sp_from_cpustate(env)), + &frame->uc.tuc_stack.ss_flags); + __put_user(target_sigaltstack_used.ss_size, + &frame->uc.tuc_stack.ss_size); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); + } + + setup_sigcontext(&frame->uc.tuc_mcontext, env); + + __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */ + __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */ + __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */ + __put_user(0x08000240, frame->tramp + 3); /* nop */ + + unlock_user_struct(frame, frame_addr, 1); + + env->gr[2] = h2g(frame->tramp); + env->gr[30] = sp; + env->gr[26] = sig; + env->gr[25] = h2g(&frame->info); + env->gr[24] = h2g(&frame->uc); + + haddr = ka->_sa_handler; + if (haddr & 2) { + /* Function descriptor. */ + target_ulong *fdesc, dest; + + haddr &= -4; + if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) { + goto give_sigsegv; + } + __get_user(dest, fdesc); + __get_user(env->gr[19], fdesc + 1); + unlock_user_struct(fdesc, haddr, 1); + haddr = dest; + } + env->iaoq_f = haddr; + env->iaoq_b = haddr + 4;; + return; + + give_sigsegv: + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPUArchState *env) +{ + abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32; + struct target_rt_sigframe *frame; + sigset_t set; + + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + target_to_host_sigset(&set, &frame->uc.tuc_sigmask); + set_sigmask(&set); + + restore_sigcontext(env, &frame->uc.tuc_mcontext); + unlock_user_struct(frame, frame_addr, 0); + + if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, + uc.tuc_stack), + 0, env->gr[30]) == -EFAULT) { + goto badframe; + } + + unlock_user_struct(frame, frame_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + + badframe: + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; +} + #else static void setup_frame(int sig, struct target_sigaction *ka, @@ -5989,7 +6178,7 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig, /* prepare the stack frame of the virtual CPU */ #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \ || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \ - || defined(TARGET_PPC64) + || defined(TARGET_PPC64) || defined(TARGET_HPPA) /* These targets do not have traditional signals. */ setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env); #else