From patchwork Fri Oct 2 13:24:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Slaby X-Patchwork-Id: 54426 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by patches.linaro.org (Postfix) with ESMTPS id 503BC218EF for ; Fri, 2 Oct 2015 13:34:14 +0000 (UTC) Received: by wicmn1 with SMTP id mn1sf8149785wic.1 for ; Fri, 02 Oct 2015 06:34:13 -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: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=hP9PZEkpeEJgd6m5EAFNK8uv3YZTPwBAo0aHpYwac6E=; b=buuQM+Sf+K4KzMqilY7tr528vSjMgJryE1PoF++juMBdeWN/T0OhtDWUUWB4M2XQbH h28Zi1Eob7aP8meZ/sbyGJLoDLcm3DbJCYl74oxzwvWKonkHAR7Ir0KMaYY6a+YqaHLZ 1bawSFNDjOgVzSfHxX3HzxZb8t/F6p/t+l50ovCM1ktUHRZLvWLUZiYY6i9qmWpb7igq 85n0dLYJKdBZ7KuqrCn9xz/O+K//tGM8iRafk9J2tlrG2u7tBsDgQjUk2DbuITacxZm9 TPgHsJOAKBXtZgSyW+QQoOHrK4SKuJKjxW30NIBXNr2QfdXnaJX0mJgy1eButUWGkSUm JFLA== X-Gm-Message-State: ALoCoQnGmTZLEb0TtTy1JrTrbC9qw1lswXjg9ZUxrVvV7+vzvhgq9L4xKXaDjM1231MY0inS9mXD X-Received: by 10.112.55.69 with SMTP id q5mr2577336lbp.24.1443792853517; Fri, 02 Oct 2015 06:34:13 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.146.9 with SMTP id u9ls244479lfd.63.gmail; Fri, 02 Oct 2015 06:34:13 -0700 (PDT) X-Received: by 10.112.77.68 with SMTP id q4mr5697837lbw.77.1443792853374; Fri, 02 Oct 2015 06:34:13 -0700 (PDT) Received: from mail-lb0-f172.google.com (mail-lb0-f172.google.com. [209.85.217.172]) by mx.google.com with ESMTPS id p140si6270024lfe.28.2015.10.02.06.34.13 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Oct 2015 06:34:13 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.172 as permitted sender) client-ip=209.85.217.172; Received: by lbbmp1 with SMTP id mp1so26580371lbb.1 for ; Fri, 02 Oct 2015 06:34:13 -0700 (PDT) X-Received: by 10.112.135.9 with SMTP id po9mr5727658lbb.56.1443792852979; Fri, 02 Oct 2015 06:34:12 -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 w3csp1248341lbq; Fri, 2 Oct 2015 06:34:11 -0700 (PDT) X-Received: by 10.50.23.108 with SMTP id l12mr4341202igf.21.1443792850962; Fri, 02 Oct 2015 06:34:10 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o186si8649762ioe.63.2015.10.02.06.34.09; Fri, 02 Oct 2015 06:34:10 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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 S1753495AbbJBNeG (ORCPT + 30 others); Fri, 2 Oct 2015 09:34:06 -0400 Received: from mx2.suse.de ([195.135.220.15]:39566 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753090AbbJBNZq (ORCPT ); Fri, 2 Oct 2015 09:25:46 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 2341DACE5; Fri, 2 Oct 2015 13:25:44 +0000 (UTC) From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Will Deacon , Jiri Slaby Subject: [PATCH 3.12 39/84] arm64: compat: fix vfp save/restore across signal handlers in big-endian Date: Fri, 2 Oct 2015 15:24:44 +0200 Message-Id: X-Mailer: git-send-email 2.6.0 In-Reply-To: <4386f737d429451d61358f771e315ed47e2f451f.1443792303.git.jslaby@suse.cz> References: <4386f737d429451d61358f771e315ed47e2f451f.1443792303.git.jslaby@suse.cz> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linux-kernel-owner@vger.kernel.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.217.172 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 3.12-stable review patch. If anyone has any objections, please let me 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);