aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/stackframe.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-04-05 04:45:45 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-04-18 22:14:28 -0400
commit41c594ab65fc89573af296d192aa5235d09717ab (patch)
tree562462512a320f386bdf49eabfbb26bb3ee761fa /include/asm-mips/stackframe.h
parent2600990e640e3bef29ed89d565864cf16ee83833 (diff)
[MIPS] MT: Improved multithreading support.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips/stackframe.h')
-rw-r--r--include/asm-mips/stackframe.h187
1 files changed, 184 insertions, 3 deletions
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 2acf3e844f00..c4856a874965 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -14,9 +14,14 @@
14#include <linux/threads.h> 14#include <linux/threads.h>
15 15
16#include <asm/asm.h> 16#include <asm/asm.h>
17#include <asm/asmmacro.h>
17#include <asm/mipsregs.h> 18#include <asm/mipsregs.h>
18#include <asm/asm-offsets.h> 19#include <asm/asm-offsets.h>
19 20
21#ifdef CONFIG_MIPS_MT_SMTC
22#include <asm/mipsmtregs.h>
23#endif /* CONFIG_MIPS_MT_SMTC */
24
20 .macro SAVE_AT 25 .macro SAVE_AT
21 .set push 26 .set push
22 .set noat 27 .set noat
@@ -57,13 +62,30 @@
57#ifdef CONFIG_SMP 62#ifdef CONFIG_SMP
58 .macro get_saved_sp /* SMP variation */ 63 .macro get_saved_sp /* SMP variation */
59#ifdef CONFIG_32BIT 64#ifdef CONFIG_32BIT
65#ifdef CONFIG_MIPS_MT_SMTC
66 .set mips32
67 mfc0 k0, CP0_TCBIND;
68 .set mips0
69 lui k1, %hi(kernelsp)
70 srl k0, k0, 19
71 /* No need to shift down and up to clear bits 0-1 */
72#else
60 mfc0 k0, CP0_CONTEXT 73 mfc0 k0, CP0_CONTEXT
61 lui k1, %hi(kernelsp) 74 lui k1, %hi(kernelsp)
62 srl k0, k0, 23 75 srl k0, k0, 23
76#endif
63 addu k1, k0 77 addu k1, k0
64 LONG_L k1, %lo(kernelsp)(k1) 78 LONG_L k1, %lo(kernelsp)(k1)
65#endif 79#endif
66#ifdef CONFIG_64BIT 80#ifdef CONFIG_64BIT
81#ifdef CONFIG_MIPS_MT_SMTC
82 .set mips64
83 mfc0 k0, CP0_TCBIND;
84 .set mips0
85 lui k0, %highest(kernelsp)
86 dsrl k1, 19
87 /* No need to shift down and up to clear bits 0-2 */
88#else
67 MFC0 k1, CP0_CONTEXT 89 MFC0 k1, CP0_CONTEXT
68 lui k0, %highest(kernelsp) 90 lui k0, %highest(kernelsp)
69 dsrl k1, 23 91 dsrl k1, 23
@@ -71,20 +93,31 @@
71 dsll k0, k0, 16 93 dsll k0, k0, 16
72 daddiu k0, %hi(kernelsp) 94 daddiu k0, %hi(kernelsp)
73 dsll k0, k0, 16 95 dsll k0, k0, 16
96#endif /* CONFIG_MIPS_MT_SMTC */
74 daddu k1, k1, k0 97 daddu k1, k1, k0
75 LONG_L k1, %lo(kernelsp)(k1) 98 LONG_L k1, %lo(kernelsp)(k1)
76#endif 99#endif /* CONFIG_64BIT */
77 .endm 100 .endm
78 101
79 .macro set_saved_sp stackp temp temp2 102 .macro set_saved_sp stackp temp temp2
80#ifdef CONFIG_32BIT 103#ifdef CONFIG_32BIT
104#ifdef CONFIG_MIPS_MT_SMTC
105 mfc0 \temp, CP0_TCBIND
106 srl \temp, 19
107#else
81 mfc0 \temp, CP0_CONTEXT 108 mfc0 \temp, CP0_CONTEXT
82 srl \temp, 23 109 srl \temp, 23
83#endif 110#endif
111#endif
84#ifdef CONFIG_64BIT 112#ifdef CONFIG_64BIT
113#ifdef CONFIG_MIPS_MT_SMTC
114 mfc0 \temp, CP0_TCBIND
115 dsrl \temp, 19
116#else
85 MFC0 \temp, CP0_CONTEXT 117 MFC0 \temp, CP0_CONTEXT
86 dsrl \temp, 23 118 dsrl \temp, 23
87#endif 119#endif
120#endif
88 LONG_S \stackp, kernelsp(\temp) 121 LONG_S \stackp, kernelsp(\temp)
89 .endm 122 .endm
90#else 123#else
@@ -122,10 +155,25 @@
122 PTR_SUBU sp, k1, PT_SIZE 155 PTR_SUBU sp, k1, PT_SIZE
123 LONG_S k0, PT_R29(sp) 156 LONG_S k0, PT_R29(sp)
124 LONG_S $3, PT_R3(sp) 157 LONG_S $3, PT_R3(sp)
158 /*
159 * You might think that you don't need to save $0,
160 * but the FPU emulator and gdb remote debug stub
161 * need it to operate correctly
162 */
125 LONG_S $0, PT_R0(sp) 163 LONG_S $0, PT_R0(sp)
126 mfc0 v1, CP0_STATUS 164 mfc0 v1, CP0_STATUS
127 LONG_S $2, PT_R2(sp) 165 LONG_S $2, PT_R2(sp)
128 LONG_S v1, PT_STATUS(sp) 166 LONG_S v1, PT_STATUS(sp)
167#ifdef CONFIG_MIPS_MT_SMTC
168 /*
169 * Ideally, these instructions would be shuffled in
170 * to cover the pipeline delay.
171 */
172 .set mips32
173 mfc0 v1, CP0_TCSTATUS
174 .set mips0
175 LONG_S v1, PT_TCSTATUS(sp)
176#endif /* CONFIG_MIPS_MT_SMTC */
129 LONG_S $4, PT_R4(sp) 177 LONG_S $4, PT_R4(sp)
130 mfc0 v1, CP0_CAUSE 178 mfc0 v1, CP0_CAUSE
131 LONG_S $5, PT_R5(sp) 179 LONG_S $5, PT_R5(sp)
@@ -234,14 +282,36 @@
234 .endm 282 .endm
235 283
236#else 284#else
285/*
286 * For SMTC kernel, global IE should be left set, and interrupts
287 * controlled exclusively via IXMT.
288 */
237 289
290#ifdef CONFIG_MIPS_MT_SMTC
291#define STATMASK 0x1e
292#else
293#define STATMASK 0x1f
294#endif
238 .macro RESTORE_SOME 295 .macro RESTORE_SOME
239 .set push 296 .set push
240 .set reorder 297 .set reorder
241 .set noat 298 .set noat
299#ifdef CONFIG_MIPS_MT_SMTC
300 .set mips32r2
301 /*
302 * This may not really be necessary if ints are already
303 * inhibited here.
304 */
305 mfc0 v0, CP0_TCSTATUS
306 ori v0, TCSTATUS_IXMT
307 mtc0 v0, CP0_TCSTATUS
308 ehb
309 DMT 5 # dmt a1
310 jal mips_ihb
311#endif /* CONFIG_MIPS_MT_SMTC */
242 mfc0 a0, CP0_STATUS 312 mfc0 a0, CP0_STATUS
243 ori a0, 0x1f 313 ori a0, STATMASK
244 xori a0, 0x1f 314 xori a0, STATMASK
245 mtc0 a0, CP0_STATUS 315 mtc0 a0, CP0_STATUS
246 li v1, 0xff00 316 li v1, 0xff00
247 and a0, v1 317 and a0, v1
@@ -250,6 +320,26 @@
250 and v0, v1 320 and v0, v1
251 or v0, a0 321 or v0, a0
252 mtc0 v0, CP0_STATUS 322 mtc0 v0, CP0_STATUS
323#ifdef CONFIG_MIPS_MT_SMTC
324/*
325 * Only after EXL/ERL have been restored to status can we
326 * restore TCStatus.IXMT.
327 */
328 LONG_L v1, PT_TCSTATUS(sp)
329 ehb
330 mfc0 v0, CP0_TCSTATUS
331 andi v1, TCSTATUS_IXMT
332 /* We know that TCStatua.IXMT should be set from above */
333 xori v0, v0, TCSTATUS_IXMT
334 or v0, v0, v1
335 mtc0 v0, CP0_TCSTATUS
336 ehb
337 andi a1, a1, VPECONTROL_TE
338 beqz a1, 1f
339 emt
3401:
341 .set mips0
342#endif /* CONFIG_MIPS_MT_SMTC */
253 LONG_L v1, PT_EPC(sp) 343 LONG_L v1, PT_EPC(sp)
254 MTC0 v1, CP0_EPC 344 MTC0 v1, CP0_EPC
255 LONG_L $31, PT_R31(sp) 345 LONG_L $31, PT_R31(sp)
@@ -302,11 +392,33 @@
302 * Set cp0 enable bit as sign that we're running on the kernel stack 392 * Set cp0 enable bit as sign that we're running on the kernel stack
303 */ 393 */
304 .macro CLI 394 .macro CLI
395#if !defined(CONFIG_MIPS_MT_SMTC)
305 mfc0 t0, CP0_STATUS 396 mfc0 t0, CP0_STATUS
306 li t1, ST0_CU0 | 0x1f 397 li t1, ST0_CU0 | 0x1f
307 or t0, t1 398 or t0, t1
308 xori t0, 0x1f 399 xori t0, 0x1f
309 mtc0 t0, CP0_STATUS 400 mtc0 t0, CP0_STATUS
401#else /* CONFIG_MIPS_MT_SMTC */
402 /*
403 * For SMTC, we need to set privilege
404 * and disable interrupts only for the
405 * current TC, using the TCStatus register.
406 */
407 mfc0 t0,CP0_TCSTATUS
408 /* Fortunately CU 0 is in the same place in both registers */
409 /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
410 li t1, ST0_CU0 | 0x08001c00
411 or t0,t1
412 /* Clear TKSU, leave IXMT */
413 xori t0, 0x00001800
414 mtc0 t0, CP0_TCSTATUS
415 ehb
416 /* We need to leave the global IE bit set, but clear EXL...*/
417 mfc0 t0, CP0_STATUS
418 ori t0, ST0_EXL | ST0_ERL
419 xori t0, ST0_EXL | ST0_ERL
420 mtc0 t0, CP0_STATUS
421#endif /* CONFIG_MIPS_MT_SMTC */
310 irq_disable_hazard 422 irq_disable_hazard
311 .endm 423 .endm
312 424
@@ -315,11 +427,35 @@
315 * Set cp0 enable bit as sign that we're running on the kernel stack 427 * Set cp0 enable bit as sign that we're running on the kernel stack
316 */ 428 */
317 .macro STI 429 .macro STI
430#if !defined(CONFIG_MIPS_MT_SMTC)
318 mfc0 t0, CP0_STATUS 431 mfc0 t0, CP0_STATUS
319 li t1, ST0_CU0 | 0x1f 432 li t1, ST0_CU0 | 0x1f
320 or t0, t1 433 or t0, t1
321 xori t0, 0x1e 434 xori t0, 0x1e
322 mtc0 t0, CP0_STATUS 435 mtc0 t0, CP0_STATUS
436#else /* CONFIG_MIPS_MT_SMTC */
437 /*
438 * For SMTC, we need to set privilege
439 * and enable interrupts only for the
440 * current TC, using the TCStatus register.
441 */
442 ehb
443 mfc0 t0,CP0_TCSTATUS
444 /* Fortunately CU 0 is in the same place in both registers */
445 /* Set TCU0, TKSU (for later inversion) and IXMT */
446 li t1, ST0_CU0 | 0x08001c00
447 or t0,t1
448 /* Clear TKSU *and* IXMT */
449 xori t0, 0x00001c00
450 mtc0 t0, CP0_TCSTATUS
451 ehb
452 /* We need to leave the global IE bit set, but clear EXL...*/
453 mfc0 t0, CP0_STATUS
454 ori t0, ST0_EXL
455 xori t0, ST0_EXL
456 mtc0 t0, CP0_STATUS
457 /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
458#endif /* CONFIG_MIPS_MT_SMTC */
323 irq_enable_hazard 459 irq_enable_hazard
324 .endm 460 .endm
325 461
@@ -328,11 +464,56 @@
328 * Set cp0 enable bit as sign that we're running on the kernel stack 464 * Set cp0 enable bit as sign that we're running on the kernel stack
329 */ 465 */
330 .macro KMODE 466 .macro KMODE
467#ifdef CONFIG_MIPS_MT_SMTC
468 /*
469 * This gets baroque in SMTC. We want to
470 * protect the non-atomic clearing of EXL
471 * with DMT/EMT, but we don't want to take
472 * an interrupt while DMT is still in effect.
473 */
474
475 /* KMODE gets invoked from both reorder and noreorder code */
476 .set push
477 .set mips32r2
478 .set noreorder
479 mfc0 v0, CP0_TCSTATUS
480 andi v1, v0, TCSTATUS_IXMT
481 ori v0, TCSTATUS_IXMT
482 mtc0 v0, CP0_TCSTATUS
483 ehb
484 DMT 2 # dmt v0
485 /*
486 * We don't know a priori if ra is "live"
487 */
488 move t0, ra
489 jal mips_ihb
490 nop /* delay slot */
491 move ra, t0
492#endif /* CONFIG_MIPS_MT_SMTC */
331 mfc0 t0, CP0_STATUS 493 mfc0 t0, CP0_STATUS
332 li t1, ST0_CU0 | 0x1e 494 li t1, ST0_CU0 | 0x1e
333 or t0, t1 495 or t0, t1
334 xori t0, 0x1e 496 xori t0, 0x1e
335 mtc0 t0, CP0_STATUS 497 mtc0 t0, CP0_STATUS
498#ifdef CONFIG_MIPS_MT_SMTC
499 ehb
500 andi v0, v0, VPECONTROL_TE
501 beqz v0, 2f
502 nop /* delay slot */
503 emt
5042:
505 mfc0 v0, CP0_TCSTATUS
506 /* Clear IXMT, then OR in previous value */
507 ori v0, TCSTATUS_IXMT
508 xori v0, TCSTATUS_IXMT
509 or v0, v1, v0
510 mtc0 v0, CP0_TCSTATUS
511 /*
512 * irq_disable_hazard below should expand to EHB
513 * on 24K/34K CPUS
514 */
515 .set pop
516#endif /* CONFIG_MIPS_MT_SMTC */
336 irq_disable_hazard 517 irq_disable_hazard
337 .endm 518 .endm
338 519