diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index d690a626dba6a0..d91fc6f98b0265 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -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)) diff --git a/src/runtime/rt0_noos_mips64.s b/src/runtime/rt0_noos_mips64.s index f3f3aa665b032d..facd3026b897eb 100644 --- a/src/runtime/rt0_noos_mips64.s +++ b/src/runtime/rt0_noos_mips64.s @@ -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 @@ -45,6 +49,7 @@ 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 @@ -52,12 +57,13 @@ loop: 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 @@ -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) @@ -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 diff --git a/src/runtime/tasker_noos_mips64.go b/src/runtime/tasker_noos_mips64.go index cebc3539e52df8..e583a3a3f32740 100644 --- a/src/runtime/tasker_noos_mips64.go +++ b/src/runtime/tasker_noos_mips64.go @@ -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 ( @@ -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 @@ -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 } } diff --git a/src/runtime/tasker_noos_mips64.s b/src/runtime/tasker_noos_mips64.s index a7c33db906cfc8..672b0865ba6303 100644 --- a/src/runtime/tasker_noos_mips64.s +++ b/src/runtime/tasker_noos_mips64.s @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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) @@ -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 @@ -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 @@ -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 @@ -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