From a06213ca112258cacda186ae771a2fddad4ae824 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 19 Jul 2020 20:02:50 +0200 Subject: [PATCH] kernel: mask interrupts during callbacks on SH3! This change fixes very weird bugs first observed with the RTC, related to IMASK not being updated when an interrupt occurs to avoid re-interruption. On SH4 there is a CPUOPM setting that automatically sets IMASK to the level of the accepted interrupt, which is so exactly what every kernel needs that I can't figure out why this isn't the only behavior. Turns out on SH3 it's not even an option. This commit sets IMASK to 15 when accepting a callback on SH3. This most notably prevents the gray engine from updating the screen so callbacks need to be made very short. --- src/core/inth.S | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/core/inth.S b/src/core/inth.S index d5dfbca..2cd6be2 100644 --- a/src/core/inth.S +++ b/src/core/inth.S @@ -217,13 +217,24 @@ _gint_inth_callback: ldc r4, r0_bank ldc r5, r4_bank - /* Enable interrupts and go back to user bank. SR.IMASK is already set + /* Enable interrupts and go back to user bank. On SH4, SR.IMASK is set to the level of the current interrupt, which makes sure we can only be re-interrupted by something with a higher priority. */ - stc sr, r0 - mov.l .SR_clear_RB_BL, r1 - and r1, r0 - ldc r0, sr + stc sr, r1 + mov.l .SR_clear_RB_BL, r0 + and r0, r1 + + /* On SH3, set IMASK to 15 to block interrupts while allowing TLB + misses to be handled. */ + mov.l .gint, r0 + mov.l @r0, r0 + tst #1, r0 + bt .load_sr + mov.l .SR_set_IMASK, r0 + or r0, r1 + +.load_sr: + ldc r1, sr /* We are now in the user bank with r0 and r4 set. Call back. We want to forward the return value to kernel bank, but this bank can be @@ -256,3 +267,7 @@ _gint_inth_callback: .align 4 .SR_clear_RB_BL: .long ~((1 << 29) | (1 << 28)) +.SR_set_IMASK: + .long (0xf << 4) +.gint: + .long _gint