diff options
| author | Derek Hensley <hensley.derek58@gmail.com> | 2025-02-21 16:03:51 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-21 17:03:51 -0700 |
| commit | 8c6ae625aef6d07741cd8925f422f43ae24b198c (patch) | |
| tree | 741fafdf5cf11006a23a9019451082c269fe4922 /lib/ultralib/src/os/setintmask.s | |
| parent | f013a028f42a1b11134bc5f22f28e9f48236b6f0 (diff) | |
Ultralib Update (#233)
* git subrepo pull (merge) lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "74f0eee"
upstream:
origin: "git@github.com:decompals/ultralib.git"
branch: "main"
commit: "2717d45"
git-subrepo:
version: "0.4.9"
origin: "https://github.com/ingydotnet/git-subrepo"
commit: "cce3d93"
* New ultralib fixes
* Update some includes in tools
* git subrepo commit (merge) lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "3a702eaf"
upstream:
origin: "git@github.com:decompals/ultralib.git"
branch: "main"
commit: "48f9f908"
git-subrepo:
version: "0.4.9"
origin: "git@github.com:ingydotnet/git-subrepo.git"
commit: "ea10886"
* Update warnings file
Diffstat (limited to 'lib/ultralib/src/os/setintmask.s')
| -rw-r--r-- | lib/ultralib/src/os/setintmask.s | 100 |
1 files changed, 69 insertions, 31 deletions
diff --git a/lib/ultralib/src/os/setintmask.s b/lib/ultralib/src/os/setintmask.s index f19ed17..b9f93b0 100644 --- a/lib/ultralib/src/os/setintmask.s +++ b/lib/ultralib/src/os/setintmask.s @@ -10,47 +10,85 @@ .text .set noreorder -LEAF(osSetIntMask) - mfc0 ta0, C0_SR +/** + * OSIntMask osSetIntMask(OSIntMask); + * + * Sets the interrupt enable mask for the current thread. External interrupts + * originating either in the CPU or the RCP may be "masked out" so that they + * are not handled. This is sometimes important for critical code sections + * that must not be interrupted. + * Interrupts that are not enabled in the global interrupt mask __OSGlobalIntMask + * cannot be set here. The global interrupt mask is OS-internal and is not + * expected to change during runtime. + * The returned value is the previous interrupt enable mask so that it can be + * restored later. + * + * @bug Some usage of the global interrupt mask is broken both in here and in the + * exception handler routines. + * While a thread is running, the C0_SR interrupt enable bits contain the + * interrupt enable bits for the current thread masked by the global + * interrupt mask. There is an attempt to recover only the original interrupt + * enable bits belonging to the thread itself using the operation + * (SR | ~__OSGlobalIntMask). + * However, this does not work as intended and can cause interrupts to end + * up enabled when not intended to be. The same issue is present for the + * RCP interrupt enable bits in MI_INTR_MASK_REG. + * This does not cause issues in practice as __OSGlobalIntMask is almost always + * OS_IM_ALL, so the operation is usually simply (SR | 0). + */ +LEAF(osSetIntMask) + /* Extract interrupt enable bits from current SR */ + mfc0 ta0, C0_SR - andi v0, ta0, OS_IM_CPU + andi v0, ta0, OS_IM_CPU - la t0, __OSGlobalIntMask - lw t3, 0(t0) - - xor t0, t3,-1 - andi t0, t0,(SR_IMASK) - or v0, v0,t0 + /* Get value of __OSGlobalIntMask */ + la t0, __OSGlobalIntMask + lw t3, 0(t0) - lw t2, PHYS_TO_K1(MI_INTR_MASK_REG) - beqz t2, 1f - srl t1, t3,0x10 + /* Bitwise-OR in the disabled CPU bits of __OSGlobalIntMask */ + xor t0, t3, ~0 + andi t0, t0, SR_IMASK + or v0, v0, t0 - xor t1, t1,-1 - andi t1, t1, MI_INTR_MASK - or t2, t2,t1 + /* Fetch MI_INTR_MASK_REG */ + lw t2, PHYS_TO_K1(MI_INTR_MASK_REG) + /* If there are RCP interrupts masked */ + beqz t2, 1f + srl t1, t3, 0x10 + + /* Bitwise-OR in the disabled RCP bits of __OSGlobalIntMask */ + xor t1, t1, ~0 + andi t1, t1, (RCP_IMASK >> RCP_IMASKSHIFT) + or t2, t2, t1 1: - sll t2, t2,0x10 - or v0, v0,t2 + /* Shift the RCP bits to not conflict with the CPU bits */ + sll t2, t2, RCP_IMASKSHIFT + /* OR the CPU and RCP bits together */ + or v0, v0, t2 - and t0, a0, MI_INTR_MASK<<0x10 - and t0, t0,t3 - srl t0, t0,0xf - lhu t2, __osRcpImTable(t0) - sw t2, PHYS_TO_K1(MI_INTR_MASK_REG) - - andi t0, a0, OS_IM_CPU - andi t1, t3, SR_IMASK - and t0, t0,t1 + /* Extract RCP interrupt enable bits from requested mask and mask with __OSGlobalIntMask */ + and t0, a0, RCP_IMASK + and t0, t0, t3 + /* Convert to a value for MI_INTR_MASK_REG and set it */ + srl t0, t0, (RCP_IMASKSHIFT - 1) + lhu t2, __osRcpImTable(t0) + sw t2, PHYS_TO_K1(MI_INTR_MASK_REG) - and ta0, ta0, ~SR_IMASK - or ta0, ta0,t0 + /* Extract CPU interrupt enable bits from requested mask and mask with __OSGlobalIntMask */ + andi t0, a0, OS_IM_CPU + andi t1, t3, SR_IMASK + and t0, t0, t1 - mtc0 ta0, C0_SR - nop + and ta0, ta0, ~SR_IMASK + /* Bitwise OR in the remaining bits of SR and set new SR */ + or ta0, ta0, t0 + + mtc0 ta0, C0_SR nop - jr ra nop + jr ra + nop END(osSetIntMask) .rdata |
