mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
arm64: kernel: implement fpsimd CPU PM notifier
When a CPU enters a low power state, its FP register content is lost. This patch adds a notifier to save the FP context on CPU shutdown and restore it on CPU resume. The context is saved and restored only if the suspending thread is not a kernel thread, mirroring the current context switch behaviour. Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Conflicts: arch/arm64/kernel/fpsimd.c
This commit is contained in:
committed by
Alex Shi
parent
ffc58bc556
commit
82c76f166d
@@ -17,6 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
@@ -85,6 +86,66 @@ void fpsimd_flush_thread(void)
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
|
||||
/*
|
||||
* Kernel-side NEON support functions
|
||||
*/
|
||||
void kernel_neon_begin(void)
|
||||
{
|
||||
/* Avoid using the NEON in interrupt context */
|
||||
BUG_ON(in_interrupt());
|
||||
preempt_disable();
|
||||
|
||||
if (current->mm)
|
||||
fpsimd_save_state(¤t->thread.fpsimd_state);
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_neon_begin);
|
||||
|
||||
void kernel_neon_end(void)
|
||||
{
|
||||
if (current->mm)
|
||||
fpsimd_load_state(¤t->thread.fpsimd_state);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_neon_end);
|
||||
|
||||
#endif /* CONFIG_KERNEL_MODE_NEON */
|
||||
|
||||
#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:
|
||||
if (current->mm)
|
||||
fpsimd_save_state(¤t->thread.fpsimd_state);
|
||||
break;
|
||||
case CPU_PM_EXIT:
|
||||
if (current->mm)
|
||||
fpsimd_load_state(¤t->thread.fpsimd_state);
|
||||
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,
|
||||
};
|
||||
|
||||
static void fpsimd_pm_init(void)
|
||||
{
|
||||
cpu_pm_register_notifier(&fpsimd_cpu_pm_notifier_block);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void fpsimd_pm_init(void) { }
|
||||
#endif /* CONFIG_CPU_PM */
|
||||
|
||||
/*
|
||||
* FP/SIMD support code initialisation.
|
||||
*/
|
||||
@@ -103,6 +164,8 @@ static int __init fpsimd_init(void)
|
||||
else
|
||||
elf_hwcap |= HWCAP_ASIMD;
|
||||
|
||||
fpsimd_pm_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(fpsimd_init);
|
||||
|
||||
Reference in New Issue
Block a user