mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-23 16:39:53 +07:00
1db1af84d6
This patch adds support for context switching the MSA vector registers. These 128 bit vector registers are aliased with the FP registers - an FP register accesses the least significant bits of the vector register with which it is aliased (ie. the register with the same index). Due to both this & the requirement that the scalar FPU must be 64-bit (FR=1) if enabled at the same time as MSA the kernel will enable MSA & scalar FP at the same time for tasks which use MSA. If we restore the MSA vector context then we might as well enable the scalar FPU since the reason it was left disabled was to allow for lazy FP context restoring - but we just restored the FP context as it's a subset of the vector context. If we restore the FP context and have previously used MSA then we have to restore the whole vector context anyway (see comment in enable_restore_fp_context for details) so similarly we might as well enable MSA. Thus if a task does not use MSA then it will continue to behave as without this patch - the scalar FP context will be saved & restored as usual. But if a task executes an MSA instruction then it will save & restore the vector context forever more. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6431/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
125 lines
3.8 KiB
C
125 lines
3.8 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
|
|
* Copyright (C) 1996 by Paul M. Antoine
|
|
* Copyright (C) 1999 Silicon Graphics
|
|
* Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
|
|
* Copyright (C) 2000 MIPS Technologies, Inc.
|
|
*/
|
|
#ifndef _ASM_SWITCH_TO_H
|
|
#define _ASM_SWITCH_TO_H
|
|
|
|
#include <asm/cpu-features.h>
|
|
#include <asm/watch.h>
|
|
#include <asm/dsp.h>
|
|
#include <asm/cop2.h>
|
|
#include <asm/msa.h>
|
|
|
|
struct task_struct;
|
|
|
|
enum {
|
|
FP_SAVE_NONE = 0,
|
|
FP_SAVE_VECTOR = -1,
|
|
FP_SAVE_SCALAR = 1,
|
|
};
|
|
|
|
/**
|
|
* resume - resume execution of a task
|
|
* @prev: The task previously executed.
|
|
* @next: The task to begin executing.
|
|
* @next_ti: task_thread_info(next).
|
|
* @fp_save: Which, if any, FP context to save for prev.
|
|
*
|
|
* This function is used whilst scheduling to save the context of prev & load
|
|
* the context of next. Returns prev.
|
|
*/
|
|
extern asmlinkage struct task_struct *resume(struct task_struct *prev,
|
|
struct task_struct *next, struct thread_info *next_ti,
|
|
s32 fp_save);
|
|
|
|
extern unsigned int ll_bit;
|
|
extern struct task_struct *ll_task;
|
|
|
|
#ifdef CONFIG_MIPS_MT_FPAFF
|
|
|
|
/*
|
|
* Handle the scheduler resume end of FPU affinity management. We do this
|
|
* inline to try to keep the overhead down. If we have been forced to run on
|
|
* a "CPU" with an FPU because of a previous high level of FP computation,
|
|
* but did not actually use the FPU during the most recent time-slice (CU1
|
|
* isn't set), we undo the restriction on cpus_allowed.
|
|
*
|
|
* We're not calling set_cpus_allowed() here, because we have no need to
|
|
* force prompt migration - we're already switching the current CPU to a
|
|
* different thread.
|
|
*/
|
|
|
|
#define __mips_mt_fpaff_switch_to(prev) \
|
|
do { \
|
|
struct thread_info *__prev_ti = task_thread_info(prev); \
|
|
\
|
|
if (cpu_has_fpu && \
|
|
test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) && \
|
|
(!(KSTK_STATUS(prev) & ST0_CU1))) { \
|
|
clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND); \
|
|
prev->cpus_allowed = prev->thread.user_cpus_allowed; \
|
|
} \
|
|
next->thread.emulated_fp = 0; \
|
|
} while(0)
|
|
|
|
#else
|
|
#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
|
|
#endif
|
|
|
|
#define __clear_software_ll_bit() \
|
|
do { \
|
|
if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc) \
|
|
ll_bit = 0; \
|
|
} while (0)
|
|
|
|
#define switch_to(prev, next, last) \
|
|
do { \
|
|
u32 __c0_stat; \
|
|
s32 __fpsave = FP_SAVE_NONE; \
|
|
__mips_mt_fpaff_switch_to(prev); \
|
|
if (cpu_has_dsp) \
|
|
__save_dsp(prev); \
|
|
if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) { \
|
|
if (cop2_lazy_restore) \
|
|
KSTK_STATUS(prev) &= ~ST0_CU2; \
|
|
__c0_stat = read_c0_status(); \
|
|
write_c0_status(__c0_stat | ST0_CU2); \
|
|
cop2_save(&prev->thread.cp2); \
|
|
write_c0_status(__c0_stat & ~ST0_CU2); \
|
|
} \
|
|
__clear_software_ll_bit(); \
|
|
if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU)) \
|
|
__fpsave = FP_SAVE_SCALAR; \
|
|
if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA)) \
|
|
__fpsave = FP_SAVE_VECTOR; \
|
|
(last) = resume(prev, next, task_thread_info(next), __fpsave); \
|
|
disable_msa(); \
|
|
} while (0)
|
|
|
|
#define finish_arch_switch(prev) \
|
|
do { \
|
|
u32 __c0_stat; \
|
|
if (cop2_present && !cop2_lazy_restore && \
|
|
(KSTK_STATUS(current) & ST0_CU2)) { \
|
|
__c0_stat = read_c0_status(); \
|
|
write_c0_status(__c0_stat | ST0_CU2); \
|
|
cop2_restore(¤t->thread.cp2); \
|
|
write_c0_status(__c0_stat & ~ST0_CU2); \
|
|
} \
|
|
if (cpu_has_dsp) \
|
|
__restore_dsp(current); \
|
|
if (cpu_has_userlocal) \
|
|
write_c0_userlocal(current_thread_info()->tp_value); \
|
|
__restore_watch(); \
|
|
} while (0)
|
|
|
|
#endif /* _ASM_SWITCH_TO_H */
|