Skip to content

mips64: Fix memory initialization and interrupt handling issues #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cmd/link/internal/mips64/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func gentext_noos(ctxt *ld.Link, ldr *loader.Loader) {
// search for user defined ISRs: //go:linkname functionName IRQ%d_Handler
// This code tries to keep runtime.vectors small, by cutting off all irq
// at the end that point to runtime.unhandledExternalInterrupt.
var irqHandlers [5]loader.Sym
var irqHandlers [8]loader.Sym
irqNum := 1
for i := 1; i < len(irqHandlers); i++ {
s := lookupFuncSym(ldr, ld.InterruptHandler(i))
Expand Down
22 changes: 14 additions & 8 deletions src/runtime/rt0_noos_mips64.s
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ TEXT runtime·_rt0_mips64_noos1(SB),NOSPLIT|NOFRAME,$0
// Store RAM size in a register not used by memclrNoHeapPointers
MOVV R4, R16

// Make sure the MIPS64X struct is initialized before calling
// memclrNoHeapPointers.
MOVBU R0, internal∕cpu·MIPS64X+const_offsetMIPS64XHasMSA(SB)

// Clear .bss, .noptrbss and unallocated memory.
SUBU $16, R29

Expand Down Expand Up @@ -45,19 +49,21 @@ TEXT runtime·_rt0_mips64_noos1(SB),NOSPLIT|NOFRAME,$0
// Load interrupt vector
MOVW $runtime·intvector(SB), R8
MOVW $0xa0000000, R9
MOVW $0x80000000, R12
MOVW $4, R10
loop:
MOVW (R8), R11
MOVW R11, 0(R9)
MOVW R11, 0x80(R9)
MOVW R11, 0x100(R9)
MOVW R11, 0x180(R9)
CACHE HIT_INVALIDATE_I, 0(R9)
CACHE HIT_INVALIDATE_I, 0x80(R9)
CACHE HIT_INVALIDATE_I, 0x100(R9)
CACHE HIT_INVALIDATE_I, 0x180(R9)
CACHE HIT_INVALIDATE_I, 0(R12)
CACHE HIT_INVALIDATE_I, 0x80(R12)
CACHE HIT_INVALIDATE_I, 0x100(R12)
CACHE HIT_INVALIDATE_I, 0x180(R12)
ADD $4, R8
ADD $4, R9
ADD $4, R12
ADDU $-1, R10
BGTZ R10,loop

Expand Down Expand Up @@ -101,13 +107,14 @@ TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
MOVV $runtime·nodmaend(SB), R11
SUB $SIGNAL_STACK_SIZE, R9

SUB $32, R29
SUB $48, R29
MOVV R8, 8(R29)
MOVV R9, 16(R29)
MOVV R10, 24(R29)
MOVV R11, 32(R29)
MOVV R0, 40(R29)
JAL runtime·meminit(SB)
ADD $32, R29
ADD $48, R29

// initialize noos tasker and Go scheduler
JAL runtime·taskerinit(SB)
Expand Down Expand Up @@ -153,10 +160,9 @@ TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
ADD $16, R29

// enable interrupts
// TODO where to enable interupts correctly?
MOVW R0, M(C0_COMPARE)
MOVW M(C0_SR), R8
OR $(SR_IE|INTR_SW|INTR_EXT), R8
OR $(SR_IE|INTR_SW), R8
MOVW R8, M(C0_SR)

// start this M
Expand Down
19 changes: 11 additions & 8 deletions src/runtime/tasker_noos_mips64.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ import (

// See saveGPRS and saveFPRS
const (
numGPRS = 28
numGPRS = 27
numFPRS = 33
)

type mOS struct {
// thread context
gprs [numGPRS]uintptr
fprs [numFPRS]float64
sp, fp, ra, epc uintptr
gprs [numGPRS]uintptr
fprs [numFPRS]float64
sp, fp, ra, epc, tmp uintptr
}

var (
Expand Down Expand Up @@ -112,7 +112,10 @@ func syscachemaint(op int, p unsafe.Pointer, size int) {
}
}

var highPrioIRQMask uint32
var (
globalIRQMask uint32
highPrioIRQMask uint32
)

func sysirqctl(irq, ctl, ctxid int) (enabled, prio, errno int) {
if uint(irq) > 8 { // TODO PIC dependent
Expand All @@ -132,14 +135,14 @@ func sysirqctl(irq, ctl, ctxid int) (enabled, prio, errno int) {
} else if ctl > 0 {
atomic.Or32(&highPrioIRQMask, irqMask) // set prio to high
}
creg.STATUS.SetBits(irqMask)
atomic.Or32(&globalIRQMask, irqMask)
case ctl == -2: // disable IRQ
creg.STATUS.ClearBits(irqMask)
atomic.And32(&globalIRQMask, ^irqMask)
default: // -3, IRQ status
if irqMask&atomic.Load(&highPrioIRQMask) != 0 {
prio = 1
}
if creg.STATUS.LoadBits(irqMask) != 0 {
if atomic.Load(&globalIRQMask)&irqMask != 0 {
enabled = 1
}
}
Expand Down
85 changes: 54 additions & 31 deletions src/runtime/tasker_noos_mips64.s
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
#define _lr (0*8)
#define _mstatus (1*8)
#define _mepc (2*8)
#define excCtxSize (3*8)
#define _mregtmp (3*8)
#define excCtxSize (4*8)


// This will be copied into the processor's general exception vector. Since the
Expand All @@ -69,6 +70,9 @@ TEXT runtime·intvector(SB),NOSPLIT|NOFRAME,$0
// Only syscalls and interrupts are handled at the moment, all other exceptions
// are fatal.
TEXT runtime·exceptionHandler(SB),NOSPLIT|NOFRAME,$0
// Be especially careful to not clobber REGTMP with multi-instruction
// statements until it's saved on the stack.

// Determine caller stack
MOVV $·cpu0(SB), R26
BNE R26, g, fromThread
Expand All @@ -89,6 +93,7 @@ fromThread:
fromHandler:
// Save exception context on ISR stack
SUB $excCtxSize, R29
MOVV R23, _mregtmp(R29) // R23 (REGTMP) is now free for use
OR $1, R31, R26 // Encode smallCtx flag in lr
MOVV R26, _lr(R29) // R29 is now free for use
MOVV M(C0_SR), R26
Expand Down Expand Up @@ -170,7 +175,8 @@ TEXT runtime·syscallHandler(SB),NOSPLIT|NOFRAME,$0

MOVV _lr(R29), R3
MOVV R3, (m_mOS+mOS_ra)(R2)

MOVV _mregtmp(R29), R3
MOVV R3, (m_mOS+mOS_tmp)(R2)
MOVV _mepc(R29), R3
AND $~1, R3 // Remove fromHandler flag from epc
MOVV R3, (m_mOS+mOS_epc)(R2)
Expand All @@ -184,7 +190,7 @@ TEXT runtime·syscallHandler(SB),NOSPLIT|NOFRAME,$0

currentStack:
BGTZ R4, badSyscall // slow syscall from handler
ADD $excCtxSize, R29, R1 // duffcopy src handler
ADD $excCtxSize, R29, R1 // duffcopy src

duffcopy:
// 3 extra registers to preserve src, dst and size of result
Expand Down Expand Up @@ -249,6 +255,9 @@ TEXT runtime·softwareInterruptHandler(SB),NOSPLIT|NOFRAME,$0
// Save thread context in mOS
MOVV (cpuctx_exe)(g), R27

MOVV _mregtmp(R29), R26
MOVV R26, (m_mOS+mOS_tmp)(R27)

MOVV _lr(R29), R26
AND $~1, R26 // Remove smallCtx flag from lr
MOVV R26, (m_mOS+mOS_ra)(R27)
Expand Down Expand Up @@ -287,6 +296,10 @@ TEXT runtime·enterScheduler(SB),NOSPLIT|NOFRAME,$0

// Restore mstatus from exception context
MOVV _mstatus(R29), R1
AND $~INTR_EXT, R1
MOVW ·globalIRQMask(SB), R2
AND $INTR_EXT, R2
OR R2, R1
MOVV R1, M(C0_SR)
ADD $excCtxSize, R29

Expand All @@ -311,8 +324,8 @@ smallCtx:
MOVV (m_mOS+mOS_ra)(R27), R31
MOVV (m_mOS+mOS_epc)(R27), R26
MOVV R26, M(C0_EPC)
MOVV $~1, R27
AND R27, R31 // Remove smallCtx flag
AND $~1, R31 // Remove smallCtx flag
MOVV (m_mOS+mOS_tmp)(R27), R23

ERET

Expand Down Expand Up @@ -406,28 +419,42 @@ fatal:

TEXT runtime·exceptionReturn(SB),NOSPLIT|NOFRAME,$0
MOVV _mstatus(R29), R26
AND $~INTR_EXT, R26
MOVW ·globalIRQMask(SB), R27
AND $INTR_EXT, R27
OR R27, R26
MOVV R26, M(C0_SR)
MOVV _lr(R29), R26
MOVV $~1, R27
AND R27, R26, R31 // Remove smallCtx flag from lr
MOVV _lr(R29), R31
AND $~1, R31 // Remove smallCtx flag from lr
MOVV _mepc(R29), R26
MOVV $~1, R27
AND R26, R27 // Remove fromHandler flag from EPC
AND $~1, R26, R27 // Remove fromHandler flag from EPC
MOVV R27, M(C0_EPC)

MOVV $1, R27
AND R26, R27
AND $1, R26, R27

ADD $excCtxSize, R29
// Don't restore interrupt mask or switch stacks yet if we were called
// from handler
BNE R27, R0, fromHandler

// Don't switch stacks yet if we were called from handler
BNE R27, R0, return
MOVW M(C0_SR), R26
AND $~INTR_EXT, R26
MOVW ·globalIRQMask(SB), R27
AND $INTR_EXT, R27
OR R27, R26
MOVW R26, M(C0_SR)

MOVV _mregtmp(R29), R23
ADD $excCtxSize, R29
MOVV $·cpu0(SB), R26
MOVV (g_sched+gobuf_sp)(R26), R29
MOVV (g_sched+gobuf_g)(R26), g

return:
ERET

fromHandler:
MOVV _mregtmp(R29), R23
ADD $excCtxSize, R29

ERET


Expand Down Expand Up @@ -460,29 +487,25 @@ TEXT ·saveGPRs(SB),NOSPLIT|NOFRAME,$0
MOVV R20, 152(R26)
MOVV R21, 160(R26)
MOVV R22, 168(R26)
MOVV R23, 176(R26)
MOVV R24, 184(R26)
MOVV R25, 192(R26)
MOVV RSB, 200(R26)
MOVV R24, 176(R26)
MOVV R25, 184(R26)
MOVV RSB, 192(R26)
MOVV HI, R1
MOVV R1, 208(R26)
MOVV R1, 200(R26)
MOVV LO, R1
MOVV R1, 216(R26)
MOVV R1, 208(R26)
RET


// R26 must point to stored gprs. Only use R26, R27 after restoring. Be
// especially careful and look at the disassembly; The assembler might decide
// to use R16-R23 for you.
// R26 must point to stored gprs. Only use R26, R27 after restoring.
TEXT ·restoreGPRs(SB),NOSPLIT|NOFRAME,$0
MOVV 216(R26), R1
MOVV R1, LO
MOVV 208(R26), R1
MOVV R1, LO
MOVV 200(R26), R1
MOVV R1, HI
MOVV 200(R26), RSB
MOVV 192(R26), R25
MOVV 184(R26), R24
MOVV 176(R26), R23
MOVV 192(R26), RSB
MOVV 184(R26), R25
MOVV 176(R26), R24
MOVV 168(R26), R22
MOVV 160(R26), R21
MOVV 152(R26), R20
Expand Down