From patchwork Thu May 3 21:39:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 134922 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp85814lji; Thu, 3 May 2018 14:40:03 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqyBrxrqsygSWZEvAi81b/2u46JNi5RPM4O1++DNR7cIOHWv+RYTGn61eoz5NyfF4qZUTmo X-Received: by 10.55.31.24 with SMTP id f24mr20679559qkf.442.1525383603711; Thu, 03 May 2018 14:40:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525383603; cv=none; d=google.com; s=arc-20160816; b=znwSR0172wkJuy74JPIBXN1hu/OzDO1GxzcV8ekx9tenEVVJDy8mX8UuMTDUd/Kqr2 N5Ehc7rsJFdhmCIfiKiUo4vzjgRA4vibp+BZsj0XMsNchHWTGCBiCEmrbxYrOHDV75cI xHQX6eJRfUMe7nHKaoIJiEs5eHheFd+nndGlnmvxFVJ50daqAO0w5PSP7ARaec8aiDnl IGMH/rYCuU6iRHXvO3KA149B255ZQgYHPSH3qHvfLyXv78Ael2oLXwf1rIJSAcRAWBFf ayF+OvlNbc918Kf4cuQ0G4tQG7JNEmeX5upExTh7914pFmLiTX+91O8SgRebwY62rmLm O0XQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:arc-authentication-results; bh=FUn/eg1viLId54H1zVI0K0ZwOIZorK8kurxSMzQaV/c=; b=fRIDm7nMvUmCqNYE7faq5ezzGPTGHjUVyxY9DpED4Fdpd3+Xrct75dRPPXkSiIK6MC FyIyeGJ5FXZhXT3JHrWxFsVkhUb1V5CYU+XFtnksTaG/n2MUYJOlLSmF8Y9M6KmEyoeH w96oqkRmxuAGyRQNgI4RyMRxZtI4NfyDpP9GYotQQbaY78mdCPFvcI7I7KfFbi3nfJZS yQ7nNJyLokhAmUpsMan4TmjV/cX176KZDIC7YaKmLvgaR1fSkIlFZb+1uSoi0r59mhAP JaotHblYQ7DxLu5f/EE98+jFo1XLs0Ly/NhztlvLaClDkRFTrttR8nRTbkUTIMdjHZ/H dSdQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id p142si8430734qke.78.2018.05.03.14.40.03 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 03 May 2018 14:40:03 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:59201 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fELxL-0004jt-4e for patch@linaro.org; Thu, 03 May 2018 17:40:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54809) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fELwo-0004jD-9a for qemu-devel@nongnu.org; Thu, 03 May 2018 17:39:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fELwk-00055i-8Q for qemu-devel@nongnu.org; Thu, 03 May 2018 17:39:30 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:46273) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fELwj-00052j-Rf for qemu-devel@nongnu.org; Thu, 03 May 2018 17:39:26 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue105 [212.227.15.183]) with ESMTPSA (Nemesis) id 0M9XrD-1f3g2n1NvD-00Cw7t; Thu, 03 May 2018 23:39:14 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Thu, 3 May 2018 23:39:01 +0200 Message-Id: <20180503213903.30335-5-laurent@vivier.eu> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180503213903.30335-1-laurent@vivier.eu> References: <20180503213903.30335-1-laurent@vivier.eu> MIME-Version: 1.0 X-Provags-ID: V03:K1:+h1q2GPJwbr6rO7T1imoa8FhgOYdKWFha1OlvG5Kxr+OOHu8lUr U9968Igd6nVDiBjJMFzT+x8MkgVToQBXzv8oWKpSu+TbUrmLwIJqmh/2jYONjE35jD7Wbz/ K+TsVud8rbZ2zf3i1zCvQmGrPvk7OrHkj+zMGZ/L7wPidzZZZcB/Rv43ZmAeJXsAmYua1Xt HqQXA+R4Iuro2b2nKl3Ug== X-UI-Out-Filterresults: notjunk:1; V01:K0:xqdIkOFFe5o=:HJ8d340aiUDXH4IZSesoNI L60ZW77KkKBjphSFlYFGT9RfM3tlGQabwq6KmAe22zCUizMw8N2zL5rtRC8PzDtZ/xe0LZpKU pgr13gO4wGN0yEnrFWm592zIQFJU43uJhM3hEcFDD+jNu8HJjIaYK6sG9GLQ176Rm2Xtl6an0 44EfwzXaue9icIfxdeYzgiUz+zJ4vXBT8tCDzw4AEUwRbnez6kYgAkXgGkVGwGXXFemu0Vjvm PrmfTZvbOr4XvDZ2yguoX+L9QzgrbFgZe0IG/ODV0Gcr3PoMMOpxT065npbC1d32azdVgB7Iw UK4vzHLMApDgO41OL52zEE1jFRTLglGv35/io4iFFwAaPh7lGOMEhNlRg24llf4HTl78X3UNN 0mekewMRRgH2bGYjqXHe5A1gvhuBV3IixkpwaNkMLbwSF2nvHxIBBwyNvr69orAdJLIHVfXos uC9vGzwemrR0dUHuKJi3zx41Jh6IebBKqvZto/IgUjUnbM34EKPx39rRR2wSAyqdreFvuNTj1 eSfma8g//gLBTaP4WD9GS4ObxqdRy+Ah0CqQSHWUcOrAFjwYS3OinctBMaEL4mv5kW+u7fK1b 8bpOJcGgeHi/gU69fZNAMb9aaqJy+wopAU8/dARMMvKj+SuHQCYFBjQJCqLIllRcX3JR0EUCm pSKPU2MhIGh2QZQqqAUtPiMbKIPHXqp9kOWpuJimYlgIO/e3UmS6KQXq9lBSTQLohL9jdL9df yE2lRG8jIzdQZc0M X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.73 Subject: [Qemu-devel] [PULL 4/6] linux-user: ARM-FDPIC: Add support for signals for FDPIC targets 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: Christophe Lyon , Riku Voipio , Laurent Vivier Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Christophe Lyon The FDPIC restorer needs to deal with a function descriptor, hence we have to extend 'retcode' such that it can hold the instructions needed to perform this. The restorer sequence uses the same thumbness as the exception handler (mainly to support Thumb-only architectures). Co-Authored-By: Mickaël Guêné Signed-off-by: Christophe Lyon Reviewed-by: Peter Maydell Message-Id: <20180430080404.7323-5-christophe.lyon@st.com> [lv: moved the change to linux-user/arm/signal.c] Signed-off-by: Laurent Vivier --- linux-user/arm/signal.c | 105 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 16 deletions(-) -- 2.14.3 diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index 0c1ec53025..eb72be5dd0 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -102,13 +102,13 @@ struct sigframe_v1 { struct target_sigcontext sc; abi_ulong extramask[TARGET_NSIG_WORDS-1]; - abi_ulong retcode; + abi_ulong retcode[4]; }; struct sigframe_v2 { struct target_ucontext_v2 uc; - abi_ulong retcode; + abi_ulong retcode[4]; }; struct rt_sigframe_v1 @@ -117,14 +117,14 @@ struct rt_sigframe_v1 abi_ulong puc; struct target_siginfo info; struct target_ucontext_v1 uc; - abi_ulong retcode; + abi_ulong retcode[4]; }; struct rt_sigframe_v2 { struct target_siginfo info; struct target_ucontext_v2 uc; - abi_ulong retcode; + abi_ulong retcode[4]; }; #define TARGET_CONFIG_CPU_32 1 @@ -147,6 +147,21 @@ static const abi_ulong retcodes[4] = { SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN }; +/* + * Stub needed to make sure the FD register (r9) contains the right + * value. + */ +static const unsigned long sigreturn_fdpic_codes[3] = { + 0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */ + 0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */ + 0xe59cf000 /* ldr pc, [r12] to jump into restorer */ +}; + +static const unsigned long sigreturn_fdpic_thumb_codes[3] = { + 0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */ + 0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */ + 0xf000f8dc /* ldr pc, [r12] to jump into restorer */ +}; static inline int valid_user_regs(CPUARMState *regs) { @@ -200,13 +215,33 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize) return (sp - framesize) & ~7; } -static void +static int setup_return(CPUARMState *env, struct target_sigaction *ka, abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr) { - abi_ulong handler = ka->_sa_handler; + abi_ulong handler = 0; + abi_ulong handler_fdpic_GOT = 0; abi_ulong retcode; - int thumb = handler & 1; + + int thumb; + int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info); + + if (is_fdpic) { + /* In FDPIC mode, ka->_sa_handler points to a function + * descriptor (FD). The first word contains the address of the + * handler. The second word contains the value of the PIC + * register (r9). */ + abi_ulong funcdesc_ptr = ka->_sa_handler; + if (get_user_ual(handler, funcdesc_ptr) + || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) { + return 1; + } + } else { + handler = ka->_sa_handler; + } + + thumb = handler & 1; + uint32_t cpsr = cpsr_read(env); cpsr &= ~CPSR_IT; @@ -217,7 +252,28 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, } if (ka->sa_flags & TARGET_SA_RESTORER) { - retcode = ka->sa_restorer; + if (is_fdpic) { + /* For FDPIC we ensure that the restorer is called with a + * correct r9 value. For that we need to write code on + * the stack that sets r9 and jumps back to restorer + * value. + */ + if (thumb) { + __put_user(sigreturn_fdpic_thumb_codes[0], rc); + __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1); + __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2); + __put_user((abi_ulong)ka->sa_restorer, rc + 3); + } else { + __put_user(sigreturn_fdpic_codes[0], rc); + __put_user(sigreturn_fdpic_codes[1], rc + 1); + __put_user(sigreturn_fdpic_codes[2], rc + 2); + __put_user((abi_ulong)ka->sa_restorer, rc + 3); + } + + retcode = rc_addr + thumb; + } else { + retcode = ka->sa_restorer; + } } else { unsigned int idx = thumb; @@ -231,10 +287,15 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, } env->regs[0] = usig; + if (is_fdpic) { + env->regs[9] = handler_fdpic_GOT; + } env->regs[13] = frame_addr; env->regs[14] = retcode; env->regs[15] = handler & (thumb ? ~1 : ~3); cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr); + + return 0; } static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env) @@ -327,12 +388,15 @@ static void setup_frame_v1(int usig, struct target_sigaction *ka, __put_user(set->sig[i], &frame->extramask[i - 1]); } - setup_return(regs, ka, &frame->retcode, frame_addr, usig, - frame_addr + offsetof(struct sigframe_v1, retcode)); + if (setup_return(regs, ka, frame->retcode, frame_addr, usig, + frame_addr + offsetof(struct sigframe_v1, retcode))) { + goto sigsegv; + } unlock_user_struct(frame, frame_addr, 1); return; sigsegv: + unlock_user_struct(frame, frame_addr, 1); force_sigsegv(usig); } @@ -349,12 +413,15 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka, setup_sigframe_v2(&frame->uc, set, regs); - setup_return(regs, ka, &frame->retcode, frame_addr, usig, - frame_addr + offsetof(struct sigframe_v2, retcode)); + if (setup_return(regs, ka, frame->retcode, frame_addr, usig, + frame_addr + offsetof(struct sigframe_v2, retcode))) { + goto sigsegv; + } unlock_user_struct(frame, frame_addr, 1); return; sigsegv: + unlock_user_struct(frame, frame_addr, 1); force_sigsegv(usig); } @@ -404,8 +471,10 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka, __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); } - setup_return(env, ka, &frame->retcode, frame_addr, usig, - frame_addr + offsetof(struct rt_sigframe_v1, retcode)); + if (setup_return(env, ka, frame->retcode, frame_addr, usig, + frame_addr + offsetof(struct rt_sigframe_v1, retcode))) { + goto sigsegv; + } env->regs[1] = info_addr; env->regs[2] = uc_addr; @@ -413,6 +482,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka, unlock_user_struct(frame, frame_addr, 1); return; sigsegv: + unlock_user_struct(frame, frame_addr, 1); force_sigsegv(usig); } @@ -435,8 +505,10 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, setup_sigframe_v2(&frame->uc, set, env); - setup_return(env, ka, &frame->retcode, frame_addr, usig, - frame_addr + offsetof(struct rt_sigframe_v2, retcode)); + if (setup_return(env, ka, frame->retcode, frame_addr, usig, + frame_addr + offsetof(struct rt_sigframe_v2, retcode))) { + goto sigsegv; + } env->regs[1] = info_addr; env->regs[2] = uc_addr; @@ -444,6 +516,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, unlock_user_struct(frame, frame_addr, 1); return; sigsegv: + unlock_user_struct(frame, frame_addr, 1); force_sigsegv(usig); }