From patchwork Fri Sep 25 12:00:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Slaby X-Patchwork-Id: 54157 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by patches.linaro.org (Postfix) with ESMTPS id 89AE422B1E for ; Fri, 25 Sep 2015 12:00:54 +0000 (UTC) Received: by lamf6 with SMTP id f6sf55747457lam.1 for ; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=coF3ziASRScIrfYtnq9f71P18I1js1PAGLmz2O4SN7U=; b=K0HvWhQDWdSN16bgsm6lM1TGIipMshKepMsxaCa/dcchh3H0zhe+m3pEb5NZlw7d1R gBhGwoY8aA/Lx3DOtu3gI8mU0aWdMWmqpUCAUyWT66tU3vVym/HV5KjIOpWOQxHG/vmK 08/ZKon7Lh48rnPhjW5GpaI/1EsqN9IQ5Npm8E+B6uVHQttmqURFb0ZopMuVjONSpm7v qbYLh3r2nmeBpJoL2HdBU99hqOwVclc//LltkXpp5kOEl7L0qhkuQKXx/R/0qSD23TnU y6bLbimFLYXiOh9xt4CdGbCzYa6vtryh1zeLmIstszWcnTXPQIP7FdvZNIzW4yDkdBsJ R18A== X-Gm-Message-State: ALoCoQnj/A6jChMRcbctMJVqzNFy6tbdMKwK2v63+Cmufzj/rc6ws77+ubzT+yka1tp0cuvpny8R X-Received: by 10.195.12.234 with SMTP id et10mr857808wjd.2.1443182453528; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.152.83 with SMTP id a80ls218812lfe.96.gmail; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) X-Received: by 10.112.53.231 with SMTP id e7mr1549374lbp.103.1443182453401; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) Received: from mail-la0-f43.google.com (mail-la0-f43.google.com. [209.85.215.43]) by mx.google.com with ESMTPS id wh4si1566830lbb.123.2015.09.25.05.00.53 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 25 Sep 2015 05:00:53 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.43 as permitted sender) client-ip=209.85.215.43; Received: by laclj5 with SMTP id lj5so569411lac.3 for ; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) X-Received: by 10.25.28.73 with SMTP id c70mr865182lfc.76.1443182453264; Fri, 25 Sep 2015 05:00:53 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp902844lbq; Fri, 25 Sep 2015 05:00:51 -0700 (PDT) X-Received: by 10.68.69.45 with SMTP id b13mr6746022pbu.67.1443182440218; Fri, 25 Sep 2015 05:00:40 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id wn10si5223050pab.97.2015.09.25.05.00.39; Fri, 25 Sep 2015 05:00:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755946AbbIYMAj (ORCPT + 1 other); Fri, 25 Sep 2015 08:00:39 -0400 Received: from mx2.suse.de ([195.135.220.15]:56677 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755923AbbIYMAh (ORCPT ); Fri, 25 Sep 2015 08:00:37 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3F349ACE5; Fri, 25 Sep 2015 12:00:35 +0000 (UTC) From: Jiri Slaby To: stable@vger.kernel.org Cc: Will Deacon , Jiri Slaby Subject: [patch added to the 3.12 stable tree] arm64: compat: fix vfp save/restore across signal handlers in big-endian Date: Fri, 25 Sep 2015 14:00:20 +0200 Message-Id: <1443182432-19692-6-git-send-email-jslaby@suse.cz> X-Mailer: git-send-email 2.5.3 In-Reply-To: <1443182432-19692-1-git-send-email-jslaby@suse.cz> References: <1443182432-19692-1-git-send-email-jslaby@suse.cz> Sender: stable-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: stable@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: patch@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.43 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Will Deacon This patch has been added to the 3.12 stable tree. If you have any objections, please let us know. =============== commit bdec97a855ef1e239f130f7a11584721c9a1bf04 upstream. When saving/restoring the VFP registers from a compat (AArch32) signal frame, we rely on the compat registers forming a prefix of the native register file and therefore make use of copy_{to,from}_user to transfer between the native fpsimd_state and the compat_vfp_sigframe. Unfortunately, this doesn't work so well in a big-endian environment. Our fpsimd save/restore code operates directly on 128-bit quantities (Q registers) whereas the compat_vfp_sigframe represents the registers as an array of 64-bit (D) registers. The architecture packs the compat D registers into the Q registers, with the least significant bytes holding the lower register. Consequently, we need to swap the 64-bit halves when converting between these two representations on a big-endian machine. This patch replaces the __copy_{to,from}_user invocations in our compat VFP signal handling code with explicit __put_user loops that operate on 64-bit values and swap them accordingly. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Jiri Slaby --- arch/arm64/kernel/signal32.c | 47 +++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index b9564b8d6bab..1e60acc6a4d7 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -231,14 +231,32 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) /* * VFP save/restore code. + * + * We have to be careful with endianness, since the fpsimd context-switch + * code operates on 128-bit (Q) register values whereas the compat ABI + * uses an array of 64-bit (D) registers. Consequently, we need to swap + * the two halves of each Q register when running on a big-endian CPU. */ +union __fpsimd_vreg { + __uint128_t raw; + struct { +#ifdef __AARCH64EB__ + u64 hi; + u64 lo; +#else + u64 lo; + u64 hi; +#endif + }; +}; + static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) { struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; compat_ulong_t magic = VFP_MAGIC; compat_ulong_t size = VFP_STORAGE_SIZE; compat_ulong_t fpscr, fpexc; - int err = 0; + int i, err = 0; /* * Save the hardware registers to the fpsimd_state structure. @@ -254,10 +272,15 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) /* * Now copy the FP registers. Since the registers are packed, * we can copy the prefix we want (V0-V15) as it is. - * FIXME: Won't work if big endian. */ - err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs, - sizeof(frame->ufp.fpregs)); + for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) { + union __fpsimd_vreg vreg = { + .raw = fpsimd->vregs[i >> 1], + }; + + __put_user_error(vreg.lo, &frame->ufp.fpregs[i], err); + __put_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err); + } /* Create an AArch32 fpscr from the fpsr and the fpcr. */ fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) | @@ -282,7 +305,7 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) compat_ulong_t magic = VFP_MAGIC; compat_ulong_t size = VFP_STORAGE_SIZE; compat_ulong_t fpscr; - int err = 0; + int i, err = 0; __get_user_error(magic, &frame->magic, err); __get_user_error(size, &frame->size, err); @@ -292,12 +315,14 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) return -EINVAL; - /* - * Copy the FP registers into the start of the fpsimd_state. - * FIXME: Won't work if big endian. - */ - err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs, - sizeof(frame->ufp.fpregs)); + /* Copy the FP registers into the start of the fpsimd_state. */ + for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) { + union __fpsimd_vreg vreg; + + __get_user_error(vreg.lo, &frame->ufp.fpregs[i], err); + __get_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err); + fpsimd.vregs[i >> 1] = vreg.raw; + } /* Extract the fpsr and the fpcr from the fpscr */ __get_user_error(fpscr, &frame->ufp.fpscr, err);