From bdc296adef172f5320f7165b41c4de376ca108fa Mon Sep 17 00:00:00 2001 From: Elliot Nunn Date: Sun, 8 Jul 2018 17:57:30 +0800 Subject: [PATCH] exceptions round-trip except for FDP offsets (which suck) --- Internal/EmulatorPublic.a | 85 +-- Internal/NKPublic.a | 64 +-- NanoKernel/NKEquates.s | 76 ++- NanoKernel/NKExceptions.s | 1096 +++++++++++++------------------------ NanoKernel/NKFloatingPt.s | 20 +- NanoKernel/NKMacros.s | 4 +- NanoKernel/NKSoftInt.s | 90 +-- NanoKernel/NanoKernel.s | 23 +- 8 files changed, 539 insertions(+), 919 deletions(-) diff --git a/Internal/EmulatorPublic.a b/Internal/EmulatorPublic.a index 57fe932..125b730 100644 --- a/Internal/EmulatorPublic.a +++ b/Internal/EmulatorPublic.a @@ -83,41 +83,59 @@ BootstrapVersion ds.b 16 ; f00:f10 ; Bootstrap loader version info, from Config -; Lives in EDP. Keeping a separate record to EDP makes the code nicer. -; Gets called the "system context" -ContextBlock record 0,INCR +; Move this! + +CB record 0,INCR Flags ds.l 1 ; 000 ; (SPAC) copied from kdp by CreateTask Enables ds.l 1 ; 004 - - org 0x40 -SavedFlags ds.l 1 ; 040 ; from before exception - - org 0x44 -SavedEnables ds.l 1 ; 044 ; from before exception - - org 0x4c + ds.l 1 ; 008 + ds.l 1 ; 00c + ds.l 1 ; 010 + ds.l 1 ; 014 + ds.l 1 ; 018 + ds.l 1 ; 01c + ds.l 1 ; 020 +LowSave17 ds.l 1 ; 024 +LowSave20 ds.l 1 ; 028 +LowSave21 ds.l 1 ; 02c + ds.l 1 ; 030 +LowSave19 ds.l 1 ; 034 + ds.l 1 ; 038 +LowSave18 ds.l 1 ; 03c +ExceptionOriginFlags ds.l 1 ; 040 ; from before exception +ExceptionOriginEnables ds.l 1 ; 044 ; from before exception + ds.l 1 ; 048 ExceptionHandler ds.l 1 ; 04c - - org 0x5c -LA_EmulatorKernelTrapTable ds.l 1 - - org 0x74 -SRR0 ds.l 1 ; 074 - - org 0x84 -LA_EmulatorEntry ds.l 1 ; 084 ; Entry pt of emulator; set by NK Init.s - - org 0x94 -LA_EmulatorData ds.l 1 - - org 0x9c -LA_DispatchTable ds.l 1 - - org 0xa4 + ds.l 1 ; 050 +ExceptionHandlerR4 ds.l 1 ; 054 + ds.l 1 ; 058 +ExceptionHandlerRetAddr ds.l 1 ; 05c + ds.l 1 ; 060 +PropagateR17 ds.l 1 ; 064 +PropagateR20 ds.l 1 ; 068 +PropagateR21 ds.l 1 ; 06c + ds.l 1 ; 070 +PropagateR19 ds.l 1 ; 074 + ds.l 1 ; 078 +PropagateR18 ds.l 1 ; 07c + ds.l 1 ; 080 +ExceptionOriginAddr ds.l 1 ; 084 ; Entry pt of emulator; set by NK Init.s + ds.l 1 ; 088 +ExceptionOriginLR ds.l 1 ; 08c + ds.l 1 ; 090 +ExceptionOriginR3 ds.l 1 ; 094 + ds.l 1 ; 098 +ExceptionOriginR4 ds.l 1 ; 09c + ds.l 1 ; 0a0 MSR ds.l 1 ; 0a4 ; (SPAC) copied from kdp by CreateTask - - org 0xc4 + ds.l 1 ; 0a8 + ds.l 1 ; 0ac + ds.l 1 ; 0b0 + ds.l 1 ; 0b4 + ds.l 1 ; 0b8 + ds.l 1 ; 0bc + ds.l 1 ; 0c0 MQ ds.l 1 ; 0c4 ; 601 only EDPOffsetSWIRelated ds.l 1 ; 0c8 PriorityShifty ds.l 1 ; 0cc ; if low nybble is empty, SchInit sets this to 2 @@ -131,11 +149,8 @@ FE000000 ds.l 1 ; 0e8 ; also LR? LR ds.l 1 ; 0ec CTR ds.l 1 ; 0f0 KernelCTR ds.l 1 ; 0f4 - - org 0xfc + ds.l 1 ; 0f8 CodePtr ds.l 1 ; 0fc ; probably goes in SRR0? - - org 0x100 ds.l 1 r0 ds.l 1 ; 104 ds.l 1 @@ -200,7 +215,5 @@ r29 ds.l 1 ; 1ec r30 ds.l 1 ; 1f4 ds.l 1 r31 ds.l 1 ; 1fc - FloatRegisters ds.d 32 ; 200:300 - endr diff --git a/Internal/NKPublic.a b/Internal/NKPublic.a index 9e5d94d..0432987 100644 --- a/Internal/NKPublic.a +++ b/Internal/NKPublic.a @@ -2,27 +2,6 @@ ; Data structures internal to the NanoKernel ;_______________________________________________________________________ -;_______________________________________________________________________ -; NOTE: DECLARING BIT FIELDS -; -; Bit fields get defined inside a record only in order to give them a -; namespace (e.g. MSR_IP). The _bitEqu macro is used to produce three -; equates per bit: -; (name) = the bit's place value -; (name)bit = the bit's PowerPC index (0 is leftmost) -; (name)shift = the bit's 68k index (0 is rightmost) -;_______________________________________________________________________ - - macro - _bitEqu &name, &bit -&name equ 1 << (31-&bit) -&name.bit equ &bit -&name.shift equ 31 - &bit - endm - - - - ;_______________________________________________________________________ ; INFORECORD PAGE ; @@ -131,7 +110,7 @@ NominalReadyQ ds.l 8 ; -9b0:-990 ; unblocked tasks with priority 2 IdleReadyQ ds.l 8 ; -990:-970 ; unblocked tasks with priority 3 PriorityFlags ds.l 1 ; -970 ; bit 0 is 0, bit 1 is 1, etc... ScrambledMPCallTime ds.l 1 ; -96c ; by MP call return -FlagsTemplate ds.l 1 ; -968 ; typically just EWA.kFlagVec +FlagsTemplate ds.l 1 ; -968 ; typically just bitFlagVec UserModeMSR ds.l 1 ; -964 ThudBuffer ds.b 96 ; -960:-900 ; that's the kernel debugger NoIdeaR23 ds.l 1 ; -900 ; r23 copies here... replated to RTAS? @@ -505,45 +484,6 @@ r31 ds.l 1 ; 07c, cpu+3bc ; Fun fact: offsets past here contain the main kernel globals ; ("Kernel Data Page"), but only on CPU-0. -kFlag0 equ 0 -kFlag1 equ 1 -kFlag2 equ 2 -kFlag3 equ 3 -kFlag4 equ 4 -kFlag5 equ 5 -kFlag6 equ 6 -kFlag7 equ 7 - - ; PER-TASK FLAGS -kFlagEmu equ 8 ; emulator is running -kFlag9 equ 9 ; * = preserved on alt>sys switch -kFlagBlue equ 10 ; * -kFlag11 equ 11 ; * -kFlagVec equ 12 ; * -kFlagHasMQ equ 13 ; * -kFlag14 equ 14 ; * -kFlag15 equ 15 ; * -kFlagSIGP equ 16 ; * - - ; PER-CONTEXT FLAGS -kFlag17 equ 17 -kFlag18 equ 18 -kFlag19 equ 19 - -kFlagFE0 equ 20 ; these correspond with MSR bits -kFlagSE equ 21 -kFlagBE equ 22 -kFlagFE1 equ 23 - -kFlag24 equ 24 -kFlag25 equ 25 -kFlag26 equ 26 ; can be copied from kFlagSE -kFlagLowSaves equ 27 -kFlag28 equ 28 -kFlag29 equ 29 -kFlag30 equ 30 -kFlag31 equ 31 - endr @@ -616,7 +556,7 @@ PA_ECB ds.l 1 ; 658 ; gets called "system context" PA_ContextBlock ds.l 1 ; 65c ; moved to EWA (per-CPU) in NKv2 Flags ds.l 1 ; 660 ; moved to EWA (per-CPU) in NKv2 Enables ds.l 1 ; 664 ; moved to EWA (per-CPU) in NKv2 - ds.l 1 ; 668 +ContextClock ds.l 1 ; 668 PA_PageMapEnd ds.l 1 ; 66c ; Set at the same time as PA_PageMapStart below... TestIntMaskInit ds.l 1 ; 670 ; These are all copied from ConfigInfo... PostIntMaskInit ds.l 1 ; 674 diff --git a/NanoKernel/NKEquates.s b/NanoKernel/NKEquates.s index 5425ed0..1e7f465 100644 --- a/NanoKernel/NKEquates.s +++ b/NanoKernel/NKEquates.s @@ -3,27 +3,38 @@ ;_______________________________________________________________________ +; Helps with making equates +; X = 0x00008000, Xbit=16, Xshift=15 + macro + _bitEqu &bit, &name +&name equ 1 << (31-&bit) +bit&name equ &bit +shift&name equ 31 - &bit + endm + + + kNanoKernelVersion equ $0228 ; PowerPC Machine Status Register (MSR) bits ; (borrowing the _bitEqu macro from NKInfoRecordsPriv.s) - _bitEqu MSR_POW, 13 - _bitEqu MSR_ILE, 15 - _bitEqu MSR_EE, 16 - _bitEqu MSR_PR, 17 - _bitEqu MSR_FP, 18 - _bitEqu MSR_ME, 19 - _bitEqu MSR_FE0, 20 - _bitEqu MSR_SE, 21 - _bitEqu MSR_BE, 22 - _bitEqu MSR_FE1, 23 - _bitEqu MSR_IP, 25 - _bitEqu MSR_IR, 26 - _bitEqu MSR_DR, 27 - _bitEqu MSR_RI, 30 - _bitEqu MSR_LE, 31 + _bitEqu 13, MsrPOW + _bitEqu 15, MsrILE + _bitEqu 16, MsrEE + _bitEqu 17, MsrPR + _bitEqu 18, MsrFP + _bitEqu 19, MsrME + _bitEqu 20, MsrFE0 + _bitEqu 21, MsrSE + _bitEqu 22, MsrBE + _bitEqu 23, MsrFE1 + _bitEqu 25, MsrIP + _bitEqu 26, MsrIR + _bitEqu 27, MsrDR + _bitEqu 30, MsrRI + _bitEqu 31, MsrLE ; Special Purpose Registers (SPRs) not understood by MPW @@ -92,3 +103,38 @@ ecDataWriteViolation equ 21 ; ExceptionMemRetried ecDataSupAccessViolation equ 22 ; ExceptionMemRetried ecDataSupWriteViolation equ 23 ; ? ecUnknown24 equ 24 ; ExceptionMemRetried + + +; Runtime Flag equates + _bitEqu 0, Flag0 + _bitEqu 1, Flag1 + _bitEqu 2, Flag2 + _bitEqu 3, Flag3 + _bitEqu 4, Flag4 + _bitEqu 5, Flag5 + _bitEqu 6, Flag6 + _bitEqu 7, Flag7 + _bitEqu 8, FlagEmu + _bitEqu 9, Flag9 + _bitEqu 10, FlagBlue + _bitEqu 11, Flag11 + _bitEqu 12, FlagVec + _bitEqu 13, FlagHasMQ + _bitEqu 14, Flag14 + _bitEqu 15, Flag15 + _bitEqu 16, FlagSIGP + _bitEqu 17, Flag17 + _bitEqu 18, Flag18 + _bitEqu 19, Flag19 + _bitEqu 20, FlagFE0 + _bitEqu 21, FlagSE + _bitEqu 22, FlagBE + _bitEqu 23, FlagFE1 + _bitEqu 24, Flag24 + _bitEqu 25, Flag25 + _bitEqu 26, Flag26 + _bitEqu 27, FlagLowSaves + _bitEqu 28, Flag28 + _bitEqu 29, Flag29 + _bitEqu 30, Flag30 + _bitEqu 31, Flag31 diff --git a/NanoKernel/NKExceptions.s b/NanoKernel/NKExceptions.s index 28ff57e..3742f64 100644 --- a/NanoKernel/NKExceptions.s +++ b/NanoKernel/NKExceptions.s @@ -1,66 +1,17 @@ ; AUTO-GENERATED SYMBOL LIST -; IMPORTS: -; NKConsoleLog -; printw -; NKFloatInts -; IntHandleSpecialFPException -; bugger_around_with_floats -; NKIndex -; LookupID -; NKIntMisc -; IntReturnFromSIGP -; NKMPCalls -; BlockMPCall -; NKPoolAllocator -; PoolAlloc -; NKScheduler -; FlagSchEval -; Save_v0_v31 -; SchEval -; SchRdyTaskNow -; SchRestoreStartingAtR14 -; SchReturn -; SchSaveStartingAtR14 -; SchTaskUnrdy -; NKSync -; CauseNotification -; EnqueueMessage -; UnblockBlueIfCouldBePolling -; NKTasks -; ThrowTaskToDebugger -; NKTranslation -; FDP_011c -; EXPORTS: -; Exception (=> NKIntHandlers, NKIntMisc, NKThud, NKTranslation) -; ExceptionMemRetried (=> NKIntHandlers, NKTranslation) -; IntReturn (=> NKCache, NKIntHandlers, NKIntMisc, NKMPCalls, NKPowerCalls, NKPrimaryIntHandlers, NKRTASCalls, NKVMCalls) -; IntReturnToOtherBlueContext (=> NKIntMisc) -; IntReturnToSystemContext (=> NKIntHandlers) +######################################################################## - -BlockTaskToHandleException - - b BlockMPCall - - - -; ARG EC r8, nuFlags r16, ? r17, ? r19, ? r23, vecTable *r24 - - align 5 - -ExceptionMemRetried - - mfsprg r1, 0 +ExceptionAfterRetry mtsprg 3, r24 - lwz r9, EWA.Enables(r1) + lwz r9, KDP.Enables(r1) rlwinm r23, r17, (32-1), 27, 31 - rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) + rlwnm. r9, r9, r8, 0, 0 ; BGE taken if exception disabled - bcl BO_IF, EWA.kFlag15, major_0x02980_0x100 + bcl BO_IF, bitFlag15, major_0x02980_0x100 - lwz r6, EWA.PA_ContextBlock(r1) + lwz r6, KDP.PA_ContextBlock(r1) _bset r7, r16, 27 @@ -68,773 +19,458 @@ ExceptionMemRetried mtcrf 0x3f, r7 add r19, r19, r23 - ; Exception code in high byte of flags - rlwimi r7, r8, 24, 0xFF000000 + insrwi r7, r8, 8, 0 ; ec code -> high byte of flags - - ; Increment counter, easy enough - lwz r1, EWA.PA_KDP(r1) - slwi r8, r8, 2 + slwi r8, r8, 2 ; increment counter add r8, r8, r1 lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionCauseCounts(r8) addi r9, r9, 1 stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionCauseCounts(r8) - srwi r9, r7, 24 + ; Move regs from KDP to ContextBlock + lwz r8, EWA.r7(r1) + stw r8, CB.r7(r6) + lwz r8, EWA.r8(r1) + stw r8, CB.r8(r6) + lwz r8, EWA.r9(r1) + stw r8, CB.r9(r6) + lwz r8, EWA.r10(r1) + stw r8, CB.r10(r6) + lwz r8, EWA.r11(r1) + stw r8, CB.r11(r6) + lwz r8, EWA.r12(r1) + stw r8, CB.r12(r6) + lwz r8, EWA.r13(r1) + stw r8, CB.r13(r6) - ; Move regs from EWA to ContextBlock - mfsprg r1, 0 - lwz r8, 0x0000(r1) - stw r8, 0x0104(r6) - lwz r8, 0x001c(r1) - stw r8, 0x013c(r6) - lwz r8, 0x0020(r1) - stw r8, 0x0144(r6) - lwz r8, 0x0024(r1) - stw r8, 0x014c(r6) - lwz r8, 0x0028(r1) - stw r8, 0x0154(r6) - lwz r8, 0x002c(r1) - stw r8, 0x015c(r6) - lwz r8, 0x0030(r1) - stw r8, 0x0164(r6) - lwz r8, 0x0034(r1) - stw r8, 0x016c(r6) + bge RunSystemContext ; Alt Context has left exception disabled => Sys Context + ;fall through ; exception enabled => run userspace handler +######################################################################## - ; Order of preference: - ; SIGP-return exceptions obviously separate - ; MTasks (non-blue) -> UnhandledDataFault (ends up going to system page queue) - ; Exception enabled for blue task (i.e. in system context) -> field exception to task - ; Not actually a data fault -> system context (68k interrupt) - ; Data fault that blue does not wish to handle +RunExceptionHandler + stw r10, CB.ExceptionOriginAddr(r6) ; Save r10/SRR0, r12/LR, r3, r4 + stw r12, CB.ExceptionOriginLR(r6) + stw r3, CB.ExceptionOriginR3(r6) + stw r4, CB.ExceptionOriginR4(r6) - cmpwi cr1, r9, ecDataPageFault + lwz r8, KDP.Enables(r1) ; Save Enables & Flags + stw r7, CB.ExceptionOriginFlags(r6) + stw r8, CB.ExceptionOriginEnables(r6) - bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP - bc BO_IF_NOT, EWA.kFlagBlue, UnhandledDataFault - blt LetBlueHandleOwnException - bne cr1, IntReturnToSystemContext - b UnhandledDataFault - - - -LetBlueHandleOwnException - - ; How does the ContextBlock contain exception handling information? - mfsprg r1, 0 - stw r10, 0x0084(r6) - stw r12, 0x008c(r6) - stw r3, 0x0094(r6) - stw r4, 0x009c(r6) - lwz r8, EWA.Enables(r1) - stw r7, ContextBlock.SavedFlags(r6) - stw r8, ContextBlock.SavedEnables(r6) - li r8, 0 - lwz r10, ContextBlock.ExceptionHandler(r6) - stw r8, EWA.Enables(r1) ; disallow double-exceptions - lwz r1, EWA.PA_KDP(r1) - lwz r4, 0x0054(r6) - - ; Which context will we pass to the task exception handler? - lwz r3, KDP.LA_ECB(r1) - bc BO_IF, 8, @pass_system_context - lwz r3, KDP.LA_NCB(r1) - _bclr r11, r11, MSR_EEbit -@pass_system_context - - ; exception handler will return via trap in emulator code + ; Set up the Exception Handler context + li r8, 0 ; r8/Enables = 0 (handler must not throw exception) + lwz r10, CB.ExceptionHandler(r6) ; r10/SRR0 = handler addr + lwz r4, CB.ExceptionHandlerR4(r6) ; r4 = arbitrary second argument + lwz r3, KDP.LA_ECB(r1) ; r3 = ContextBlock ptr + bc BO_IF, bitFlagEmu, @sys + lwz r3, KDP.NCBCacheLA0(r1) +@sys lwz r12, KDP.LA_EmulatorKernelTrapTable + NanoKernelCallTable.ReturnFromException(r1) + ; r12/LR = address of KCallReturnFromException trap - bcl BO_IF, EWA.kFlagLowSaves, PreferRegistersFromEWASavingContextBlock + bcl BO_IF, bitFlagLowSaves, PreferRegistersFromKDPSavingContextBlock ; ??? - rlwinm r7, r7, 0, 29, 16 ; unset 17-28 - rlwimi r11, r7, 0, 20, 23 ; threfore unset MSR[FE0/SE/BE/FE1] + rlwinm r7, r7, 0, 29, 15 ; unset flags 16-28 + stw r8, KDP.Enables(r1) + rlwimi r11, r7, 0, 20, 23 ; threfore unset MSR[FE0/SE/BE/FE1] b IntReturn - +######################################################################## major_0x02980_0x100 - lwz r2, 0x0008(r1) - lwz r3, 0x000c(r1) - lwz r4, 0x0010(r1) - lwz r5, 0x0014(r1) + lwz r0, EWA.r0(r1) + lwz r2, EWA.r2(r1) + lwz r3, EWA.r3(r1) + lwz r4, EWA.r4(r1) + lwz r5, EWA.r5(r1) blr -PreferRegistersFromEWASavingContextBlock ; OUTSIDE REFERER - mfsprg r8, 0 - stw r17, 0x0064(r6) - stw r20, 0x0068(r6) - stw r21, 0x006c(r6) - stw r19, ContextBlock.SRR0(r6) - stw r18, 0x007c(r6) - lmw r14, EWA.r14(r8) +PreferRegistersFromKDPSavingContextBlock + stw r17, CB.PropagateR17(r6) + stw r20, CB.PropagateR20(r6) + stw r21, CB.PropagateR21(r6) + stw r19, CB.PropagateR19(r6) + stw r18, CB.PropagateR18(r6) + lmw r14, EWA.r14(r1) blr +######################################################################## + align kIntAlign +KCallReturnFromExceptionFastPath + lwz r11, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r1) + mr r10, r12 + addi r11, r11, 1 + stw r11, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r1) + mfsrr1 r11 + rlwimi r7, r7, 27, 26, 26 ; ?re-enable single stepping -; This is the only path to UnhandledCodeFault +KCallReturnFromException + cmplwi cr1, r3, 1 ; exception handler return value + blt cr1, @dispose + mtcrf 0x3f, r7 + beq cr1, @propagate + +;force to system context ; Handler returned >= 1 + subi r8, r3, 32 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) + cmplwi r8, 256-32 + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) + insrwi r7, r3, 8, 0 + blt RunSystemContext ; Handler returned 1-255: force that exception number to System + li r8, ecTrapInstr + b Exception ; Handler returned >= 256: fail! + +@dispose ; Handler returned 0: return to the code that threw the exception + lwz r8, CB.ExceptionOriginFlags(r6) + lwz r10, CB.ExceptionOriginAddr(r6) + rlwimi r7, r8, 0, 0xFF00FFFF ; restore most Flags to pre-exception state + lwz r8, CB.ExceptionOriginEnables(r6) + rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] <- Flags + stw r8, KDP.Enables(r1) + + andi. r8, r11, MsrFE0 + MsrFE1 ; check: are floating-pt exceptions enabled? + + lwz r12, CB.ExceptionOriginLR(r6) ; restore LR/r3/r4 + lwz r3, CB.ExceptionOriginR3(r6) + lwz r4, CB.ExceptionOriginR4(r6) + + bnel EnableFPU ; if FP exceptions are enabled, make sure the FPU is enabled + + addi r9, r6, CB.ExceptionOriginFlags ; never gets used... points to exception part of ContextBlock? + + b IntReturn + +@propagate ; Handler returned 1: propagate exception + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) + lwz r8, CB.ExceptionOriginFlags(r6) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) + lwz r10, CB.ExceptionOriginAddr(r6) + rlwimi r7, r8, 0, 0xFF00FFFF ; restore most Flags to pre-exception state + lwz r8, CB.ExceptionOriginEnables(r6) + mtcrf 0x0f, r7 + rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] <- Flags + stw r8, KDP.Enables(r1) + + lwz r12, CB.ExceptionOriginLR(r6) ; restore LR/r3/r4 + lwz r3, CB.ExceptionOriginR3(r6) + lwz r4, CB.ExceptionOriginR4(r6) + + bc BO_IF_NOT, bitFlagLowSaves, RunSystemContext + stmw r14, EWA.r14(r1) + lwz r17, CB.PropagateR17(r6) + lwz r20, CB.PropagateR20(r6) + lwz r21, CB.PropagateR21(r6) + lwz r19, CB.PropagateR19(r6) + lwz r18, CB.PropagateR18(r6) + b RunSystemContext + +######################################################################## + +; BEFORE +; PowerPC exception vector saved r1/LR in SPRG1/2 and +; jumped where directed by the vecTable pointed to by +; SPRG3. That function bl'ed here. +; +; AFTER +; Reg Contains Original saved in +; --------------------------------------------- +; r0 (itself) +; r1 KDP SPRG1 +; r2 (itself) +; r3 (itself) +; r4 (itself) +; r5 (itself) +; r6 ContextBlock EWA +; r7 Flags ContextBlock +; r8 KDP ContextBlock +; r9 (scratch CB ptr) ContextBlock +; r10 SRR0 ContextBlock +; r11 SRR1 ContextBlock +; r12 LR ContextBlock +; r13 CR ContextBlock + +LoadInterruptRegisters + mfsprg r1, 0 + stw r6, EWA.r6(r1) + mfsprg r6, 1 + stw r6, EWA.r1(r1) + lwz r6, KDP.PA_ContextBlock(r1) + stw r7, CB.r7(r6) + stw r8, CB.r8(r6) + stw r9, CB.r9(r6) + stw r10, CB.r10(r6) + stw r11, CB.r11(r6) + stw r12, CB.r12(r6) + stw r13, CB.r13(r6) + mfsrr0 r10 + mfcr r13 + lwz r7, KDP.Flags(r1) + mfsprg r12, 2 + mfsrr1 r11 + blr + +######################################################################## Exception - - mfsprg r1, 0 + lwz r9, KDP.Enables(r1) mtcrf 0x3f, r7 - lwz r9, EWA.Enables(r1) - lwz r1, EWA.PA_KDP(r1) + rlwnm. r9, r9, r8, 0, 0 ; BLT taken if exception enabled - rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) + insrwi r7, r8, 8, 0 ; Exception code to hi byte of Flags - ; Exception code in high byte of flags - rlwimi r7, r8, 24, 0xFF000000 - - ; Increment counter, easy enough - slwi r8, r8, 2 + slwi r8, r8, 2 ; Increment counter, easy enough add r8, r8, r1 lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionCauseCounts(r8) addi r9, r9, 1 stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionCauseCounts(r8) - srwi r9, r7, 24 + blt RunExceptionHandler ; exception enabled => run userspace handler + ;fall through ; Alt Context has left exception disabled => Sys Context - ; Order of preference: - ; SIGP-return exceptions obviously separate - ; MTasks (non-blue) -> UnhandledCodeFault (ends up going to backing store) - ; Exception enabled for blue task (i.e. in system context) -> field exception to task - ; Code fault for blue task but exception is disabled -> UnhandledCodeFault - ; Non-code fault for blue task -> system context (68k interrupt) +######################################################################## - bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP - bc BO_IF_NOT, EWA.kFlagBlue, UnhandledCodeFault +RunSystemContext + lwz r9, KDP.PA_ECB(r1) ; System ("Emulator") ContextBlock - cmpwi cr1, r9, ecInstPageFault - - blt LetBlueHandleOwnException - beq cr1, UnhandledCodeFault -; b IntReturnToSystemContext - - - -; THESE TWO RETURN PATHS ARE ONLY CALLED IF BLUE IS RUNNING! - -IntReturnToSystemContext - - lwz r1, EWA.PA_KDP(r1) - lwz r9, KDP.PA_ECB(r1) - - addi r8, r1, KDP.VecBaseSystem + addi r8, r1, KDP.VecBaseSystem ; System VecTable mtsprg 3, r8 - ; Exception came from emulator! Can't handle that with a 68k interrupt, can we? - bcl BO_IF, EWA.kFlagEmu, SuspendBlueTask + bcl BO_IF, bitFlagEmu, Panic ; System Context already running! + ; Fallthru (new CB in r9, old CB in r6) +######################################################################## -; Swap the blue task between the system and alternate contexts +SwitchContext ; OldCB *r6, NewCB *r9 +; Run the System or Alternate Context + lwz r8, KDP.Enables(r1) + stw r7, CB.Flags(r6) + stw r8, CB.Enables(r6) -; ARG old_context r6, new_context r9 - -IntReturnToOtherBlueContext - - mfsprg r1, 0 - - lwz r8, EWA.Enables(r1) - stw r7, ContextBlock.Flags(r6) - stw r8, ContextBlock.Enables(r6) - - bc BO_IF_NOT, EWA.kFlagLowSaves, @not_low_saves - stw r17, 0x0024(r6) - stw r20, 0x0028(r6) - stw r21, 0x002c(r6) - stw r19, 0x0034(r6) - stw r18, 0x003c(r6) - lmw r14, 0x0038(r1) + bc BO_IF_NOT, bitFlagLowSaves, @not_low_saves + stw r17, CB.LowSave17(r6) + stw r20, CB.LowSave20(r6) + stw r21, CB.LowSave21(r6) + stw r19, CB.LowSave19(r6) + stw r18, CB.LowSave18(r6) + lmw r14, EWA.r14(r1) @not_low_saves - - ; Save state to the old ContextBlock - mfxer r8 - stw r13, ContextBlock.CR(r6) - stw r8, ContextBlock.XER(r6) - stw r12, ContextBlock.LR(r6) + stw r13, CB.CR(r6) + stw r8, CB.XER(r6) + stw r12, CB.LR(r6) mfctr r8 - stw r10, ContextBlock.CodePtr(r6) - stw r8, ContextBlock.KernelCTR(r6) + stw r10, CB.CodePtr(r6) + stw r8, CB.KernelCTR(r6) - bc BO_IF_NOT, EWA.kFlagHasMQ, @no_mq - lwz r8, ContextBlock.MQ(r9) + bc BO_IF_NOT, bitFlagHasMQ, @no_mq + lwz r8, CB.MQ(r9) mfspr r12, mq mtspr mq, r8 - stw r12, ContextBlock.MQ(r6) + stw r12, CB.MQ(r6) @no_mq - lwz r8, 0x0004(r1) - stw r8, 0x010c(r6) - stw r2, 0x0114(r6) - stw r3, 0x011c(r6) - stw r4, 0x0124(r6) - lwz r8, 0x0018(r1) - stw r5, 0x012c(r6) - stw r8, 0x0134(r6) - stw r14, 0x0174(r6) - stw r15, 0x017c(r6) - stw r16, 0x0184(r6) - stw r17, 0x018c(r6) - stw r18, 0x0194(r6) - stw r19, 0x019c(r6) - stw r20, 0x01a4(r6) - stw r21, 0x01ac(r6) - stw r22, 0x01b4(r6) - stw r23, 0x01bc(r6) - stw r24, 0x01c4(r6) - stw r25, 0x01cc(r6) - stw r26, 0x01d4(r6) - _band. r8, r11, MSR_FPbit - stw r27, 0x01dc(r6) - stw r28, 0x01e4(r6) - stw r29, 0x01ec(r6) - stw r30, 0x01f4(r6) - stw r31, 0x01fc(r6) + lwz r8, EWA.r1(r1) + stw r0, CB.r0(r6) + stw r8, 0x010c(r6) + stw r2, 0x0114(r6) + stw r3, 0x011c(r6) + stw r4, 0x0124(r6) + lwz r8, 0x0018(r1) + stw r5, 0x012c(r6) + stw r8, 0x0134(r6) + _band. r8, r11, bitMsrFP + stw r14, 0x0174(r6) + stw r15, 0x017c(r6) + stw r16, 0x0184(r6) + stw r17, 0x018c(r6) + stw r18, 0x0194(r6) + stw r19, 0x019c(r6) + stw r20, 0x01a4(r6) + stw r21, 0x01ac(r6) + stw r22, 0x01b4(r6) + stw r23, 0x01bc(r6) + stw r24, 0x01c4(r6) + stw r25, 0x01cc(r6) + stw r26, 0x01d4(r6) + stw r27, 0x01dc(r6) + stw r28, 0x01e4(r6) + stw r29, 0x01ec(r6) + stw r30, 0x01f4(r6) + stw r31, 0x01fc(r6) + bnel DisableFPU - bnel bugger_around_with_floats + lwz r8, KDP.ContextClock(r1) + mfdec r31 + cmpwi r8, 0 + stw r31, KDP.ContextClock(r1) + mtdec r8 + blel ResetDEC ; to r8 - bc BO_IF_NOT, EWA.kFlagVec, @no_vec - bl Save_v0_v31 -@no_vec + lwz r8, CB.Flags(r9) ; r8 is the new Flags variable + stw r9, KDP.PA_ContextBlock(r1) + xoris r7, r7, 1 << (15 - bitFlagEmu) ; flip Emulator flag + rlwimi r11, r8, 0, 20, 23 ; "enact" MSR[FE0/SE/BE/FE1] + mr r6, r9 ; change the magic ContextBlock register + rlwimi r7, r8, 0, 0x0000FFFF ; change bottom half of flags only - stw r11, ContextBlock.MSR(r6) + andi. r8, r11, MsrFE0 + MsrFE1 ; FP exceptions enabled in new context? - - ; Load state from the new ContextBlock - - lwz r8, ContextBlock.Flags(r9) - - stw r9, EWA.PA_ContextBlock(r1) - - xoris r7, r7, 1 << (15 - EWA.kFlagEmu) ; toggle the emulator flag - - rlwimi r11, r8, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] - - mr r6, r9 - rlwimi r7, r8, 0, 17, 31 ; copy the flags that *do* differ between contexts - - andi. r8, r11, MSR_FE0 | MSR_FE1 - - lwz r8, ContextBlock.Enables(r6) - lwz r13, ContextBlock.CR(r6) - stw r8, EWA.Enables(r1) - lwz r8, ContextBlock.XER(r6) - lwz r12, ContextBlock.LR(r6) + lwz r8, CB.Enables(r6) + lwz r13, CB.CR(r6) + stw r8, KDP.Enables(r1) + lwz r8, CB.XER(r6) + lwz r12, CB.LR(r6) mtxer r8 - lwz r8, ContextBlock.KernelCTR(r6) - lwz r10, ContextBlock.CodePtr(r6) + lwz r8, CB.KernelCTR(r6) + lwz r10, CB.CodePtr(r6) mtctr r8 - bnel IntHandleSpecialFPException + bnel ReloadFPU ; FP exceptions enabled, so load FPU - lwarx r8, 0, r1 - sync - stwcx. r8, 0, r1 + stwcx. r0, 0, r1 - lwz r29, ContextBlock.VectorSaveArea(r6) - lwz r8, ContextBlock.r1(r6) - cmpwi r29, 0 + lwz r8, CB.r1(r6) + lwz r0, CB.r0(r6) stw r8, EWA.r1(r1) - lwz r28, 0x210(r29) - beq @no_vrsave - mtspr vrsave, r28 -@no_vrsave + lwz r2, 0x0114(r6) + lwz r3, 0x011c(r6) + lwz r4, 0x0124(r6) + lwz r8, 0x0134(r6) + lwz r5, 0x012c(r6) + stw r8, 0x0018(r1) + lwz r14, 0x0174(r6) + lwz r15, 0x017c(r6) + lwz r16, 0x0184(r6) + lwz r17, 0x018c(r6) + lwz r18, 0x0194(r6) + lwz r19, 0x019c(r6) + lwz r20, 0x01a4(r6) + lwz r21, 0x01ac(r6) + lwz r22, 0x01b4(r6) + lwz r23, 0x01bc(r6) + lwz r24, 0x01c4(r6) + lwz r25, 0x01cc(r6) + lwz r26, 0x01d4(r6) + lwz r27, 0x01dc(r6) + lwz r28, 0x01e4(r6) + lwz r29, 0x01ec(r6) + lwz r30, 0x01f4(r6) + lwz r31, 0x01fc(r6) - lwz r2, 0x0114(r6) - lwz r3, 0x011c(r6) - lwz r4, 0x0124(r6) - lwz r8, 0x0134(r6) - lwz r5, 0x012c(r6) - stw r8, 0x0018(r1) - lwz r14, 0x0174(r6) - lwz r15, 0x017c(r6) - lwz r16, 0x0184(r6) - lwz r17, 0x018c(r6) - lwz r18, 0x0194(r6) - lwz r19, 0x019c(r6) - lwz r20, 0x01a4(r6) - lwz r21, 0x01ac(r6) - lwz r22, 0x01b4(r6) - lwz r23, 0x01bc(r6) - lwz r24, 0x01c4(r6) - lwz r25, 0x01cc(r6) - lwz r26, 0x01d4(r6) - lwz r27, 0x01dc(r6) - lwz r28, 0x01e4(r6) - lwz r29, 0x01ec(r6) - lwz r30, 0x01f4(r6) - lwz r31, 0x01fc(r6) - - - -; Almost always goes straight through to SchReturn. Zeros a word in EWA. - -; ARG flags_to_set r7 - -IntReturn ; OUTSIDE REFERER +######################################################################## +IntReturn andi. r8, r7, (1 << (31 - 26)) | (1 << (31 - 27)) - mfsprg r1, 0 - bnel major_0x02ccc ; my counters say almost never called! - li r8, 0 - stw r7, EWA.Flags(r1) - stw r8, EWA.WeMightClear(r1) - b SchReturn + bnel @do_trace ; Keep single-step code out of hot path + + stw r7, KDP.Flags(r1) + + mtlr r12 ; restore user SPRs from kernel GPRs + mtsrr0 r10 + mtsrr1 r11 + mtcr r13 + + lwz r10, CB.r10(r6) ; restore user GPRs from ContextBlock + lwz r11, CB.r11(r6) + lwz r12, CB.r12(r6) + lwz r13, CB.r13(r6) + lwz r7, CB.r7(r6) + lwz r8, CB.r8(r6) + lwz r9, CB.r9(r6) + + lwz r6, EWA.r6(r1) ; restore last two registers from EWA + lwz r1, EWA.r1(r1) + + rfi - -; Almost never called (by above func) - -major_0x02ccc ; OUTSIDE REFERER - +@do_trace mtcrf 0x3f, r7 - bc BO_IF_NOT, EWA.kFlagLowSaves, @major_0x02ccc_0x18 - _bclr r7, r7, EWA.kFlagLowSaves + bc BO_IF_NOT, bitFlagLowSaves, @Trace_0x18 + _bclr r7, r7, bitFlagLowSaves - bc BO_IF, EWA.kFlag31, major_0x02ccc_0x30 - _bclr r7, r7, EWA.kFlag26 + bc BO_IF, bitFlag31, Trace_0x30 + _bclr r7, r7, bitFlag26 b @return -@major_0x02ccc_0x18 +@Trace_0x18 - bc BO_IF_NOT, EWA.kFlag26, @return - _bclr r7, r7, EWA.kFlag26 + bc BO_IF_NOT, bitFlag26, @return + _bclr r7, r7, bitFlag26 - stw r7, EWA.Flags(r1) + stw r7, KDP.Flags(r1) li r8, ecInstTrace b Exception -@return +@return blr -major_0x02ccc_0x30 +Trace_0x30 ; according to my counter, this point is never reached - rlwinm. r8, r7, 0, 8, 8 - beq SuspendBlueTask - stw r7, EWA.Flags(r1) - lwz r8, 0x0104(r6) - stw r8, 0x0000(r1) - stw r2, 0x0008(r1) - stw r3, 0x000c(r1) - stw r4, 0x0010(r1) - stw r5, 0x0014(r1) - lwz r8, 0x013c(r6) - stw r8, 0x001c(r1) - lwz r8, 0x0144(r6) - stw r8, 0x0020(r1) - lwz r8, 0x014c(r6) - stw r8, 0x0024(r1) - lwz r8, 0x0154(r6) - stw r8, 0x0028(r1) - lwz r8, 0x015c(r6) - stw r8, 0x002c(r1) - lwz r8, 0x0164(r6) - stw r8, 0x0030(r1) - lwz r8, 0x016c(r6) - stw r8, 0x0034(r1) - stmw r14, 0x0038(r1) - lwz r8, -0x0004(r1) - lwz r17, 0x0024(r9) - lwz r20, 0x0028(r9) - lwz r21, 0x002c(r9) - lwz r19, 0x0034(r9) - lwz r18, 0x003c(r9) - _bclr r16, r7, EWA.kFlagLowSaves - lwz r25, 0x0650(r8) - rlwinm. r22, r17, 31, 27, 31 + stw r7, KDP.Flags(r1) + stw r0, 0x0000(r1) + stw r2, 0x0008(r1) + stw r3, 0x000c(r1) + stw r4, 0x0010(r1) + stw r5, 0x0014(r1) + lwz r8, 0x013c(r6) + stw r8, 0x001c(r1) + lwz r8, 0x0144(r6) + stw r8, 0x0020(r1) + lwz r8, 0x014c(r6) + stw r8, 0x0024(r1) + lwz r8, 0x0154(r6) + stw r8, 0x0028(r1) + lwz r8, 0x015c(r6) + stw r8, 0x002c(r1) + lwz r8, 0x0164(r6) + stw r8, 0x0030(r1) + lwz r8, 0x016c(r6) + stw r8, 0x0034(r1) + stmw r14, 0x0038(r1) + lwz r17, 0x0024(r9) + lwz r20, 0x0028(r9) + lwz r21, 0x002c(r9) + lwz r19, 0x0034(r9) + lwz r18, 0x003c(r9) + _bclr r16, r7, bitFlagLowSaves + lwz r25, 0x0650(r1) + extrwi. r22, r17, 4, 27 add r19, r19, r22 - rlwimi r25, r17, 7, 25, 30 - lhz r26, 0x0d20(r25) - rlwimi r25, r19, 1, 28, 30 - stw r16, EWA.Flags(r1) - rlwimi r26, r26, 8, 8, 15 ; copy hi byte of entry to second byte of word - rlwimi r25, r17, 4, 23, 27 + rlwimi r25, r17, 7, 25, 30 + lhz r26, 0x0d20(r25) ; leaving this incorrect as a reminder! + insrwi r25, r19, 3, 28 + stw r16, KDP.Flags(r1) + rlwimi r26, r26, 8, 8, 15 ; copy hi byte of entry to second byte of word + insrwi r25, r17, 4, 24 mtcrf 0x10, r26 ; so the second nybble of the entry is copied to cr3 - lha r22, 0x0c00(r25) - addi r23, r8, KDP.VecBaseMemRetry + lha r22, 0x0c00(r25) + addi r23, r1, KDP.VecBaseMemRetry add r22, r22, r25 mfsprg r24, 3 mtlr r22 mtsprg 3, r23 mfmsr r14 - ori r15, r14, 0x10 + ori r15, r14, 0x10 mtmsr r15 - isync - rlwimi r25, r26, 2, 22, 29 ; apparently the lower byte of the entry is an FDP (code?) offset, /4! + rlwimi r25, r26, 2, 22, 29 ; apparently the lower byte of the entry is an FDP (code?) offset, /4! bnelr b FDP_011c +######################################################################## - -SuspendBlueTask - bl SchSaveStartingAtR14 ; r8 := EWA - - lwz r31, EWA.PA_CurTask(r8) - lwz r8, Task.ExceptionHandlerID(r31) - bl LookupID - cmpwi r9, Queue.kIDClass - mr r30, r8 - bnel @no_exception_handler - - lwz r28, Queue.ReservePtr(r30) - cmpwi r28, 0 - beql @no_memory_reserved_for_exception_messages - -;notify exception handler - _Lock PSA.SchLock, scratch1=r8, scratch2=r9 - - lwz r29, Task.Flags(r31) - _bset r29, r29, Task.kFlagStopped - _bset r29, r29, Task.kFlag19 - stw r29, Task.Flags(r31) - - ; pop 'notr' - lwz r17, Message.LLL + LLL.Next(r28) - stw r17, Queue.ReservePtr(r30) - - ; word1 = task ID - lwz r17, Task.ID(r31) - stw r17, Message.Word1(r28) - - ; word 2 = kMPTaskAbortedErr - li r18, kMPTaskAbortedErr - stw r18, Message.Word2(r28) - stw r18, Task.ErrToReturnIfIDie(r31) - - ; word 3 = SRR0 - stw r10, Message.Word3(r28) - - _log 'Blue task suspended. Notifying exception handler - srr1/0 ' - mr r8, r11 - bl Printw - mr r8, r10 - bl Printw - _log 'lr ' - mr r8, r12 - bl Printw - _log '^n' - - mr r31, r30 - mr r8, r28 - bl EnqueueMessage ; Message *r8, Queue *r31 - - b SchEval - -@no_exception_handler -@no_memory_reserved_for_exception_messages - mflr r16 - _log 'Blue task terminated - no exception handler registered - srr1/0 ' - mr r8, r11 - bl Printw - mr r8, r10 - bl Printw - _log 'lr ' - mr r8, r12 - bl Printw - _log '^n' - mtlr r16 - b IntPanicIsland - - - -######## ### ###### ######## ######## ### ## ## ## ######## ###### -## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## ## -######## ## ## ## #### ###### ###### ## ## ## ## ## ## ###### -## ######### ## ## ## ## ######### ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ###### ######## ## ## ## ####### ######## ## ###### - -; Blue can easily get to both of these! - -UnhandledCodeFault - - bcl BO_IF, EWA.kFlagLowSaves, IntPanicIsland - bl SchSaveStartingAtR14 - - mr r30, r10 - lwz r29, EWA.r6(r8) - lwz r31, EWA.PA_CurTask(r8) - stw r29, ContextBlock.r6(r6) - stw r30, ContextBlock.SRR0(r6) ; ContextBlock.srr0? - stw r7, 0x0040(r6) ; ContextBlock.savedFlags? - lwz r1, EWA.PA_KDP(r1) - - ; get task in r31, globals in r1 - - ; Will be released via BlockMPCall - _Lock PSA.SchLock, scratch1=r28, scratch2=r29 - - mr r8, r31 - bl SchTaskUnrdy - - lwz r16, Task.Flags(r31) - srwi r8, r7, 24 - - - ; To debugger if not actually a code fault, or Task takes all exceptions - rlwinm. r16, r16, 0, Task.kFlagTakesAllExceptions, Task.kFlagTakesAllExceptions - cmpwi cr1, r8, ecInstPageFault - bne _PageFaultToDebugger - bne cr1, _PageFaultToDebugger - - - lwz r8, Task.CodeFaultCtr(r31) - addi r8, r8, 1 - stw r8, Task.CodeFaultCtr(r31) - - b _CommonFaultPath - - - -UnhandledDataFault - - bcl BO_IF_NOT, EWA.kFlagLowSaves, IntPanicIsland - - bl PreferRegistersFromEWASavingContextBlock - - stw r10, ContextBlock.LA_EmulatorEntry(r6) - - _bclr r7, r7, EWA.kFlagLowSaves - - - bl SchSaveStartingAtR14 - - lwz r30, ContextBlock.SRR0(r6) - lwz r29, 0x0018(r8) - lwz r31, -0x0008(r8) - stw r29, 0x0134(r6) - stw r7, 0x0040(r6) - lwz r1, -0x0004(r1) - - - ; Will be released via BlockMPCall - _Lock PSA.SchLock, scratch1=r28, scratch2=r29 - - - mr r8, r31 - bl SchTaskUnrdy - - - lwz r16, Task.Flags(r31) - srwi r8, r7, 24 - - - ; To debugger if not actually a data fault, or Task takes all exceptions - rlwinm. r16, r16, 0, Task.kFlagTakesAllExceptions, Task.kFlagTakesAllExceptions - cmpwi cr1, r8, ecDataPageFault - bne _PageFaultToDebugger - bne cr1, _PageFaultToDebugger - - - lwz r8, Task.DataFaultCtr(r31) - addi r8, r8, 1 - stw r8, Task.DataFaultCtr(r31) - - - -_CommonFaultPath - - mfsprg r14, 0 - - _bclr r7, r7, EWA.kFlag26 - _bclr r7, r7, EWA.kFlag31 - - ; Panic if EWA.SpecialAreaPtr is invalid (presumably means CurrentlyFaultingArea?) - lwz r29, EWA.SpecialAreaPtr(r14) - lisori r17, Area.kSignature - lwz r16, Area.Signature(r29) - cmplw r16, r17 - bnel IntPanicIsland - - lwz r17, Area.Counter(r29) - addi r17, r17, 1 - stw r17, Area.Counter(r29) - - ; Get BackingProvider ptr in r26 (`mr` a few instructions down) - lwz r8, Area.BackingProviderID(r29) - bl LookupID - - - ; Three escape hatches: - - ; PAGE FAULT TASK VMMaxVirtualPages CODE PATH - ; -------------------------------------------------------------- - ; code blue 0 1 - ; code blue nonzero 3 - ; code non-blue 0 1 - ; code non-blue nonzero 1 - ; data blue 0 3 - ; data blue nonzero 3 - ; data non-blue 0 2 - ; data non-blue nonzero 2 - - lwz r16, KDP.VMMaxVirtualPages(r1) - cmpwi cr0, r9, ecInstPageFault - cmpwi cr1, r16, 0 - mr r26, r8 - bne cr0, @ESCAPE_HATCH_2_OR_3 - beq cr1, @force_escape_hatch_1 - bc BO_IF, EWA.kFlagBlue, @ESCAPE_HATCH_2_OR_3 -@force_escape_hatch_1 - - - -; ESCAPE HATCH 1: CODE FAULT OUTSIDE BLUE TASK -> AREA BACKING PROVIDER - -; (also handles blue code faults IFF the never-before-seen VM regime is active) - - lwz r16, Task.Flags(r31) - - ; Enqueue Task on its internal Semaphore (only to be released when Provider says) - addi r17, r31, Task.QueueMember - addi r18, r31, Task.PageFaultSema - stw r18, LLL.Freeform(r17) - InsertAsPrev r17, r18, scratch=r19 - - li r17, 1 - _bset r16, r16, Task.kFlagPageFaulted - stw r17, Task.PageFaultSema + Semaphore.Value(r31) - stw r16, Task.Flags(r31) - - ; SRR0 points to faulting instruction. Extract the faulting page. - rlwinm r30, r30, 0, 0xFFFFF000 - - ; Message = page address || Area ID || Task ID - lwz r27, Area.ID(r29) - lwz r28, Task.ID(r31) - stw r30, Message.Word1(r26) - stw r27, Message.Word2(r26) - stw r28, Message.Word3(r26) - - ; Bang - mr r30, r26 - bl CauseNotification - - ; Success? If not, fall through to using the global blue-serviced page queue - cmpwi r8, 0 - beq BlockTaskToHandleException - - - -@ESCAPE_HATCH_2_OR_3 - - mfcr r28 ; only for hatch 3 - li r8, Message.Size ; only for hatch 2 - - bc BO_IF, EWA.kFlagBlue, @ESCAPE_HATCH_3 - - - -; ESCAPE HATCH 2: DATA FAULT OUTSIDE BLUE TASK -> INTO SYSTEM PAGQ FOR BLUE TO SERVICE - - ; Instead of banging a notification, we send a (new) message to the global Page Queue - - bl PoolAlloc - mr. r26, r8 - beq @oom_for_pagq_message - - - ; Block the task in the usual way, but do *not* set Task.kFlagPageFaulted - - addi r17, r31, Task.QueueMember - addi r18, r31, Task.PageFaultSema - stw r18, LLL.Freeform(r17) - InsertAsPrev r17, r18, scratch=r19 - - li r17, 1 - stw r17, Task.PageFaultSema + Semaphore.Value(r31) - - - ; Via the Page Queue, tell the blue task what it needs to know - - lwz r27, Area.ID(r29) - lisori r8, Message.kSignature - lwz r29, Task.PageFaultSema(r31) - stw r27, Message.Word1(r26) ; arg1 = area ID - stw r29, Message.Word2(r26) ; arg2 = sempahore ID in its BlockedTasks linked list - stw r8, Message.LLL + LLL.Signature(r26) - stw r30, Message.Word3(r26) ; arg3 = page address - - mr r8, r26 - addi r31, r1, PSA.PageQueue - bl EnqueueMessage ; Message *r8, Queue *r31 - - - ; (Unconditionally) raise blue's priority to latency protection, and unblock it - - lwz r8, PSA.BlueSpinningOn(r1) ; this guarantees that blue will always be unblocked - bl UnblockBlueIfCouldBePolling - - - ; Block the faulting task (this releases the scheduler lock) - - b BlockMPCall - - - -; ESCAPE HATCH 3: PAGE FAULT IN BLUE TASK -> 68K INTERRUPT - -; All faults that occur in the blue task, except inst faults when the ?? VM regime is enabled - -@ESCAPE_HATCH_3 - - ; Let the blue task keep running! - mr r8, r31 - bl SchRdyTaskNow - - ; The other pathways release the Sch lock in BlockMPCall - _AssertAndRelease PSA.SchLock, scratch=r31 - - ; Restore CR (got clobbered by SchRdyTaskNow?) - - ; Do the LowSaves help the Emulator do an interrupt? - mtcr r28 - bc BO_IF_NOT, EWA.kFlagLowSaves, @nolo - lwz r8, 0x0064(r6) - lwz r9, 0x0068(r6) - stw r8, 0x0024(r6) - stw r9, 0x0028(r6) - lwz r8, 0x006c(r6) - lwz r9, ContextBlock.SRR0(r6) - stw r8, 0x002c(r6) - stw r9, 0x0034(r6) - lwz r8, 0x007c(r6) - stw r8, 0x003c(r6) - crclr EWA.kFlagLowSaves -@nolo - - bl SchRestoreStartingAtR14 - - ; Central to the Mac OS architecture: a 68k interrupt! - b IntReturnToSystemContext - - - -; This seems like an awfully calm way to handle a page fault. - -@oom_for_pagq_message - - li r16, Task.kNominalPriority - stb r16, Task.Priority(r31) - mr r8, r31 - bl SchRdyTaskNow - bl FlagSchEval - b BlockMPCall - - - -; For tasks that were created with kMPCreateTaskTakesAllExceptionsMask - -_PageFaultToDebugger - - b ThrowTaskToDebugger +ResetDEC ; to r8 + lis r31, 0x7FFF + mtdec r31 + mtdec r8 + blr diff --git a/NanoKernel/NKFloatingPt.s b/NanoKernel/NKFloatingPt.s index f259e47..ab30552 100644 --- a/NanoKernel/NKFloatingPt.s +++ b/NanoKernel/NKFloatingPt.s @@ -14,11 +14,11 @@ IntFPUnavail stw r11, KDP.NanoKernelInfo + NKNanoKernelInfo.FPUReloadCount(r1) mfsrr1 r11 - _bset r11, r11, MSR_FPbit + _bset r11, r11, bitMsrFP mtsrr1 r11 mfmsr r11 ; need this to access float registers - _bset r11, r11, MSR_FPbit + _bset r11, r11, bitMsrFP lwz r6, KDP.PA_ContextBlock(r1) mtmsr r11 @@ -35,18 +35,20 @@ IntFPUnavail ######################################################################## -major_0x03e18 +EnableFPU rlwinm. r8, r11, 0, 18, 18 bnelr -IntHandleSpecialFPException - lwz r8, 0xe4(r6) +ReloadFPU + lwz r8, 0xe4(r6) ; ??? rlwinm. r8, r8, 1, 0, 0 + mfmsr r8 - _bset r8, r8, MSR_FPbit + _bset r8, r8, bitMsrFP beqlr mtmsr r8 - _bset r11, r11, MSR_FPbit + + _bset r11, r11, bitMsrFP ######################################################################## @@ -92,10 +94,10 @@ LoadFloats DisableFPU mfmsr r8 - _bset r8, r8, MSR_FPbit + _bset r8, r8, bitMsrFP mtmsr r8 - _bclr r11, r11, MSR_FPbit + _bclr r11, r11, bitMsrFP stfd f0, 0x200(r6) stfd f1, 0x208(r6) diff --git a/NanoKernel/NKMacros.s b/NanoKernel/NKMacros.s index ff2119a..8999060 100644 --- a/NanoKernel/NKMacros.s +++ b/NanoKernel/NKMacros.s @@ -268,7 +268,7 @@ _bclr_lbit set 31 MACRO _FloatRangeToContextBlock &first, &last - stfd &first, ContextBlock.FloatRegisters+8*(&first)(r6) + stfd &first, CB.FloatRegisters+8*(&first)(r6) IF &first != &last _FloatRangeToContextBlock &first+1, &last @@ -280,7 +280,7 @@ _bclr_lbit set 31 MACRO _FloatRangeFromContextBlock &first, &last - lfd &first, ContextBlock.FloatRegisters+8*(&first)(r6) + lfd &first, CB.FloatRegisters+8*(&first)(r6) IF &first != &last _FloatRangeFromContextBlock &first+1, &last diff --git a/NanoKernel/NKSoftInt.s b/NanoKernel/NKSoftInt.s index 64b277d..4fe7cb0 100644 --- a/NanoKernel/NKSoftInt.s +++ b/NanoKernel/NKSoftInt.s @@ -5,7 +5,7 @@ IllegalInstruction mfmsr r9 - _bset r8, r9, MSR_DRbit + _bset r8, r9, bitMsrDR mtmsr r8 lwz r8, 0(r10) mtmsr r9 @@ -15,19 +15,19 @@ IllegalInstruction stw r3, EWA.r3(r1) stw r4, EWA.r4(r1) stw r5, EWA.r5(r1) - lwz r9, ContextBlock.r7(r6) + lwz r9, CB.r7(r6) stw r9, EWA.r7(r1) - lwz r9, ContextBlock.r8(r6) + lwz r9, CB.r8(r6) stw r9, EWA.r8(r1) - lwz r9, ContextBlock.r9(r6) + lwz r9, CB.r9(r6) stw r9, EWA.r9(r1) - lwz r9, ContextBlock.r10(r6) + lwz r9, CB.r10(r6) stw r9, EWA.r10(r1) - lwz r9, ContextBlock.r11(r6) + lwz r9, CB.r11(r6) stw r9, EWA.r11(r1) - lwz r9, ContextBlock.r12(r6) + lwz r9, CB.r12(r6) stw r9, EWA.r12(r1) - lwz r9, ContextBlock.r13(r6) + lwz r9, CB.r13(r6) stw r9, EWA.r13(r1) stmw r14, EWA.r14(r1) @@ -89,7 +89,7 @@ IllegalInstruction addi r23, r23, 1 stw r23, KDP.NanoKernelInfo + NKNanoKernelInfo.EmulatedUnimpInstCount(r1) mfmsr r14 - _bset r15, r14, MSR_DRbit + _bset r15, r14, bitMsrDR b loc_A38 ######################################################################## @@ -119,11 +119,11 @@ KCallRunAlternateContext lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) mtcrf 0x3f, r7 clrlwi r7, r7, 8 - stw r8, ContextBlock.LA_EmulatorKernelTrapTable(r9) + stw r8, CB.ExceptionHandlerRetAddr(r9) stw r9, KDP.PA_ContextBlock(r1) - b IntReturnToOtherBlueContext + b SwitchContext ; OldCB *r6, NewCB *r9 @search_cache @@ -255,7 +255,7 @@ KCallResetSystem ; Gary Davidian skeleton key: r5/D0 = MSR bits to unset, r7/D2 = MSR bits to set andc r11, r11, r5 - lwz r8, ContextBlock.r7(r6) + lwz r8, CB.r7(r6) or r11, r11, r8 b IntReturn @@ -275,18 +275,18 @@ KCallPrioritizeInterrupts mtsrr0 r10 mtsrr1 r11 mtcr r13 - lwz r10, ContextBlock.r10(r6) - lwz r11, ContextBlock.r11(r6) - lwz r12, ContextBlock.r12(r6) - lwz r13, ContextBlock.r13(r6) - lwz r7, ContextBlock.r7(r6) + lwz r10, CB.r10(r6) + lwz r11, CB.r11(r6) + lwz r12, CB.r12(r6) + lwz r13, CB.r13(r6) + lwz r7, CB.r7(r6) lwz r8, EWA.r1(r1) mfsprg r9, 3 lwz r9, VecTable.ExternalIntVector(r9) mtsprg 1, r8 mtlr r9 - lwz r8, ContextBlock.r8(r6) - lwz r9, ContextBlock.r9(r6) + lwz r8, CB.r8(r6) + lwz r9, CB.r9(r6) lwz r6, EWA.r6(r1) blrl ; (could this ever fall though to KCallSystemCrash?) @@ -300,22 +300,22 @@ KCallSystemCrash stw r4, EWA.r4(r1) stw r5, EWA.r5(r1) - lwz r8, ContextBlock.r7(r6) - lwz r9, ContextBlock.r8(r6) + lwz r8, CB.r7(r6) + lwz r9, CB.r8(r6) stw r8, EWA.r7(r1) stw r9, EWA.r8(r1) - lwz r8, ContextBlock.r9(r6) - lwz r9, ContextBlock.r10(r6) + lwz r8, CB.r9(r6) + lwz r9, CB.r10(r6) stw r8, EWA.r9(r1) stw r9, EWA.r10(r1) - lwz r8, ContextBlock.r11(r6) - lwz r9, ContextBlock.r12(r6) + lwz r8, CB.r11(r6) + lwz r9, CB.r12(r6) stw r8, EWA.r11(r1) stw r9, EWA.r12(r1) - lwz r8, ContextBlock.r13(r6) + lwz r8, CB.r13(r6) stw r8, EWA.r13(r1) stmw r14, EWA.r14(r1) @@ -334,13 +334,13 @@ IntProgram mfsprg r6, 1 stw r6, EWA.r1(r1) lwz r6, KDP.PA_ContextBlock(r1) - stw r7, ContextBlock.r7(r6) - stw r8, ContextBlock.r8(r6) - stw r9, ContextBlock.r9(r6) - stw r10, ContextBlock.r10(r6) - stw r11, ContextBlock.r11(r6) - stw r12, ContextBlock.r12(r6) - stw r13, ContextBlock.r13(r6) + stw r7, CB.r7(r6) + stw r8, CB.r8(r6) + stw r9, CB.r9(r6) + stw r10, CB.r10(r6) + stw r11, CB.r11(r6) + stw r12, CB.r12(r6) + stw r13, CB.r13(r6) ; Compare SRR0 with address of Emulator's KCall trap table lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) @@ -349,11 +349,11 @@ IntProgram xor. r8, r10, r8 lwz r7, KDP.Flags(r1) mfsprg r12, 2 - beq ReturnFromExceptionFastPath ; KCall in Emulator table => fast path - rlwimi. r7, r7, EWA.kFlagEmu, 0, 0 + beq KCallReturnFromExceptionFastPath ; KCall in Emulator table => fast path + rlwimi. r7, r7, bitFlagEmu, 0, 0 cmplwi cr7, r8, 16 * 4 - bge cr0, @fromAltContext ; Alt Context cannot make KCalls; this might be an External Int - bge cr7, @notFromEmulatorTrapTable ; from Emulator but not from its KCall table => do more checks + bge cr0, @fromAltContext ; Alt Context cannot make KCalls; this might be an External Int + bge cr7, @notFromEmulatorTrapTable ; from Emulator but not from its KCall table => do more checks ; SUCCESSFUL TRAP from emulator KCall table ; => Service call then return to link register @@ -373,14 +373,14 @@ IntProgram mtcrf 0x70, r11 bc BO_IF_NOT, 14, @notTrap - mfmsr r9 ; fetch the instruction to get the "trap number" - _bset r8, r9, MSR_DRbit + mfmsr r9 ; fetch the instruction to get the "trap number" + _bset r8, r9, bitMsrDR mtmsr r8 lwz r8, 0(r10) mtmsr r9 xoris r8, r8, 0xfff - cmplwi cr7, r8, 16 ; only traps 0-15 are allowed - slwi r8, r8, 2 ; (for "success" case below) + cmplwi cr7, r8, 16 ; only traps 0-15 are allowed + slwi r8, r8, 2 ; (for "success" case below) bge cr7, @illegalTrap ; SUCCESSFUL TRAP from outside emulator KCall table @@ -396,17 +396,17 @@ IntProgram blr ; Cannot service with a KCall => throw Exception -@fromAltContext ; external interrupt, or a (forbidden) KCall attempt +@fromAltContext ; external interrupt, or a (forbidden) KCall attempt mfsrr1 r11 mtcrf 0x70, r11 -@notTrap ; then it was some other software exception +@notTrap ; then it was some other software exception bc BO_IF, 12, IllegalInstruction bc BO_IF, 11, @floatingPointException -@illegalTrap ; because we only allow traps 0-15 +@illegalTrap ; because we only allow traps 0-15 rlwinm r8, r11, 17, 28, 29 addi r8, r8, 0x4b3 rlwnm r8, r8, r8, 28, 31 - b Exception ; CLEVER BIT HACKING described below + b Exception ; CLEVER BIT HACKING described below ; SRR1[13] SRR[14] Exception ; 0 0 ecNoException diff --git a/NanoKernel/NanoKernel.s b/NanoKernel/NanoKernel.s index aef7d95..c089940 100644 --- a/NanoKernel/NanoKernel.s +++ b/NanoKernel/NanoKernel.s @@ -50,6 +50,8 @@ FDP FDP_003C org 0xA38 loc_A38 + org 0xD18 +FDP_011C org 0xD50 loc_D50 FDP_0DA0 @@ -76,27 +78,8 @@ PagingL2PWithoutBATs org 0x1F98 PagingFlushTLB org 0x1FB8 -ExceptionMemRetried - org 0x2034 -LetBlueHandleOwnException - org 0x20C0 -ReturnFromExceptionFastPath - org 0x20D8 -KCallReturnFromException - org 0x2194 -LoadInterruptRegisters - org 0x21DC -Exception - org 0x2204 -IntReturnToSystemContext - org 0x2214 -IntReturnToOtherBlueContext - org 0x23AC -IntReturn - org 0x23F0 -major_0x02ccc - org 0x2500 + include 'NKExceptions.s' include 'NKFloatingPt.s' include 'NKSoftInt.s' include 'NKLegacyVM.s'