NetBSD-currentの割り込み
FreeBSD 6.3の割り込み - かーねる・う゛いえむにっき
で割り込み時のコンテキストがスタックに退避されてるー、って書いたけど、これはx86に限らず一般的にこうなってるもののようだ。
NetBSD/mipsはそれなりにコードを読んだつもりだったが、割り込み時のコンテキスト退避・復帰とyield()などでのコンテキスト切り替えとシステムコールでの切り替えと、色々あってそれぞれの処理の違いを頭の中でまとめきれてない。(似たようなもんだろ、と思ってたが、良く見るとちょっと違う。)
以下、NetBSD-current/mipsの割り込み処理。
/* * mipsX_KernIntr * * Handle an interrupt from kernel mode. * Build intrframe on stack to hold interrupted kernel context, then * call cpu_intr() to process it. * */ NESTED_NOPROFILE(MIPSX(KernIntr), KERNFRAME_SIZ, ra) .set noat .mask 0x80000000, -4 subu sp, sp, KERNFRAME_SIZ /* * Save the relevant kernel registers onto the stack. * We don't need to save s0 - s8, sp and gp because * the compiler does it for us. */ REG_S AT, TF_BASE+TF_REG_AST(sp) REG_S v0, TF_BASE+TF_REG_V0(sp) REG_S v1, TF_BASE+TF_REG_V1(sp) mflo v0 mfhi v1 REG_S a0, TF_BASE+TF_REG_A0(sp) REG_S a1, TF_BASE+TF_REG_A1(sp) REG_S a2, TF_BASE+TF_REG_A2(sp) REG_S a3, TF_BASE+TF_REG_A3(sp) mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS REG_S t0, TF_BASE+TF_REG_T0(sp) REG_S t1, TF_BASE+TF_REG_T1(sp) REG_S t2, TF_BASE+TF_REG_T2(sp) REG_S t3, TF_BASE+TF_REG_T3(sp) mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE REG_S ta0, TF_BASE+TF_REG_TA0(sp) REG_S ta1, TF_BASE+TF_REG_TA1(sp) REG_S ta2, TF_BASE+TF_REG_TA2(sp) REG_S ta3, TF_BASE+TF_REG_TA3(sp) mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is exception PC REG_S t8, TF_BASE+TF_REG_T8(sp) REG_S t9, TF_BASE+TF_REG_T9(sp) REG_S ra, TF_BASE+TF_REG_RA(sp) REG_S a0, TF_BASE+TF_REG_SR(sp) REG_S v0, TF_BASE+TF_REG_MULLO(sp) REG_S v1, TF_BASE+TF_REG_MULHI(sp) REG_S a2, TF_BASE+TF_REG_EPC(sp) REG_S MIPS_CURLWP, TF_BASE+TF_PAD(sp) # XXX Atheros HAL /* * Call the interrupt handler. */ #if defined(DDB) || defined(DEBUG) || defined(KGDB) move ra, a2 sw ra, KERNFRAME_RA(sp) # for debugging #endif #ifdef IPL_ICU_MASK .set at lw t0, _C_LABEL(md_imask) sw t0, TF_BASE+TF_PPL(sp) .set noat #endif mtc0 zero, MIPS_COP_0_STATUS # Reset exl, trap possible. COP0_SYNC lw MIPS_CURLWP, CPUVAR(CURLWP) # XXX Atheros HAL jal _C_LABEL(cpu_intr) and a3, a0, a1 # 4th is STATUS & CAUSE /* * Restore registers and return from the interrupt. */ mtc0 zero, MIPS_COP_0_STATUS # Disable interrupt COP0_SYNC nop nop nop #ifdef IPL_ICU_MASK .set at lw a0, TF_BASE+TF_PPL(sp) sw a0, _C_LABEL(md_imask) jal _C_LABEL(md_imask_update) nop .set noat #endif REG_L MIPS_CURLWP, TF_BASE+TF_PAD(sp) # XXX Atheros HAL REG_L a0, TF_BASE+TF_REG_SR(sp) # ??? why differs ??? DYNAMIC_STATUS_MASK(a0, t0) # machine dependent masking REG_L t0, TF_BASE+TF_REG_MULLO(sp) REG_L t1, TF_BASE+TF_REG_MULHI(sp) REG_L v0, TF_BASE+TF_REG_EPC(sp) mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs COP0_SYNC mtlo t0 mthi t1 #ifdef notyet /* Check for restartable sequences. */ lui t0, %hi(_C_LABEL(_lock_ras_start)) ori t0, zero, %lo(_C_LABEL(_lock_ras_start)) li t1, -MIPS_LOCK_RAS_SIZE and t1, t1, v0 bne t1, t0, 1f move k1, v0 jal _C_LABEL(_lock_ras) nop mov v0, k1 #endif 1: _MTC0 v0, MIPS_COP_0_EXC_PC # set return address COP0_SYNC REG_L AT, TF_BASE+TF_REG_AST(sp) REG_L v0, TF_BASE+TF_REG_V0(sp) REG_L v1, TF_BASE+TF_REG_V1(sp) REG_L a0, TF_BASE+TF_REG_A0(sp) REG_L a1, TF_BASE+TF_REG_A1(sp) REG_L a2, TF_BASE+TF_REG_A2(sp) REG_L a3, TF_BASE+TF_REG_A3(sp) REG_L t0, TF_BASE+TF_REG_T0(sp) REG_L t1, TF_BASE+TF_REG_T1(sp) REG_L t2, TF_BASE+TF_REG_T2(sp) REG_L t3, TF_BASE+TF_REG_T3(sp) REG_L ta0, TF_BASE+TF_REG_TA0(sp) REG_L ta1, TF_BASE+TF_REG_TA1(sp) REG_L ta2, TF_BASE+TF_REG_TA2(sp) REG_L ta3, TF_BASE+TF_REG_TA3(sp) REG_L t8, TF_BASE+TF_REG_T8(sp) REG_L t9, TF_BASE+TF_REG_T9(sp) REG_L ra, TF_BASE+TF_REG_RA(sp) addu sp, sp, KERNFRAME_SIZ # restore kernel SP eret # return to interrupted point .set at END(MIPSX(KernIntr))
内容はx86のとほぼ変わらんように見える。