2012-03-05 11:49:32 +00:00
/*
* FP / SIMD context switching and fault handling
*
* Copyright ( C ) 2012 ARM Ltd .
* Author : Catalin Marinas < catalin . marinas @ arm . com >
*
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
# include <linux/bottom_half.h>
2015-06-11 12:02:45 +08:00
# include <linux/cpu.h>
2013-07-19 17:48:08 +01:00
# include <linux/cpu_pm.h>
2012-03-05 11:49:32 +00:00
# include <linux/kernel.h>
# include <linux/init.h>
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
# include <linux/percpu.h>
2017-08-03 17:23:22 +01:00
# include <linux/preempt.h>
2017-02-08 18:51:30 +01:00
# include <linux/sched/signal.h>
2012-03-05 11:49:32 +00:00
# include <linux/signal.h>
# include <asm/fpsimd.h>
# include <asm/cputype.h>
2017-08-03 17:23:22 +01:00
# include <asm/simd.h>
2012-03-05 11:49:32 +00:00
# define FPEXC_IOF (1 << 0)
# define FPEXC_DZF (1 << 1)
# define FPEXC_OFF (1 << 2)
# define FPEXC_UFF (1 << 3)
# define FPEXC_IXF (1 << 4)
# define FPEXC_IDF (1 << 7)
2014-05-08 11:20:23 +02:00
/*
* In order to reduce the number of times the FPSIMD state is needlessly saved
* and restored , we need to keep track of two things :
* ( a ) for each task , we need to remember which CPU was the last one to have
* the task ' s FPSIMD state loaded into its FPSIMD registers ;
* ( b ) for each CPU , we need to remember which task ' s userland FPSIMD state has
* been loaded into its FPSIMD registers most recently , or whether it has
* been used to perform kernel mode NEON in the meantime .
*
* For ( a ) , we add a ' cpu ' field to struct fpsimd_state , which gets updated to
2016-02-24 09:52:41 -08:00
* the id of the current CPU every time the state is loaded onto a CPU . For ( b ) ,
2014-05-08 11:20:23 +02:00
* we add the per - cpu variable ' fpsimd_last_state ' ( below ) , which contains the
* address of the userland FPSIMD state of the task that was loaded onto the CPU
* the most recently , or NULL if kernel mode NEON has been performed after that .
*
* With this in place , we no longer have to restore the next FPSIMD state right
* when switching between tasks . Instead , we can defer this check to userland
* resume , at which time we verify whether the CPU ' s fpsimd_last_state and the
* task ' s fpsimd_state . cpu are still mutually in sync . If this is the case , we
* can omit the FPSIMD restore .
*
* As an optimization , we use the thread_info flag TIF_FOREIGN_FPSTATE to
* indicate whether or not the userland FPSIMD state of the current task is
* present in the registers . The flag is set unless the FPSIMD registers of this
* CPU currently contain the most recent userland FPSIMD state of the current
* task .
*
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
* In order to allow softirq handlers to use FPSIMD , kernel_neon_begin ( ) may
* save the task ' s FPSIMD context back to task_struct from softirq context .
* To prevent this from racing with the manipulation of the task ' s FPSIMD state
* from task context and thereby corrupting the state , it is necessary to
* protect any manipulation of a task ' s fpsimd_state or TIF_FOREIGN_FPSTATE
* flag with local_bh_disable ( ) unless softirqs are already masked .
*
2014-05-08 11:20:23 +02:00
* For a certain task , the sequence may look something like this :
* - the task gets scheduled in ; if both the task ' s fpsimd_state . cpu field
* contains the id of the current CPU , and the CPU ' s fpsimd_last_state per - cpu
* variable points to the task ' s fpsimd_state , the TIF_FOREIGN_FPSTATE flag is
* cleared , otherwise it is set ;
*
* - the task returns to userland ; if TIF_FOREIGN_FPSTATE is set , the task ' s
* userland FPSIMD state is copied from memory to the registers , the task ' s
* fpsimd_state . cpu field is set to the id of the current CPU , the current
* CPU ' s fpsimd_last_state pointer is set to this task ' s fpsimd_state and the
* TIF_FOREIGN_FPSTATE flag is cleared ;
*
* - the task executes an ordinary syscall ; upon return to userland , the
* TIF_FOREIGN_FPSTATE flag will still be cleared , so no FPSIMD state is
* restored ;
*
* - the task executes a syscall which executes some NEON instructions ; this is
* preceded by a call to kernel_neon_begin ( ) , which copies the task ' s FPSIMD
* register contents to memory , clears the fpsimd_last_state per - cpu variable
* and sets the TIF_FOREIGN_FPSTATE flag ;
*
* - the task gets preempted after kernel_neon_end ( ) is called ; as we have not
* returned from the 2 nd syscall yet , TIF_FOREIGN_FPSTATE is still set so
* whatever is in the FPSIMD registers is not saved to memory , but discarded .
*/
static DEFINE_PER_CPU ( struct fpsimd_state * , fpsimd_last_state ) ;
2012-03-05 11:49:32 +00:00
/*
* Trapped FP / ASIMD access .
*/
void do_fpsimd_acc ( unsigned int esr , struct pt_regs * regs )
{
/* TODO: implement lazy context saving/restoring */
WARN_ON ( 1 ) ;
}
/*
* Raise a SIGFPE for the current process .
*/
void do_fpsimd_exc ( unsigned int esr , struct pt_regs * regs )
{
siginfo_t info ;
unsigned int si_code = 0 ;
if ( esr & FPEXC_IOF )
si_code = FPE_FLTINV ;
else if ( esr & FPEXC_DZF )
si_code = FPE_FLTDIV ;
else if ( esr & FPEXC_OFF )
si_code = FPE_FLTOVF ;
else if ( esr & FPEXC_UFF )
si_code = FPE_FLTUND ;
else if ( esr & FPEXC_IXF )
si_code = FPE_FLTRES ;
memset ( & info , 0 , sizeof ( info ) ) ;
info . si_signo = SIGFPE ;
info . si_code = si_code ;
info . si_addr = ( void __user * ) instruction_pointer ( regs ) ;
send_sig_info ( SIGFPE , & info , current ) ;
}
void fpsimd_thread_switch ( struct task_struct * next )
{
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
2014-05-08 11:20:23 +02:00
/*
* Save the current FPSIMD state to memory , but only if whatever is in
* the registers is in fact the most recent userland FPSIMD state of
* ' current ' .
*/
if ( current - > mm & & ! test_thread_flag ( TIF_FOREIGN_FPSTATE ) )
2012-03-05 11:49:32 +00:00
fpsimd_save_state ( & current - > thread . fpsimd_state ) ;
2014-05-08 11:20:23 +02:00
if ( next - > mm ) {
/*
* If we are switching to a task whose most recent userland
* FPSIMD state is already in the registers of * this * cpu ,
* we can skip loading the state from memory . Otherwise , set
* the TIF_FOREIGN_FPSTATE flag so the state will be loaded
* upon the next return to userland .
*/
struct fpsimd_state * st = & next - > thread . fpsimd_state ;
if ( __this_cpu_read ( fpsimd_last_state ) = = st
& & st - > cpu = = smp_processor_id ( ) )
clear_ti_thread_flag ( task_thread_info ( next ) ,
TIF_FOREIGN_FPSTATE ) ;
else
set_ti_thread_flag ( task_thread_info ( next ) ,
TIF_FOREIGN_FPSTATE ) ;
}
2012-03-05 11:49:32 +00:00
}
void fpsimd_flush_thread ( void )
{
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_disable ( ) ;
2012-03-05 11:49:32 +00:00
memset ( & current - > thread . fpsimd_state , 0 , sizeof ( struct fpsimd_state ) ) ;
2015-08-27 07:12:33 +01:00
fpsimd_flush_task_state ( current ) ;
2014-05-08 11:20:23 +02:00
set_thread_flag ( TIF_FOREIGN_FPSTATE ) ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_enable ( ) ;
2012-03-05 11:49:32 +00:00
}
2014-02-24 15:26:27 +01:00
/*
2014-05-08 11:20:23 +02:00
* Save the userland FPSIMD state of ' current ' to memory , but only if the state
* currently held in the registers does in fact belong to ' current '
2014-02-24 15:26:27 +01:00
*/
void fpsimd_preserve_current_state ( void )
{
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_disable ( ) ;
2014-05-08 11:20:23 +02:00
if ( ! test_thread_flag ( TIF_FOREIGN_FPSTATE ) )
fpsimd_save_state ( & current - > thread . fpsimd_state ) ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_enable ( ) ;
2014-02-24 15:26:27 +01:00
}
/*
2014-05-08 11:20:23 +02:00
* Load the userland FPSIMD state of ' current ' from memory , but only if the
* FPSIMD state already held in the registers is / not / the most recent FPSIMD
* state of ' current '
*/
void fpsimd_restore_current_state ( void )
{
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_disable ( ) ;
2014-05-08 11:20:23 +02:00
if ( test_and_clear_thread_flag ( TIF_FOREIGN_FPSTATE ) ) {
struct fpsimd_state * st = & current - > thread . fpsimd_state ;
fpsimd_load_state ( st ) ;
2017-08-03 17:23:21 +01:00
__this_cpu_write ( fpsimd_last_state , st ) ;
2014-05-08 11:20:23 +02:00
st - > cpu = smp_processor_id ( ) ;
}
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_enable ( ) ;
2014-05-08 11:20:23 +02:00
}
/*
* Load an updated userland FPSIMD state for ' current ' from memory and set the
* flag that indicates that the FPSIMD register contents are the most recent
* FPSIMD state of ' current '
2014-02-24 15:26:27 +01:00
*/
void fpsimd_update_current_state ( struct fpsimd_state * state )
{
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_disable ( ) ;
2014-02-24 15:26:27 +01:00
fpsimd_load_state ( state ) ;
2014-05-08 11:20:23 +02:00
if ( test_and_clear_thread_flag ( TIF_FOREIGN_FPSTATE ) ) {
struct fpsimd_state * st = & current - > thread . fpsimd_state ;
2017-08-03 17:23:21 +01:00
__this_cpu_write ( fpsimd_last_state , st ) ;
2014-05-08 11:20:23 +02:00
st - > cpu = smp_processor_id ( ) ;
}
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
local_bh_enable ( ) ;
2014-02-24 15:26:27 +01:00
}
2014-05-08 11:20:23 +02:00
/*
* Invalidate live CPU copies of task t ' s FPSIMD state
*/
void fpsimd_flush_task_state ( struct task_struct * t )
{
t - > thread . fpsimd_state . cpu = NR_CPUS ;
}
2013-07-09 14:18:12 +01:00
# ifdef CONFIG_KERNEL_MODE_NEON
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
DEFINE_PER_CPU ( bool , kernel_neon_busy ) ;
2017-08-07 12:36:35 +01:00
EXPORT_PER_CPU_SYMBOL ( kernel_neon_busy ) ;
2014-02-24 15:26:29 +01:00
2013-07-09 14:18:12 +01:00
/*
* Kernel - side NEON support functions
*/
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
/*
* kernel_neon_begin ( ) : obtain the CPU FPSIMD registers for use by the calling
* context
*
* Must not be called unless may_use_simd ( ) returns true .
* Task context in the FPSIMD registers is saved back to memory as necessary .
*
* A matching call to kernel_neon_end ( ) must be made before returning from the
* calling context .
*
* The caller may freely use the FPSIMD registers until kernel_neon_end ( ) is
* called .
*/
void kernel_neon_begin ( void )
2013-07-09 14:18:12 +01:00
{
2016-11-08 13:56:21 +00:00
if ( WARN_ON ( ! system_supports_fpsimd ( ) ) )
return ;
2013-07-09 14:18:12 +01:00
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
BUG_ON ( ! may_use_simd ( ) ) ;
local_bh_disable ( ) ;
__this_cpu_write ( kernel_neon_busy , true ) ;
/* Save unsaved task fpsimd state, if any: */
if ( current - > mm & & ! test_and_set_thread_flag ( TIF_FOREIGN_FPSTATE ) )
fpsimd_save_state ( & current - > thread . fpsimd_state ) ;
/* Invalidate any task state remaining in the fpsimd regs: */
__this_cpu_write ( fpsimd_last_state , NULL ) ;
preempt_disable ( ) ;
local_bh_enable ( ) ;
2013-07-09 14:18:12 +01:00
}
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
EXPORT_SYMBOL ( kernel_neon_begin ) ;
2013-07-09 14:18:12 +01:00
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
/*
* kernel_neon_end ( ) : give the CPU FPSIMD registers back to the current task
*
* Must be called from a context in which kernel_neon_begin ( ) was previously
* called , with no call to kernel_neon_end ( ) in the meantime .
*
* The caller must not use the FPSIMD registers after this function is called ,
* unless kernel_neon_begin ( ) is called again in the meantime .
*/
2013-07-09 14:18:12 +01:00
void kernel_neon_end ( void )
{
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
bool busy ;
2016-11-08 13:56:21 +00:00
if ( ! system_supports_fpsimd ( ) )
return ;
arm64: neon: Remove support for nested or hardirq kernel-mode NEON
Support for kernel-mode NEON to be nested and/or used in hardirq
context adds significant complexity, and the benefits may be
marginal. In practice, kernel-mode NEON is not used in hardirq
context, and is rarely used in softirq context (by certain mac80211
drivers).
This patch implements an arm64 may_use_simd() function to allow
clients to check whether kernel-mode NEON is usable in the current
context, and simplifies kernel_neon_{begin,end}() to handle only
saving of the task FPSIMD state (if any). Without nesting, there
is no other state to save.
The partial fpsimd save/restore functions become redundant as a
result of these changes, so they are removed too.
The save/restore model is changed to operate directly on
task_struct without additional percpu storage. This simplifies the
code and saves a bit of memory, but means that softirqs must now be
disabled when manipulating the task fpsimd state from task context:
correspondingly, preempt_{en,dis}sable() calls are upgraded to
local_bh_{en,dis}able() as appropriate. fpsimd_thread_switch()
already runs with hardirqs disabled and so is already protected
from softirqs.
These changes should make it easier to support kernel-mode NEON in
the presence of the Scalable Vector extension in the future.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-08-03 17:23:23 +01:00
busy = __this_cpu_xchg ( kernel_neon_busy , false ) ;
WARN_ON ( ! busy ) ; /* No matching kernel_neon_begin()? */
preempt_enable ( ) ;
2013-07-09 14:18:12 +01:00
}
EXPORT_SYMBOL ( kernel_neon_end ) ;
2017-09-18 09:40:12 +01:00
# ifdef CONFIG_EFI
2017-08-18 14:53:47 +01:00
static DEFINE_PER_CPU ( struct fpsimd_state , efi_fpsimd_state ) ;
static DEFINE_PER_CPU ( bool , efi_fpsimd_state_used ) ;
2017-08-03 17:23:22 +01:00
/*
* EFI runtime services support functions
*
* The ABI for EFI runtime services allows EFI to use FPSIMD during the call .
* This means that for EFI ( and only for EFI ) , we have to assume that FPSIMD
* is always used rather than being an optional accelerator .
*
* These functions provide the necessary support for ensuring FPSIMD
* save / restore in the contexts from which EFI is used .
*
* Do not use them for any other purpose - - if tempted to do so , you are
* either doing something wrong or you need to propose some refactoring .
*/
/*
* __efi_fpsimd_begin ( ) : prepare FPSIMD for making an EFI runtime services call
*/
void __efi_fpsimd_begin ( void )
{
if ( ! system_supports_fpsimd ( ) )
return ;
WARN_ON ( preemptible ( ) ) ;
if ( may_use_simd ( ) )
kernel_neon_begin ( ) ;
else {
fpsimd_save_state ( this_cpu_ptr ( & efi_fpsimd_state ) ) ;
__this_cpu_write ( efi_fpsimd_state_used , true ) ;
}
}
/*
* __efi_fpsimd_end ( ) : clean up FPSIMD after an EFI runtime services call
*/
void __efi_fpsimd_end ( void )
{
if ( ! system_supports_fpsimd ( ) )
return ;
if ( __this_cpu_xchg ( efi_fpsimd_state_used , false ) )
fpsimd_load_state ( this_cpu_ptr ( & efi_fpsimd_state ) ) ;
else
kernel_neon_end ( ) ;
}
2017-09-18 09:40:12 +01:00
# endif /* CONFIG_EFI */
2013-07-09 14:18:12 +01:00
# endif /* CONFIG_KERNEL_MODE_NEON */
2013-07-19 17:48:08 +01:00
# ifdef CONFIG_CPU_PM
static int fpsimd_cpu_pm_notifier ( struct notifier_block * self ,
unsigned long cmd , void * v )
{
switch ( cmd ) {
case CPU_PM_ENTER :
2014-05-08 11:20:23 +02:00
if ( current - > mm & & ! test_thread_flag ( TIF_FOREIGN_FPSTATE ) )
2013-07-19 17:48:08 +01:00
fpsimd_save_state ( & current - > thread . fpsimd_state ) ;
2014-09-01 11:09:51 +08:00
this_cpu_write ( fpsimd_last_state , NULL ) ;
2013-07-19 17:48:08 +01:00
break ;
case CPU_PM_EXIT :
if ( current - > mm )
2014-05-08 11:20:23 +02:00
set_thread_flag ( TIF_FOREIGN_FPSTATE ) ;
2013-07-19 17:48:08 +01:00
break ;
case CPU_PM_ENTER_FAILED :
default :
return NOTIFY_DONE ;
}
return NOTIFY_OK ;
}
static struct notifier_block fpsimd_cpu_pm_notifier_block = {
. notifier_call = fpsimd_cpu_pm_notifier ,
} ;
2015-11-20 17:59:10 +08:00
static void __init fpsimd_pm_init ( void )
2013-07-19 17:48:08 +01:00
{
cpu_pm_register_notifier ( & fpsimd_cpu_pm_notifier_block ) ;
}
# else
static inline void fpsimd_pm_init ( void ) { }
# endif /* CONFIG_CPU_PM */
2015-06-11 12:02:45 +08:00
# ifdef CONFIG_HOTPLUG_CPU
2016-09-06 19:04:37 +02:00
static int fpsimd_cpu_dead ( unsigned int cpu )
2015-06-11 12:02:45 +08:00
{
2016-09-06 19:04:37 +02:00
per_cpu ( fpsimd_last_state , cpu ) = NULL ;
return 0 ;
2015-06-11 12:02:45 +08:00
}
static inline void fpsimd_hotplug_init ( void )
{
2016-09-06 19:04:37 +02:00
cpuhp_setup_state_nocalls ( CPUHP_ARM64_FPSIMD_DEAD , " arm64/fpsimd:dead " ,
NULL , fpsimd_cpu_dead ) ;
2015-06-11 12:02:45 +08:00
}
# else
static inline void fpsimd_hotplug_init ( void ) { }
# endif
2012-03-05 11:49:32 +00:00
/*
* FP / SIMD support code initialisation .
*/
static int __init fpsimd_init ( void )
{
2015-10-19 14:24:53 +01:00
if ( elf_hwcap & HWCAP_FP ) {
fpsimd_pm_init ( ) ;
fpsimd_hotplug_init ( ) ;
} else {
2012-03-05 11:49:32 +00:00
pr_notice ( " Floating-point is not implemented \n " ) ;
}
2015-10-19 14:24:53 +01:00
if ( ! ( elf_hwcap & HWCAP_ASIMD ) )
2012-03-05 11:49:32 +00:00
pr_notice ( " Advanced SIMD is not implemented \n " ) ;
2013-07-19 17:48:08 +01:00
2012-03-05 11:49:32 +00:00
return 0 ;
}
late_initcall ( fpsimd_init ) ;