aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-04-05 04:45:47 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-04-18 22:14:28 -0400
commitf088fc84f94c1a36943e28ad704a9a740a35f877 (patch)
tree309add2d3fe666920a681985c36d55f731df9922
parent41c594ab65fc89573af296d192aa5235d09717ab (diff)
[MIPS] FPU affinity for MT ASE.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/Kconfig5
-rw-r--r--arch/mips/kernel/process.c11
-rw-r--r--arch/mips/kernel/scall32-o32.S11
-rw-r--r--arch/mips/kernel/setup.c5
-rw-r--r--arch/mips/kernel/smp-mt.c11
-rw-r--r--arch/mips/kernel/traps.c30
-rw-r--r--include/asm-mips/cpu-features.h2
-rw-r--r--include/asm-mips/fpu.h4
-rw-r--r--include/asm-mips/processor.h16
-rw-r--r--include/asm-mips/system.h32
10 files changed, 125 insertions, 2 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f9be549645ea..87f0b79c6b15 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1464,6 +1464,11 @@ config MIPS_VPE_LOADER
1464 1464
1465endchoice 1465endchoice
1466 1466
1467config MIPS_MT_FPAFF
1468 bool "Dynamic FPU affinity for FP-intensive threads"
1469 depends on MIPS_MT
1470 default y
1471
1467config MIPS_VPE_LOADER_TOM 1472config MIPS_VPE_LOADER_TOM
1468 bool "Load VPE program into memory hidden from linux" 1473 bool "Load VPE program into memory hidden from linux"
1469 depends on MIPS_VPE_LOADER 1474 depends on MIPS_VPE_LOADER
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 8b393df460a2..199a06e873c6 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -185,6 +185,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
185 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); 185 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
186 clear_tsk_thread_flag(p, TIF_USEDFPU); 186 clear_tsk_thread_flag(p, TIF_USEDFPU);
187 187
188#ifdef CONFIG_MIPS_MT_FPAFF
189 /*
190 * FPU affinity support is cleaner if we track the
191 * user-visible CPU affinity from the very beginning.
192 * The generic cpus_allowed mask will already have
193 * been copied from the parent before copy_thread
194 * is invoked.
195 */
196 p->thread.user_cpus_allowed = p->cpus_allowed;
197#endif /* CONFIG_MIPS_MT_FPAFF */
198
188 if (clone_flags & CLONE_SETTLS) 199 if (clone_flags & CLONE_SETTLS)
189 ti->tp_value = regs->regs[7]; 200 ti->tp_value = regs->regs[7];
190 201
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 4e36b87be1ed..a0ac0e5f61ad 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -569,8 +569,19 @@ einval: li v0, -EINVAL
569 sys sys_tkill 2 569 sys sys_tkill 2
570 sys sys_sendfile64 5 570 sys sys_sendfile64 5
571 sys sys_futex 6 571 sys sys_futex 6
572#ifdef CONFIG_MIPS_MT_FPAFF
573 /*
574 * For FPU affinity scheduling on MIPS MT processors, we need to
575 * intercept sys_sched_xxxaffinity() calls until we get a proper hook
576 * in kernel/sched.c. Considered only temporary we only support these
577 * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
578 */
579 sys mipsmt_sys_sched_setaffinity 3
580 sys mipsmt_sys_sched_getaffinity 3
581#else
572 sys sys_sched_setaffinity 3 582 sys sys_sched_setaffinity 3
573 sys sys_sched_getaffinity 3 /* 4240 */ 583 sys sys_sched_getaffinity 3 /* 4240 */
584#endif /* CONFIG_MIPS_MT_FPAFF */
574 sys sys_io_setup 2 585 sys sys_io_setup 2
575 sys sys_io_destroy 1 586 sys sys_io_destroy 1
576 sys sys_io_getevents 5 587 sys sys_io_getevents 5
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index dcbfd27071f0..bcf1b10e518f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -529,7 +529,10 @@ void __init setup_arch(char **cmdline_p)
529 529
530int __init fpu_disable(char *s) 530int __init fpu_disable(char *s)
531{ 531{
532 cpu_data[0].options &= ~MIPS_CPU_FPU; 532 int i;
533
534 for (i = 0; i < NR_CPUS; i++)
535 cpu_data[i].options &= ~MIPS_CPU_FPU;
533 536
534 return 1; 537 return 1;
535} 538}
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 19b8e4b31b79..57770902b9ae 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -150,6 +150,11 @@ void plat_smp_setup(void)
150 unsigned long val; 150 unsigned long val;
151 int i, num; 151 int i, num;
152 152
153#ifdef CONFIG_MIPS_MT_FPAFF
154 /* If we have an FPU, enroll ourselves in the FPU-full mask */
155 if (cpu_has_fpu)
156 cpu_set(0, mt_fpu_cpumask);
157#endif /* CONFIG_MIPS_MT_FPAFF */
153 if (!cpu_has_mipsmt) 158 if (!cpu_has_mipsmt)
154 return; 159 return;
155 160
@@ -312,6 +317,12 @@ void prom_smp_finish(void)
312{ 317{
313 write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); 318 write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
314 319
320#ifdef CONFIG_MIPS_MT_FPAFF
321 /* If we have an FPU, enroll ourselves in the FPU-full mask */
322 if (cpu_has_fpu)
323 cpu_set(smp_processor_id(), mt_fpu_cpumask);
324#endif /* CONFIG_MIPS_MT_FPAFF */
325
315 local_irq_enable(); 326 local_irq_enable();
316} 327}
317 328
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6336fe8008ec..e9902d89dc0a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -758,6 +758,36 @@ asmlinkage void do_cpu(struct pt_regs *regs)
758 &current->thread.fpu.soft); 758 &current->thread.fpu.soft);
759 if (sig) 759 if (sig)
760 force_sig(sig, current); 760 force_sig(sig, current);
761#ifdef CONFIG_MIPS_MT_FPAFF
762 else {
763 /*
764 * MIPS MT processors may have fewer FPU contexts
765 * than CPU threads. If we've emulated more than
766 * some threshold number of instructions, force
767 * migration to a "CPU" that has FP support.
768 */
769 if(mt_fpemul_threshold > 0
770 && ((current->thread.emulated_fp++
771 > mt_fpemul_threshold))) {
772 /*
773 * If there's no FPU present, or if the
774 * application has already restricted
775 * the allowed set to exclude any CPUs
776 * with FPUs, we'll skip the procedure.
777 */
778 if (cpus_intersects(current->cpus_allowed,
779 mt_fpu_cpumask)) {
780 cpumask_t tmask;
781
782 cpus_and(tmask,
783 current->thread.user_cpus_allowed,
784 mt_fpu_cpumask);
785 set_cpus_allowed(current, tmask);
786 current->thread.mflags |= MF_FPUBOUND;
787 }
788 }
789 }
790#endif /* CONFIG_MIPS_MT_FPAFF */
761 } 791 }
762 792
763 return; 793 return;
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 3f2b6d9ac45e..254e11ed247b 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -40,7 +40,7 @@
40#define cpu_has_sb1_cache (cpu_data[0].options & MIPS_CPU_SB1_CACHE) 40#define cpu_has_sb1_cache (cpu_data[0].options & MIPS_CPU_SB1_CACHE)
41#endif 41#endif
42#ifndef cpu_has_fpu 42#ifndef cpu_has_fpu
43#define cpu_has_fpu (cpu_data[0].options & MIPS_CPU_FPU) 43#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
44#endif 44#endif
45#ifndef cpu_has_32fpr 45#ifndef cpu_has_32fpr
46#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) 46#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR)
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 9c828b1f8218..b0f50015e252 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -21,6 +21,10 @@
21#include <asm/processor.h> 21#include <asm/processor.h>
22#include <asm/current.h> 22#include <asm/current.h>
23 23
24#ifdef CONFIG_MIPS_MT_FPAFF
25#include <asm/mips_mt.h>
26#endif
27
24struct sigcontext; 28struct sigcontext;
25struct sigcontext32; 29struct sigcontext32;
26 30
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 786651340de1..0fb75f0762e0 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -134,6 +134,12 @@ struct thread_struct {
134 134
135 /* Saved fpu/fpu emulator stuff. */ 135 /* Saved fpu/fpu emulator stuff. */
136 union mips_fpu_union fpu; 136 union mips_fpu_union fpu;
137#ifdef CONFIG_MIPS_MT_FPAFF
138 /* Emulated instruction count */
139 unsigned long emulated_fp;
140 /* Saved per-thread scheduler affinity mask */
141 cpumask_t user_cpus_allowed;
142#endif /* CONFIG_MIPS_MT_FPAFF */
137 143
138 /* Saved state of the DSP ASE, if available. */ 144 /* Saved state of the DSP ASE, if available. */
139 struct mips_dsp_state dsp; 145 struct mips_dsp_state dsp;
@@ -159,6 +165,12 @@ struct thread_struct {
159#define MF_N32 MF_32BIT_ADDR 165#define MF_N32 MF_32BIT_ADDR
160#define MF_N64 0 166#define MF_N64 0
161 167
168#ifdef CONFIG_MIPS_MT_FPAFF
169#define FPAFF_INIT 0, INIT_CPUMASK,
170#else
171#define FPAFF_INIT
172#endif /* CONFIG_MIPS_MT_FPAFF */
173
162#define INIT_THREAD { \ 174#define INIT_THREAD { \
163 /* \ 175 /* \
164 * saved main processor registers \ 176 * saved main processor registers \
@@ -174,6 +186,10 @@ struct thread_struct {
174 */ \ 186 */ \
175 INIT_FPU, \ 187 INIT_FPU, \
176 /* \ 188 /* \
189 * fpu affinity state (null if not FPAFF) \
190 */ \
191 FPAFF_INIT \
192 /* \
177 * saved dsp/dsp emulator stuff \ 193 * saved dsp/dsp emulator stuff \
178 */ \ 194 */ \
179 INIT_DSP, \ 195 INIT_DSP, \
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 39026690d9e4..261f71d16a07 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -155,6 +155,37 @@ extern asmlinkage void *resume(void *last, void *next, void *next_ti);
155 155
156struct task_struct; 156struct task_struct;
157 157
158#ifdef CONFIG_MIPS_MT_FPAFF
159
160/*
161 * Handle the scheduler resume end of FPU affinity management. We do this
162 * inline to try to keep the overhead down. If we have been forced to run on
163 * a "CPU" with an FPU because of a previous high level of FP computation,
164 * but did not actually use the FPU during the most recent time-slice (CU1
165 * isn't set), we undo the restriction on cpus_allowed.
166 *
167 * We're not calling set_cpus_allowed() here, because we have no need to
168 * force prompt migration - we're already switching the current CPU to a
169 * different thread.
170 */
171
172#define switch_to(prev,next,last) \
173do { \
174 if (cpu_has_fpu && \
175 (prev->thread.mflags & MF_FPUBOUND) && \
176 (!(KSTK_STATUS(prev) & ST0_CU1))) { \
177 prev->thread.mflags &= ~MF_FPUBOUND; \
178 prev->cpus_allowed = prev->thread.user_cpus_allowed; \
179 } \
180 if (cpu_has_dsp) \
181 __save_dsp(prev); \
182 next->thread.emulated_fp = 0; \
183 (last) = resume(prev, next, next->thread_info); \
184 if (cpu_has_dsp) \
185 __restore_dsp(current); \
186} while(0)
187
188#else
158#define switch_to(prev,next,last) \ 189#define switch_to(prev,next,last) \
159do { \ 190do { \
160 if (cpu_has_dsp) \ 191 if (cpu_has_dsp) \
@@ -163,6 +194,7 @@ do { \
163 if (cpu_has_dsp) \ 194 if (cpu_has_dsp) \
164 __restore_dsp(current); \ 195 __restore_dsp(current); \
165} while(0) 196} while(0)
197#endif
166 198
167/* 199/*
168 * On SMP systems, when the scheduler does migration-cost autodetection, 200 * On SMP systems, when the scheduler does migration-cost autodetection,