From patchwork Wed Feb 5 17:13:35 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 3587741 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B4A5A9F2E9 for ; Wed, 5 Feb 2014 17:14:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A4ACB20125 for ; Wed, 5 Feb 2014 17:14:57 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 76C6220123 for ; Wed, 5 Feb 2014 17:14:56 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WB63N-0000Ys-3Z; Wed, 05 Feb 2014 17:14:25 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WB63H-0002Px-8B; Wed, 05 Feb 2014 17:14:19 +0000 Received: from mail-we0-f169.google.com ([74.125.82.169]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WB630-0002MV-Ig for linux-arm-kernel@lists.infradead.org; Wed, 05 Feb 2014 17:14:07 +0000 Received: by mail-we0-f169.google.com with SMTP id t61so522547wes.14 for ; Wed, 05 Feb 2014 09:13:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+lIghrY/l/xemvEQmYBNb2rc4fddhTIecD5ROkXMw7c=; b=eJf2uQ/QKRTTdX7m/nSe2HX3wnAseFa34gXkB/Ny29VLZV+WGiL2WeYqfQvjAJK/Um na9wRYhEWW0g+voLVX6AYriiZcqQl6XIP4WclnCnKXA9h3cHju5hHtTOFmn4s39qK/ja txOQ2fNmI698La84QzAOVJCqEmY79T7Hr+Q8iYfuwCdck7s6cUbUc9k9WAtHJsoWDu12 X0BU4AArNF9KCseiKq7ntp2Lr7JSxcMS+CNHSxNQPK8ZEfE0ytGjuZmNulnqZ0TG1SFh 2D4tjKgOtnhmpC3NJJRVXWOqDmThqysnj+dHKrte0b2ZQ5oR6+9sc5EkTQkmJzEKS8tF mEyw== X-Gm-Message-State: ALoCoQkUQgUV+lspYI3f8s9dhZKiJQB3SubXRZpoBC+N7UgCog5su8XB14ydsny1N0RI/p/xkcDo X-Received: by 10.180.37.162 with SMTP id z2mr3339607wij.51.1391620421223; Wed, 05 Feb 2014 09:13:41 -0800 (PST) Received: from ards-macbook-pro.local (cag06-7-83-153-85-71.fbx.proxad.net. [83.153.85.71]) by mx.google.com with ESMTPSA id y13sm62961628wjr.8.2014.02.05.09.13.39 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 05 Feb 2014 09:13:40 -0800 (PST) From: Ard Biesheuvel To: will.deacon@arm.com, catalin.marinas@arm.com, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 1/4] arm64: add abstractions for FPSIMD state manipulation Date: Wed, 5 Feb 2014 18:13:35 +0100 Message-Id: <1391620418-3999-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1391620418-3999-1-git-send-email-ard.biesheuvel@linaro.org> References: <1391620418-3999-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140205_121402_859272_F12F09A9 X-CRM114-Status: GOOD ( 18.10 ) X-Spam-Score: -2.6 (--) Cc: Ard Biesheuvel , patches@linaro.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is a preparatory patch that replaces code that saves or restores the on-CPU or preserved FPSIMD state directly with wrapper functions, resulting in all direct manipulation of the FPSIMD state to be concentrated in fpsimd.c Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/fpsimd.h | 9 ++++++--- arch/arm64/kernel/fpsimd.c | 31 +++++++++++++++++++++++++++++++ arch/arm64/kernel/process.c | 2 +- arch/arm64/kernel/ptrace.c | 22 +++++++++++++--------- arch/arm64/kernel/signal.c | 6 +++--- arch/arm64/kernel/signal32.c | 6 +++--- 6 files changed, 57 insertions(+), 19 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index c43b4ac13008..7807974b49ee 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -52,12 +52,15 @@ struct fpsimd_state { struct task_struct; -extern void fpsimd_save_state(struct fpsimd_state *state); -extern void fpsimd_load_state(struct fpsimd_state *state); - extern void fpsimd_thread_switch(struct task_struct *next); extern void fpsimd_flush_thread(void); +struct fpsimd_state *fpsimd_get_task_state(void); +void fpsimd_set_task_state(struct fpsimd_state *state); + +struct user_fpsimd_state *fpsimd_get_user_state(struct task_struct *t); +void fpsimd_set_user_state(struct task_struct *t, struct user_fpsimd_state *st); + #endif #endif diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 4aef42a04bdc..eeb003f54ad0 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -34,6 +34,10 @@ #define FPEXC_IXF (1 << 4) #define FPEXC_IDF (1 << 7) +/* defined in entry-fpsimd.S but only used in this unit */ +void fpsimd_save_state(struct fpsimd_state *state); +void fpsimd_load_state(struct fpsimd_state *state); + /* * Trapped FP/ASIMD access. */ @@ -87,6 +91,33 @@ void fpsimd_flush_thread(void) preempt_enable(); } +/* + * Sync the saved FPSIMD context with the FPSIMD register file + */ +struct fpsimd_state *fpsimd_get_task_state(void) +{ + fpsimd_save_state(¤t->thread.fpsimd_state); + return ¤t->thread.fpsimd_state; +} + +/* + * Load a new FPSIMD state into the FPSIMD register file. + */ +void fpsimd_set_task_state(struct fpsimd_state *state) +{ + fpsimd_load_state(state); +} + +struct user_fpsimd_state *fpsimd_get_user_state(struct task_struct *t) +{ + return &t->thread.fpsimd_state.user_fpsimd; +} + +void fpsimd_set_user_state(struct task_struct *t, struct user_fpsimd_state *st) +{ + t->thread.fpsimd_state.user_fpsimd = *st; +} + #ifdef CONFIG_KERNEL_MODE_NEON /* diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 1c0a9be2ffa8..bfa8214f92d1 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -199,7 +199,7 @@ void release_thread(struct task_struct *dead_task) int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { - fpsimd_save_state(¤t->thread.fpsimd_state); + fpsimd_get_task_state(); *dst = *src; return 0; } diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 6a8928bba03c..d0b35af14539 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -500,8 +500,7 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { - struct user_fpsimd_state *uregs; - uregs = &target->thread.fpsimd_state.user_fpsimd; + struct user_fpsimd_state *uregs = fpsimd_get_user_state(target); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); } @@ -516,7 +515,7 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset, if (ret) return ret; - target->thread.fpsimd_state.user_fpsimd = newstate; + fpsimd_set_user_state(target, &newstate); return ret; } @@ -723,7 +722,7 @@ static int compat_vfp_get(struct task_struct *target, compat_ulong_t fpscr; int ret; - uregs = &target->thread.fpsimd_state.user_fpsimd; + uregs = fpsimd_get_user_state(target); /* * The VFP registers are packed into the fpsimd_state, so they all sit @@ -746,24 +745,29 @@ static int compat_vfp_set(struct task_struct *target, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { - struct user_fpsimd_state *uregs; + struct user_fpsimd_state newstate; compat_ulong_t fpscr; int ret; if (pos + count > VFP_STATE_SIZE) return -EIO; - uregs = &target->thread.fpsimd_state.user_fpsimd; + /* + * We will not overwrite the entire FPSIMD state, so we need to + * initialize 'newstate' with sane values. + */ + newstate = *fpsimd_get_user_state(target); - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, VFP_STATE_SIZE - sizeof(compat_ulong_t)); if (count && !ret) { ret = get_user(fpscr, (compat_ulong_t *)ubuf); - uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; - uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; + newstate.fpsr = fpscr & VFP_FPSCR_STAT_MASK; + newstate.fpcr = fpscr & VFP_FPSCR_CTRL_MASK; } + fpsimd_set_user_state(target, &newstate); return ret; } diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 890a591f75dd..54e1092c5b4c 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -47,11 +47,11 @@ struct rt_sigframe { static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) { - struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; + struct fpsimd_state *fpsimd; int err; /* dump the hardware registers to the fpsimd_state structure */ - fpsimd_save_state(fpsimd); + fpsimd = fpsimd_get_task_state(); /* copy the FP and status/control registers */ err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); @@ -88,7 +88,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx) /* load the hardware registers from the fpsimd_state structure */ if (!err) { preempt_disable(); - fpsimd_load_state(&fpsimd); + fpsimd_set_task_state(&fpsimd); preempt_enable(); } diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index b3fc9f5ec6d3..88e4535c3a45 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -208,7 +208,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) */ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) { - struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; + struct fpsimd_state *fpsimd; compat_ulong_t magic = VFP_MAGIC; compat_ulong_t size = VFP_STORAGE_SIZE; compat_ulong_t fpscr, fpexc; @@ -219,7 +219,7 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) * Note that this also saves V16-31, which aren't visible * in AArch32. */ - fpsimd_save_state(fpsimd); + fpsimd = fpsimd_get_task_state(); /* Place structure header on the stack */ __put_user_error(magic, &frame->magic, err); @@ -284,7 +284,7 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) */ if (!err) { preempt_disable(); - fpsimd_load_state(&fpsimd); + fpsimd_set_task_state(&fpsimd); preempt_enable(); }