Skip to content

Commit e02c09b

Browse files
committed
mips64: Don't store REGTMP with GPRS
REGTMP is the scratch register used by the assembler. Saving it with GPRS is bad because one needs to be extra careful writing assembly that won't clobber REGTMP as long as it's not saved or after it's restored. Instead try to save it as early and restore it as late as possible to prevent bugs, that will only be visible in the disassembly.
1 parent e78cfa2 commit e02c09b

File tree

2 files changed

+37
-27
lines changed

2 files changed

+37
-27
lines changed

src/runtime/tasker_noos_mips64.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ import (
2424

2525
// See saveGPRS and saveFPRS
2626
const (
27-
numGPRS = 28
27+
numGPRS = 27
2828
numFPRS = 33
2929
)
3030

3131
type mOS struct {
3232
// thread context
33-
gprs [numGPRS]uintptr
34-
fprs [numFPRS]float64
35-
sp, fp, ra, epc uintptr
33+
gprs [numGPRS]uintptr
34+
fprs [numFPRS]float64
35+
sp, fp, ra, epc, tmp uintptr
3636
}
3737

3838
var (

src/runtime/tasker_noos_mips64.s

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
#define _lr (0*8)
4747
#define _mstatus (1*8)
4848
#define _mepc (2*8)
49-
#define excCtxSize (3*8)
49+
#define _mregtmp (3*8)
50+
#define excCtxSize (4*8)
5051

5152

5253
// This will be copied into the processor's general exception vector. Since the
@@ -69,6 +70,9 @@ TEXT runtime·intvector(SB),NOSPLIT|NOFRAME,$0
6970
// Only syscalls and interrupts are handled at the moment, all other exceptions
7071
// are fatal.
7172
TEXT runtime·exceptionHandler(SB),NOSPLIT|NOFRAME,$0
73+
// Be especially careful to not clobber REGTMP with multi-instruction
74+
// statements until it's saved on the stack.
75+
7276
// Determine caller stack
7377
MOVV $·cpu0(SB), R26
7478
BNE R26, g, fromThread
@@ -89,6 +93,7 @@ fromThread:
8993
fromHandler:
9094
// Save exception context on ISR stack
9195
SUB $excCtxSize, R29
96+
MOVV R23, _mregtmp(R29) // R23 (REGTMP) is now free for use
9297
OR $1, R31, R26 // Encode smallCtx flag in lr
9398
MOVV R26, _lr(R29) // R29 is now free for use
9499
MOVV M(C0_SR), R26
@@ -170,7 +175,8 @@ TEXT runtime·syscallHandler(SB),NOSPLIT|NOFRAME,$0
170175

171176
MOVV _lr(R29), R3
172177
MOVV R3, (m_mOS+mOS_ra)(R2)
173-
178+
MOVV _mregtmp(R29), R3
179+
MOVV R3, (m_mOS+mOS_tmp)(R2)
174180
MOVV _mepc(R29), R3
175181
AND $~1, R3 // Remove fromHandler flag from epc
176182
MOVV R3, (m_mOS+mOS_epc)(R2)
@@ -249,6 +255,9 @@ TEXT runtime·softwareInterruptHandler(SB),NOSPLIT|NOFRAME,$0
249255
// Save thread context in mOS
250256
MOVV (cpuctx_exe)(g), R27
251257

258+
MOVV _mregtmp(R29), R26
259+
MOVV R26, (m_mOS+mOS_tmp)(R27)
260+
252261
MOVV _lr(R29), R26
253262
AND $~1, R26 // Remove smallCtx flag from lr
254263
MOVV R26, (m_mOS+mOS_ra)(R27)
@@ -315,8 +324,8 @@ smallCtx:
315324
MOVV (m_mOS+mOS_ra)(R27), R31
316325
MOVV (m_mOS+mOS_epc)(R27), R26
317326
MOVV R26, M(C0_EPC)
318-
MOVV $~1, R27
319-
AND R27, R31 // Remove smallCtx flag
327+
AND $~1, R31 // Remove smallCtx flag
328+
MOVV (m_mOS+mOS_tmp)(R27), R23
320329

321330
ERET
322331

@@ -426,11 +435,9 @@ TEXT runtime·exceptionReturn(SB),NOSPLIT|NOFRAME,$0
426435
MOVV $1, R27
427436
AND R26, R27
428437

429-
ADD $excCtxSize, R29
430-
431438
// Don't restore interrupt mask or switch stacks yet if we were called
432439
// from handler
433-
BNE R27, R0, return
440+
BNE R27, R0, fromHandler
434441

435442
MOVW M(C0_SR), R26
436443
MOVW $~INTR_EXT, R27
@@ -441,11 +448,18 @@ TEXT runtime·exceptionReturn(SB),NOSPLIT|NOFRAME,$0
441448
OR R27, R26
442449
MOVW R26, M(C0_SR)
443450

451+
MOVV _mregtmp(R29), R23
452+
ADD $excCtxSize, R29
444453
MOVV $·cpu0(SB), R26
445454
MOVV (g_sched+gobuf_sp)(R26), R29
446455
MOVV (g_sched+gobuf_g)(R26), g
447456

448-
return:
457+
ERET
458+
459+
fromHandler:
460+
MOVV _mregtmp(R29), R23
461+
ADD $excCtxSize, R29
462+
449463
ERET
450464

451465

@@ -478,29 +492,25 @@ TEXT ·saveGPRs(SB),NOSPLIT|NOFRAME,$0
478492
MOVV R20, 152(R26)
479493
MOVV R21, 160(R26)
480494
MOVV R22, 168(R26)
481-
MOVV R23, 176(R26)
482-
MOVV R24, 184(R26)
483-
MOVV R25, 192(R26)
484-
MOVV RSB, 200(R26)
495+
MOVV R24, 176(R26)
496+
MOVV R25, 184(R26)
497+
MOVV RSB, 192(R26)
485498
MOVV HI, R1
486-
MOVV R1, 208(R26)
499+
MOVV R1, 200(R26)
487500
MOVV LO, R1
488-
MOVV R1, 216(R26)
501+
MOVV R1, 208(R26)
489502
RET
490503

491504

492-
// R26 must point to stored gprs. Only use R26, R27 after restoring. Be
493-
// especially careful and look at the disassembly; The assembler might decide
494-
// to use R16-R23 for you.
505+
// R26 must point to stored gprs. Only use R26, R27 after restoring.
495506
TEXT ·restoreGPRs(SB),NOSPLIT|NOFRAME,$0
496-
MOVV 216(R26), R1
497-
MOVV R1, LO
498507
MOVV 208(R26), R1
508+
MOVV R1, LO
509+
MOVV 200(R26), R1
499510
MOVV R1, HI
500-
MOVV 200(R26), RSB
501-
MOVV 192(R26), R25
502-
MOVV 184(R26), R24
503-
MOVV 176(R26), R23
511+
MOVV 192(R26), RSB
512+
MOVV 184(R26), R25
513+
MOVV 176(R26), R24
504514
MOVV 168(R26), R22
505515
MOVV 160(R26), R21
506516
MOVV 152(R26), R20

0 commit comments

Comments
 (0)