From patchwork Thu Jun 6 15:03:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 17649 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vb0-f69.google.com (mail-vb0-f69.google.com [209.85.212.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3454920F47 for ; Thu, 6 Jun 2013 15:03:33 +0000 (UTC) Received: by mail-vb0-f69.google.com with SMTP id e15sf3067320vbg.0 for ; Thu, 06 Jun 2013 08:03:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=ylUa1tU+vCnWc5MHftBfwFc0qht1XebN1+Op7iJTnXc=; b=pb+8XpOdr48TifRE0xQGwBsWRrVrXv+m9a5qtU4NUtsNeZuvseGDcIdBr9HDYeJScW hAqdThuZp4RSwOIR8ubLHFw4mv/m6CjQhunl3EpK29m20mVJs5wbxhC0eRSdyOgV6xJI JxRbXsWsnNyZrz3KsqZN9p72mxPdE0qRVDMq7mnfyiNe1Cbwyf+65TSvwEnrtCGe0p/I C9dNLm0F9vpV3W4gOaIDL2j6yxHzoyZUmkfj1wrpOoTQT8GexWntWqvGrPWeQxJS/mkT apwcQvwLzsx96ViB7g+U22tqua4l6/rP+gr9kN4zTRwmPmC9+L8OfiLo/oKnbZZi9lKs QA4w== X-Received: by 10.224.200.202 with SMTP id ex10mr21464219qab.8.1370531012730; Thu, 06 Jun 2013 08:03:32 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.13.106 with SMTP id g10ls1257858qec.39.gmail; Thu, 06 Jun 2013 08:03:32 -0700 (PDT) X-Received: by 10.52.109.10 with SMTP id ho10mr855716vdb.16.1370531012395; Thu, 06 Jun 2013 08:03:32 -0700 (PDT) Received: from mail-vc0-f171.google.com (mail-vc0-f171.google.com [209.85.220.171]) by mx.google.com with ESMTPS id bj6si37505206vcb.53.2013.06.06.08.03.32 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 06 Jun 2013 08:03:32 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.171; Received: by mail-vc0-f171.google.com with SMTP id m16so2096697vca.30 for ; Thu, 06 Jun 2013 08:03:32 -0700 (PDT) X-Received: by 10.52.157.138 with SMTP id wm10mr18929339vdb.57.1370531012296; Thu, 06 Jun 2013 08:03:32 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.221.10.206 with SMTP id pb14csp70241vcb; Thu, 6 Jun 2013 08:03:31 -0700 (PDT) X-Received: by 10.180.187.234 with SMTP id fv10mr10012366wic.29.1370531011107; Thu, 06 Jun 2013 08:03:31 -0700 (PDT) Received: from mail-we0-x231.google.com (mail-we0-x231.google.com [2a00:1450:400c:c03::231]) by mx.google.com with ESMTPS id c1si21063815wje.113.2013.06.06.08.03.30 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 06 Jun 2013 08:03:31 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:400c:c03::231 is neither permitted nor denied by best guess record for domain of ard.biesheuvel@linaro.org) client-ip=2a00:1450:400c:c03::231; Received: by mail-we0-f177.google.com with SMTP id m19so2116002wev.22 for ; Thu, 06 Jun 2013 08:03:30 -0700 (PDT) X-Received: by 10.181.13.13 with SMTP id eu13mr10123125wid.26.1370531010517; Thu, 06 Jun 2013 08:03:30 -0700 (PDT) Received: from ards-mac-mini.local (cag06-7-83-153-85-71.fbx.proxad.net. [83.153.85.71]) by mx.google.com with ESMTPSA id cw8sm16357697wib.7.2013.06.06.08.03.28 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 06 Jun 2013 08:03:29 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: nico@linaro.org, rob.herring@calxeda.com, linux@arm.linux.org.uk, patches@linaro.org, Ard Biesheuvel Subject: [PATCH 1/5] ARM: add support for kernel mode NEON Date: Thu, 6 Jun 2013 17:03:01 +0200 Message-Id: <1370530985-20619-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1370530985-20619-1-git-send-email-ard.biesheuvel@linaro.org> References: <1370530985-20619-1-git-send-email-ard.biesheuvel@linaro.org> X-Gm-Message-State: ALoCoQmm9phH8BHI0f4Qsd9C4+SyutL3kRmWhRojCbX4IcTWi+QfqZDup+ohPbBLvduFYXUlHLVA X-Original-Sender: ard.biesheuvel@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , In order to safely support the use of NEON instructions in kernel mode, some precautions need to be taken: - the userland context that may be present in the registers (even if the NEON/VFP is currently disabled) must be stored under the correct task (which may not be 'current' in the UP case), - to avoid having to keep track of additional vfpstates for the kernel side, disallow the use of NEON in interrupt context and run with preemption disabled, - after use, re-enable preemption and re-enable the lazy restore machinery by disabling the NEON/VFP unit. This patch adds the functions kernel_neon_begin() and kernel_neon_end() which take care of the above. It also adds the Kconfig symbol KERNEL_MODE_NEON to enable it. Signed-off-by: Ard Biesheuvel Acked-by: Nicolas Pitre --- arch/arm/Kconfig | 7 +++++++ arch/arm/include/asm/neon.h | 36 ++++++++++++++++++++++++++++++++++++ arch/arm/vfp/vfpmodule.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 arch/arm/include/asm/neon.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ef30276..9e61402 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2355,6 +2355,13 @@ config NEON Say Y to include support code for NEON, the ARMv7 Advanced SIMD Extension. +config KERNEL_MODE_NEON + bool "Support for NEON in kernel mode" + default n + depends on NEON + help + Say Y to include support for NEON in kernel mode. + endmenu menu "Userspace binary formats" diff --git a/arch/arm/include/asm/neon.h b/arch/arm/include/asm/neon.h new file mode 100644 index 0000000..8f730fe --- /dev/null +++ b/arch/arm/include/asm/neon.h @@ -0,0 +1,36 @@ +/* + * linux/arch/arm/include/asm/neon.h + * + * Copyright (C) 2013 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#define cpu_has_neon() (!!(elf_hwcap & HWCAP_NEON)) + +#ifdef __ARM_NEON__ + +/* + * If you are affected by the BUILD_BUG below, it probably means that you are + * using NEON code /and/ calling the kernel_neon_begin() function from the same + * compilation unit. To prevent issues that may arise from GCC reordering or + * generating(1) NEON instructions outside of these begin/end functions, the + * only supported way of using NEON code in the kernel is by isolating it in a + * separate compilation unit, and calling it from another unit from inside a + * kernel_neon_begin/kernel_neon_end pair. + * + * (1) Current GCC (4.7) might generate NEON instructions at O3 level if + * -mpfu=neon is set. + */ + +#define kernel_neon_begin() \ + BUILD_BUG_ON_MSG(1, "kernel_neon_begin() called from NEON code") + +#else +void kernel_neon_begin(void); +#endif +void kernel_neon_end(void); diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 5dfbb0b..1cdc13b 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -648,6 +649,48 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action, return NOTIFY_OK; } +#ifdef CONFIG_KERNEL_MODE_NEON + +/* + * Kernel-side NEON support functions + */ +void kernel_neon_begin(void) +{ + struct thread_info *thread = current_thread_info(); + unsigned int cpu; + u32 fpexc; + + /* Avoid using the NEON in interrupt context */ + might_sleep(); + cpu = get_cpu(); + + fpexc = fmrx(FPEXC) | FPEXC_EN; + fmxr(FPEXC, fpexc); + + /* + * Save the userland NEON/VFP state. Under UP, + * the owner could be a task other than 'current' + */ + if (vfp_state_in_hw(cpu, thread)) + vfp_save_state(&thread->vfpstate, fpexc); +#ifndef CONFIG_SMP + else if (vfp_current_hw_state[cpu] != NULL) + vfp_save_state(vfp_current_hw_state[cpu], fpexc); +#endif + vfp_current_hw_state[cpu] = NULL; +} +EXPORT_SYMBOL(kernel_neon_begin); + +void kernel_neon_end(void) +{ + /* Disable the NEON/VFP unit. */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + put_cpu(); +} +EXPORT_SYMBOL(kernel_neon_end); + +#endif /* CONFIG_KERNEL_MODE_NEON */ + /* * VFP support code initialisation. */