From f0e290f7090d6eec8135aba18845780f3d30ae81 Mon Sep 17 00:00:00 2001 From: Elliot Nunn Date: Wed, 4 Jul 2018 19:26:33 +0800 Subject: [PATCH] Split up NKInterrupts.s --- NanoKernel/InnerMakeFile | 5 +- NanoKernel/NKAddressSpaces.s | 6 +- NanoKernel/NKCache.s | 4 +- NanoKernel/NKConsoleLog.s | 2 +- NanoKernel/NKEquates.s | 25 + NanoKernel/NKExceptions.s | 840 ++++++++ NanoKernel/NKFloatInts.s | 176 ++ NanoKernel/NKIndex.s | 2 +- NanoKernel/NKInit.s | 24 +- NanoKernel/NKIntHandlers.s | 934 +++++++++ NanoKernel/NKIntMisc.s | 1141 +++++++++++ NanoKernel/NKInterrupts.s | 3075 ----------------------------- NanoKernel/NKMPCalls.s | 9 +- NanoKernel/NKPaging.s | 4 +- NanoKernel/NKPoolAllocator.s | 2 +- NanoKernel/NKPowerCalls.s | 3 +- NanoKernel/NKPrimaryIntHandlers.s | 4 +- NanoKernel/NKRTASCalls.s | 5 +- NanoKernel/NKScheduler.s | 26 +- NanoKernel/NKSleep.s | 2 +- NanoKernel/NKSync.s | 6 +- NanoKernel/NKTasks.s | 2 +- NanoKernel/NKThud.s | 6 +- NanoKernel/NKTimers.s | 2 +- NanoKernel/NKTranslation.s | 15 +- NanoKernel/NKVMCalls.s | 2 +- NanoKernel/NanoKernel.s | 12 +- 27 files changed, 3198 insertions(+), 3136 deletions(-) create mode 100644 NanoKernel/NKExceptions.s create mode 100644 NanoKernel/NKFloatInts.s create mode 100644 NanoKernel/NKIntHandlers.s create mode 100644 NanoKernel/NKIntMisc.s delete mode 100644 NanoKernel/NKInterrupts.s diff --git a/NanoKernel/InnerMakeFile b/NanoKernel/InnerMakeFile index 8d26ba0..d907430 100644 --- a/NanoKernel/InnerMakeFile +++ b/NanoKernel/InnerMakeFile @@ -7,7 +7,10 @@ NKFiles = {NKDir}NKBuiltinInit.s ¶ {NKDir}NKProcFlagsTbl.s ¶ {NKDir}NKProcInfoTbl.s ¶ - {NKDir}NKInterrupts.s ¶ + {NKDir}NKExceptions.s ¶ + {NKDir}NKIntHandlers.s ¶ + {NKDir}NKFloatInts.s ¶ + {NKDir}NKIntMisc.s ¶ {NKDir}NKPaging.s ¶ {NKDir}NKTranslation.s ¶ {NKDir}NKVMCalls.s ¶ diff --git a/NanoKernel/NKAddressSpaces.s b/NanoKernel/NKAddressSpaces.s index 15381bf..49f3f45 100644 --- a/NanoKernel/NKAddressSpaces.s +++ b/NanoKernel/NKAddressSpaces.s @@ -34,7 +34,7 @@ ; CreateArea (=> NKVMCalls) ; CreateAreasFromPageMap (=> NKInit) ; DeletePTE (=> NKVMCalls) -; FindAreaAbove (=> NKInterrupts, NKPaging, NKTasks, NKVMCalls) +; FindAreaAbove (=> NKIntHandlers, NKPaging, NKTasks, NKVMCalls) ; FreePageListPush (=> NKInit) ; GetPTEFromPLE (=> NKVMCalls) ; InitFreePageList (=> NKInit) @@ -42,9 +42,9 @@ ; MPCall_95_0x254 (=> NKPaging) ; NKCreateAddressSpaceSub (=> NKInit) ; SetPTE (=> NKVMCalls) -; SpaceGetPagePLE (=> NKInterrupts, NKPaging, NKVMCalls) +; SpaceGetPagePLE (=> NKIntHandlers, NKPaging, NKVMCalls) ; SpaceL2PIgnoringBATs (=> NKMPCalls) -; SpaceL2PUsingBATs (=> NKInterrupts, NKMPCalls) +; SpaceL2PUsingBATs (=> NKIntHandlers, NKMPCalls) diff --git a/NanoKernel/NKCache.s b/NanoKernel/NKCache.s index cf88dee..5e6c985 100644 --- a/NanoKernel/NKCache.s +++ b/NanoKernel/NKCache.s @@ -41,11 +41,11 @@ ; AUTO-GENERATED SYMBOL LIST ; IMPORTS: -; NKInterrupts +; NKExceptions ; IntReturn ; EXPORTS: ; FlushCaches (=> NKPowerCalls) -; FlushL1CacheUsingMSSCR0 (=> NKInterrupts) +; FlushL1CacheUsingMSSCR0 (=> NKIntHandlers) ; kcCacheDispatch (=> NKInit) ; DeclareMPCall 199, kcCacheDispatch ; DEBUG diff --git a/NanoKernel/NKConsoleLog.s b/NanoKernel/NKConsoleLog.s index f859ddc..e0d820d 100644 --- a/NanoKernel/NKConsoleLog.s +++ b/NanoKernel/NKConsoleLog.s @@ -11,7 +11,7 @@ ; printd (=> NKInit, NKMPCalls, NKPoolAllocator, NKTimers) ; printh (=> NKBuiltinInit, NKMPCalls, NKReplacementInit, NKScheduler, NKThud, NKTimers) ; prints (=> NKMPCalls, NKThud) -; printw (=> NKAddressSpaces, NKInit, NKInterrupts, NKMPCalls, NKPaging, NKPoolAllocator, NKReplacementInit, NKScheduler, NKThud, NKTimers, NKVMCalls) +; printw (=> NKAddressSpaces, NKExceptions, NKInit, NKIntHandlers, NKIntMisc, NKMPCalls, NKPaging, NKPoolAllocator, NKReplacementInit, NKScheduler, NKThud, NKTimers, NKVMCalls) diff --git a/NanoKernel/NKEquates.s b/NanoKernel/NKEquates.s index 22c0c02..5425ed0 100644 --- a/NanoKernel/NKEquates.s +++ b/NanoKernel/NKEquates.s @@ -67,3 +67,28 @@ kSynchClock equ 8 ; r4 = target CPU idx, kSIGP9 equ 9 ; no args? kGetProcessorTemp equ 12 ; r4 = selector (ignored on Core99), r5 = cpu ID ; my name kSIGP17 equ 17 ; r4 = target CPU idx? + + +; Exception cause equates +; System = FFFFFFFF, Alt = 7DF2F700 (ecInstPageFault and ecDataPageFault disabled), same +/- VM +ecNoException equ 0 ; Exception +ecSystemCall equ 1 ; ? +ecTrapInstr equ 2 ; Exception +ecFloatException equ 3 ; Exception +ecInvalidInstr equ 4 ; Exception +ecPrivilegedInstr equ 5 ; ? +ecMachineCheck equ 7 ; Exception +ecInstTrace equ 8 ; Exception +ecInstInvalidAddress equ 10 ; Exception +ecInstHardwareFault equ 11 ; Exception +ecInstPageFault equ 12 ; Exception +ecInstSupAccessViolation equ 14 ; Exception + +; Usually from MemRetryDSI (also IntAlignment and IntMachineCheck) +ecDataInvalidAddress equ 18 ; ExceptionMemRetried +ecDataHardwareFault equ 19 ; ExceptionMemRetried +ecDataPageFault equ 20 ; ExceptionMemRetried +ecDataWriteViolation equ 21 ; ExceptionMemRetried +ecDataSupAccessViolation equ 22 ; ExceptionMemRetried +ecDataSupWriteViolation equ 23 ; ? +ecUnknown24 equ 24 ; ExceptionMemRetried diff --git a/NanoKernel/NKExceptions.s b/NanoKernel/NKExceptions.s new file mode 100644 index 0000000..28ff57e --- /dev/null +++ b/NanoKernel/NKExceptions.s @@ -0,0 +1,840 @@ +; 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 + mtsprg 3, r24 + + lwz r9, EWA.Enables(r1) + rlwinm r23, r17, (32-1), 27, 31 + rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) + + bcl BO_IF, EWA.kFlag15, major_0x02980_0x100 + + lwz r6, EWA.PA_ContextBlock(r1) + + _bset r7, r16, 27 + + neg r23, r23 + mtcrf 0x3f, r7 + add r19, r19, r23 + + ; Exception code in high byte of flags + rlwimi r7, r8, 24, 0xFF000000 + + + ; Increment counter, easy enough + lwz r1, EWA.PA_KDP(r1) + slwi r8, r8, 2 + 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 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) + + + ; 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 + + cmpwi cr1, r9, ecDataPageFault + + 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 + lwz r12, KDP.LA_EmulatorKernelTrapTable + NanoKernelCallTable.ReturnFromException(r1) + + bcl BO_IF, EWA.kFlagLowSaves, PreferRegistersFromEWASavingContextBlock + + rlwinm r7, r7, 0, 29, 16 ; unset 17-28 + 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) + 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) + blr + + + +; This is the only path to UnhandledCodeFault + +Exception + + mfsprg r1, 0 + mtcrf 0x3f, r7 + + lwz r9, EWA.Enables(r1) + lwz r1, EWA.PA_KDP(r1) + + rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) + + ; Exception code in high byte of flags + rlwimi r7, r8, 24, 0xFF000000 + + ; Increment counter, easy enough + slwi r8, r8, 2 + 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 + + ; 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 + + 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 + mtsprg 3, r8 + + ; Exception came from emulator! Can't handle that with a 68k interrupt, can we? + bcl BO_IF, EWA.kFlagEmu, SuspendBlueTask + + + +; Swap the blue task between the system and alternate contexts + +; 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) +@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) + mfctr r8 + stw r10, ContextBlock.CodePtr(r6) + stw r8, ContextBlock.KernelCTR(r6) + + bc BO_IF_NOT, EWA.kFlagHasMQ, @no_mq + lwz r8, ContextBlock.MQ(r9) + mfspr r12, mq + mtspr mq, r8 + stw r12, ContextBlock.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) + + bnel bugger_around_with_floats + + bc BO_IF_NOT, EWA.kFlagVec, @no_vec + bl Save_v0_v31 +@no_vec + + stw r11, ContextBlock.MSR(r6) + + + ; 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) + mtxer r8 + lwz r8, ContextBlock.KernelCTR(r6) + lwz r10, ContextBlock.CodePtr(r6) + mtctr r8 + + bnel IntHandleSpecialFPException + + lwarx r8, 0, r1 + sync + stwcx. r8, 0, r1 + + lwz r29, ContextBlock.VectorSaveArea(r6) + lwz r8, ContextBlock.r1(r6) + cmpwi r29, 0 + 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) + + + +; Almost always goes straight through to SchReturn. Zeros a word in EWA. + +; ARG flags_to_set r7 + +IntReturn ; OUTSIDE REFERER + + 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 + + + +; Almost never called (by above func) + +major_0x02ccc ; OUTSIDE REFERER + + mtcrf 0x3f, r7 + + bc BO_IF_NOT, EWA.kFlagLowSaves, @major_0x02ccc_0x18 + _bclr r7, r7, EWA.kFlagLowSaves + + bc BO_IF, EWA.kFlag31, major_0x02ccc_0x30 + _bclr r7, r7, EWA.kFlag26 + + b @return +@major_0x02ccc_0x18 + + bc BO_IF_NOT, EWA.kFlag26, @return + _bclr r7, r7, EWA.kFlag26 + + stw r7, EWA.Flags(r1) + li r8, ecInstTrace + b Exception +@return + + blr + +major_0x02ccc_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 + 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 + mtcrf 0x10, r26 ; so the second nybble of the entry is copied to cr3 + lha r22, 0x0c00(r25) + addi r23, r8, KDP.VecBaseMemRetry + add r22, r22, r25 + mfsprg r24, 3 + mtlr r22 + mtsprg 3, r23 + mfmsr r14 + 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! + 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 diff --git a/NanoKernel/NKFloatInts.s b/NanoKernel/NKFloatInts.s new file mode 100644 index 0000000..bd0919d --- /dev/null +++ b/NanoKernel/NKFloatInts.s @@ -0,0 +1,176 @@ +; AUTO-GENERATED SYMBOL LIST +; IMPORTS: +; NKTranslation +; FDP_003c +; FDP_0DA0 +; EXPORTS: +; FloatLoadJumpTable (=> NKTranslation) +; FloatSaveJumpTable (=> NKTranslation) +; IntFPUnavail (=> NKInit) +; IntHandleSpecialFPException (=> NKExceptions, NKRTASCalls) +; bugger_around_with_floats (=> NKExceptions, NKRTASCalls) +; major_0x03e18 (=> NKIntHandlers) + + + +### ####### ###### # # + # # # ##### # # # # # # # ## # # ## # # + # ## # # # # # # # ## # # # # # # # # # + # # # # # ##### ###### # # # # # # # # # # # # # + # # # # # # # # # # # # ###### # # ###### # # + # # ## # # # # # # ## # # # # # # # # +### # # # # # ##### # # # # ## # # # ###### + + align kIntAlign + +IntFPUnavail ; OUTSIDE REFERER + mfsprg r1, 0 + stw r11, -0x0290(r1) + stw r6, -0x028c(r1) + lwz r6, -0x0004(r1) + lwz r11, 0x0e88(r6) + addi r11, r11, 0x01 + stw r11, 0x0e88(r6) + mfspr r11, srr1 + ori r11, r11, 0x2000 + mtspr srr1, r11 + mfmsr r11 + ori r11, r11, 0x2000 + lwz r6, -0x0014(r1) + mtmsr r11 + isync + bl LoadFloatsFromContextBlock + lwz r11, -0x0290(r1) + lwz r6, -0x028c(r1) + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + dcb.b 32, 0 + + + + +major_0x03e18 ; OUTSIDE REFERER + rlwinm. r8, r11, 0, 18, 18 + bnelr + +IntHandleSpecialFPException ; OUTSIDE REFERER + lwz r8, 0x00e4(r6) + rlwinm. r8, r8, 1, 0, 0 + mfmsr r8 + ori r8, r8, 0x2000 + beqlr + mtmsr r8 + isync + ori r11, r11, 0x2000 + +LoadFloatsFromContextBlock ; OUTSIDE REFERER + lfd f31, 0x00e0(r6) + lfd f0, 0x0200(r6) + lfd f1, 0x0208(r6) + lfd f2, 0x0210(r6) + lfd f3, 0x0218(r6) + lfd f4, 0x0220(r6) + lfd f5, 0x0228(r6) + lfd f6, 0x0230(r6) + lfd f7, 0x0238(r6) + mtfsf 0xff, f31 + lfd f8, 0x0240(r6) + lfd f9, 0x0248(r6) + lfd f10, 0x0250(r6) + lfd f11, 0x0258(r6) + lfd f12, 0x0260(r6) + lfd f13, 0x0268(r6) + lfd f14, 0x0270(r6) + lfd f15, 0x0278(r6) + lfd f16, 0x0280(r6) + lfd f17, 0x0288(r6) + lfd f18, 0x0290(r6) + lfd f19, 0x0298(r6) + lfd f20, 0x02a0(r6) + lfd f21, 0x02a8(r6) + lfd f22, 0x02b0(r6) + lfd f23, 0x02b8(r6) + lfd f24, 0x02c0(r6) + lfd f25, 0x02c8(r6) + lfd f26, 0x02d0(r6) + lfd f27, 0x02d8(r6) + lfd f28, 0x02e0(r6) + lfd f29, 0x02e8(r6) + lfd f30, 0x02f0(r6) + lfd f31, 0x02f8(r6) + blr + + + + + +bugger_around_with_floats ; OUTSIDE REFERER + mfmsr r8 + ori r8, r8, 0x2000 + mtmsr r8 + isync + _bclr r11, r11, 18 + stfd f0, 0x0200(r6) + stfd f1, 0x0208(r6) + stfd f2, 0x0210(r6) + stfd f3, 0x0218(r6) + stfd f4, 0x0220(r6) + stfd f5, 0x0228(r6) + stfd f6, 0x0230(r6) + stfd f7, 0x0238(r6) + stfd f8, 0x0240(r6) + stfd f9, 0x0248(r6) + stfd f10, 0x0250(r6) + stfd f11, 0x0258(r6) + stfd f12, 0x0260(r6) + stfd f13, 0x0268(r6) + stfd f14, 0x0270(r6) + stfd f15, 0x0278(r6) + stfd f16, 0x0280(r6) + stfd f17, 0x0288(r6) + stfd f18, 0x0290(r6) + stfd f19, 0x0298(r6) + stfd f20, 0x02a0(r6) + stfd f21, 0x02a8(r6) + stfd f22, 0x02b0(r6) + stfd f23, 0x02b8(r6) + mffs f0 + stfd f24, 0x02c0(r6) + stfd f25, 0x02c8(r6) + stfd f26, 0x02d0(r6) + stfd f27, 0x02d8(r6) + stfd f28, 0x02e0(r6) + stfd f29, 0x02e8(r6) + stfd f30, 0x02f0(r6) + stfd f31, 0x02f8(r6) + stfd f0, 0x00e0(r6) + blr + + + + +; indexed emulation code, mofo + +;two instructions per load-store register + + macro + CreateFloatJumpTable &opcode, &dest, &highest==31 + + if &highest > 0 + CreateFloatJumpTable &opcode, &dest, highest = (&highest) - 1 + endif + + &opcode (&highest), -0x2e0(r1) + b &dest + + endm + + +FloatLoadJumpTable + CreateFloatJumpTable lfd, FDP_0da0 + + +FloatSaveJumpTable + CreateFloatJumpTable stfd, FDP_003c diff --git a/NanoKernel/NKIndex.s b/NanoKernel/NKIndex.s index 82f079b..172416a 100644 --- a/NanoKernel/NKIndex.s +++ b/NanoKernel/NKIndex.s @@ -26,7 +26,7 @@ ; DeleteID (=> NKAddressSpaces, NKMPCalls, NKSync, NKTasks, NKTimers) ; GetNextIDOfClass (=> NKAddressSpaces, NKMPCalls, NKThud) ; InitIDIndex (=> NKInit) -; LookupID (=> NKAddressSpaces, NKInterrupts, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKThud, NKTimers) +; LookupID (=> NKAddressSpaces, NKExceptions, NKIntMisc, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKThud, NKTimers) ; MakeID (=> NKAddressSpaces, NKInit, NKMPCalls, NKSync, NKTasks) ;_______________________________________________________________________ diff --git a/NanoKernel/NKInit.s b/NanoKernel/NKInit.s index 95ea8c2..666cdea 100644 --- a/NanoKernel/NKInit.s +++ b/NanoKernel/NKInit.s @@ -54,31 +54,33 @@ ; printc ; printd ; printw +; NKFloatInts +; IntFPUnavail ; NKIndex ; InitIDIndex ; MakeID -; NKInterrupts -; HandlePerfMonitorInt -; IgnoreSoftwareInt +; NKIntHandlers ; IntAlignment ; IntDSI ; IntDecrementer -; IntExternalAlternate -; IntExternalSystem -; IntFPUnavail ; IntISI ; IntMachineCheck +; MemRetryDSI +; MemRetryMachineCheck +; PIHDSI +; kcReturnFromException +; NKIntMisc +; HandlePerfMonitorInt +; IgnoreSoftwareInt +; IntExternalAlternate +; IntExternalSystem ; IntPerfMonitor ; IntProgram ; IntSyscall ; IntThermalEvent ; IntTrace -; MemRetryDSI -; MemRetryMachineCheck -; PIHDSI ; kcPrioritizeInterrupts ; kcResetSystem -; kcReturnFromException ; kcRunAlternateContext ; kcThud ; major_0x046d0 @@ -130,7 +132,7 @@ ; FinishInitBuiltin (=> NKBuiltinInit) ; InitHighLevel (=> NKReplacementInit) ; InitIRP (=> NKBuiltinInit, NKReplacementInit) -; ResetBuiltinKernel (=> NKInterrupts) +; ResetBuiltinKernel (=> NKIntMisc) diff --git a/NanoKernel/NKIntHandlers.s b/NanoKernel/NKIntHandlers.s new file mode 100644 index 0000000..04e0eb5 --- /dev/null +++ b/NanoKernel/NKIntHandlers.s @@ -0,0 +1,934 @@ +; AUTO-GENERATED SYMBOL LIST +; IMPORTS: +; NKAddressSpaces +; FindAreaAbove +; SpaceGetPagePLE +; SpaceL2PUsingBATs +; NKCache +; FlushL1CacheUsingMSSCR0 +; NKConsoleLog +; printw +; NKExceptions +; Exception +; ExceptionMemRetried +; IntReturn +; IntReturnToSystemContext +; NKFloatInts +; major_0x03e18 +; NKIntMisc +; IntReturnFromSIGP +; NKPaging +; PagingFunc1 +; PagingL2PWithBATs +; NKScheduler +; SchFiddlePriorityShifty +; SchRestoreStartingAtR14 +; SchSaveStartingAtR14 +; NKTimers +; TimerDispatch +; NKTranslation +; FDP_0DA0 +; EXPORTS: +; IntAlignment (=> NKInit) +; IntDSI (=> NKInit) +; IntDecrementer (=> NKInit) +; IntISI (=> NKInit) +; IntMachineCheck (=> NKInit) +; LoadInterruptRegisters (=> NKIntMisc, NKTranslation) +; MaskedInterruptTaken (=> NKIntMisc) +; MemRetryDSI (=> NKInit) +; MemRetryMachineCheck (=> NKInit) +; PIHDSI (=> NKInit) +; kcReturnFromException (=> NKInit) +; major_0x03324 (=> NKTranslation) +; major_0x03548 (=> NKTranslation) +; save_all_registers (=> NKIntMisc) + + + + align kIntAlign + +IntDecrementer ; OUTSIDE REFERER + + bl LoadInterruptRegisters + + lwz r8, KDP.OldKDP(r1) + rlwinm. r9, r11, 0, 16, 16 + cmpwi cr1, r8, 0x00 + beq MaskedInterruptTaken + beq cr1, IntDecrementer_0x54 + + stw r16, ContextBlock.r16(r6) + stw r17, ContextBlock.r17(r6) + stw r18, ContextBlock.r18(r6) + stw r25, ContextBlock.r25(r6) + + bl SchFiddlePriorityShifty + ble IntDecrementer_0x48 + + lwz r8, PSA.CriticalReadyQ + ReadyQueue.Timecake + 4(r1) + mtspr dec, r8 + + lwz r16, ContextBlock.r16(r6) + lwz r17, ContextBlock.r17(r6) + lwz r18, ContextBlock.r18(r6) + b IntReturn + +IntDecrementer_0x48 + lwz r16, 0x0184(r6) + lwz r17, 0x018c(r6) + lwz r18, 0x0194(r6) + +IntDecrementer_0x54 +; r6 = ewa + bl SchSaveStartingAtR14 +; r8 = sprg0 (not used by me) + + + _Lock PSA.SchLock, scratch1=r8, scratch2=r9 + + lwz r8, 0x0e8c(r1) + addi r8, r8, 0x01 + stw r8, 0x0e8c(r1) + bl TimerDispatch + _AssertAndRelease PSA.SchLock, scratch=r8 + + bl SchRestoreStartingAtR14 + b IntReturn + + + +### ###### ##### ### + # # # ##### # # # # # + # ## # # # # # # + # # # # # # # ##### # + # # # # # # # # # + # # ## # # # # # # +### # # # ###### ##### ### + +; Kick it to the FDP-associated MemRetryDSI + + align kIntAlign + +IntDSI + + mfsprg r1, 0 + stmw r2, EWA.r2(r1) + mfsprg r11, 1 + + stw r0, EWA.r0(r1) + stw r11, EWA.r1(r1) ; Why? + + li r0, 0 + + mfspr r10, srr0 + mfspr r11, srr1 + mfsprg r12, 2 + mfcr r13 + mfsprg r24, 3 + + lwz r16, EWA.Flags(r1) + lwz r1, EWA.PA_KDP(r1) + + mfspr r26, dsisr + + ; Activate the Translation vecTable, and test DSISR bit 5 + ; ("Set if the access is due to a lwarx, ldarx, stwcx., or stdcx. + ; instruction that addresses memory that is Write Through + ; Required or Caching Inhibited; otherwise cleared") + addi r23, r1, KDP.VecBaseMemRetry + andis. r28, r26, 0x400 ; test bit 5 (see cmt above) + mtsprg 3, r23 + + mfmsr r14 + bne HandleDSIDueToIllegalSyncPrimitive + + _bset r15, r14, 27 ; temp set MSR[DR] + mtmsr r15 + isync + + lwz r27, 0(r10) ; get instruction (should be fine!) + + mtmsr r14 ; restore MSR + isync + + + +major_0x03324 ; OUTSIDE REFERER + rlwinm. r18, r27, 18, 25, 29 + lwz r25, 0x0650(r1) + li r21, 0x00 + mfsprg r1, 0 + beq major_0x03324_0x18 + lwzx r18, r1, r18 + +major_0x03324_0x18 + andis. r26, r27, 0xec00 + lwz r16, EWA.Flags(r1) + rlwinm r17, r27, 0, 6, 15 + rlwimi r16, r16, 27, 26, 26 + bge major_0x03324_0x58 + rlwimi r25, r27, 7, 26, 29 + rlwimi r25, r27, 12, 25, 25 + lwz r26, 0x0b80(r25) + extsh r23, r27 + rlwimi r25, r26, 26, 22, 29 + mtlr r25 + mtcr r26 + add r18, r18, r23 + crclr cr5_so + rlwimi r17, r26, 6, 26, 5 + blr + +major_0x03324_0x58 + rlwimi r25, r27, 27, 26, 29 + rlwimi r25, r27, 0, 25, 25 + rlwimi r25, r27, 6, 23, 24 + rlwimi r25, r27, 4, 22, 22 + lwz r26, 0x0800(r25) + rlwinm r23, r27, 23, 25, 29 + rlwimi r25, r26, 26, 22, 29 + mtlr r25 + mtcr r26 + lwzx r23, r1, r23 + crclr cr5_so + rlwimi r17, r26, 6, 26, 5 + add r18, r18, r23 + bclr BO_IF_NOT, 13 + neg r23, r23 + add r18, r18, r23 + blr + + + +HandleDSIDueToIllegalSyncPrimitive ; OUTSIDE REFERER + + ori r15, r14, 0x10 + mr r28, r16 + mfspr r18, dar + mfspr r19, dsisr + mtmsr r15 + isync + lwz r27, 0x0000(r10) + mtmsr r14 + isync + mtsprg 3, r24 + lwz r1, -0x0004(r1) + mr r31, r19 + mr r8, r18 + li r9, 0x00 + bl SpaceL2PUsingBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17 + mr r16, r28 + crset cr3_so + mfsprg r1, 0 + beq major_0x03324_0x12c + mr r18, r8 + rlwinm r28, r27, 13, 25, 29 + andis. r9, r31, 0x200 + rlwimi r18, r17, 0, 0, 19 + beq major_0x03324_0x118 + lwzx r31, r1, r28 + stwcx. r31, 0, r18 + sync + dcbf 0, r18 + mfcr r31 + rlwimi r13, r31, 0, 0, 3 + b FDP_0da0 + +major_0x03324_0x118 + lwarx r31, 0, r18 + sync + dcbf 0, r18 + stwx r31, r1, r28 + b FDP_0da0 + +major_0x03324_0x12c + subi r10, r10, 4 + b FDP_0da0 + + + +; This int handler is our best foothold into the FDP! + + align kIntAlign + +IntAlignment ; OUTSIDE REFERER + mfsprg r1, 0 + stmw r2, 0x0008(r1) + mfsprg r11, 1 + stw r0, 0x0000(r1) + stw r11, 0x0004(r1) + li r0, 0x00 + + lwz r11, EWA.PA_CurTask(r1) + lwz r16, EWA.Flags(r1) + lwz r21, Task.Flags(r11) + lwz r1, -0x0004(r1) ; wha??? + + lwz r11, KDP.NanoKernelInfo + NKNanoKernelInfo.MisalignmentCount(r1) + addi r11, r11, 1 + stw r11, KDP.NanoKernelInfo + NKNanoKernelInfo.MisalignmentCount(r1) + + mfspr r10, srr0 + mfspr r11, srr1 + mfsprg r12, 2 + mfcr r13 + mfsprg r24, 3 + mfspr r27, dsisr + mfspr r18, dar + + rlwinm. r21, r21, 0, Task.kFlagTakesAllExceptions, Task.kFlagTakesAllExceptions + + addi r23, r1, KDP.VecBaseMemRetry + + bne major_0x03548_0x20 + + ; DSISR for misaligned X-form instruction: + + ; (0) 0 (14)||(15) 29:30 (16)||(17) 25 (17)||(18) 21:24 (21)||(22) rD (26)||(27) rA? (31) + + ; DSISR for misaligned D-form instruction: + + ; (0) zero (16)||(17) 5 (17)||(18) 1:4 (21)||(22) rD (26)||(27) rA? (31) + +FDP_TableBase equ 0xa00 + + ; Virtual PC might put the thing in MSR_LE mode + rlwinm. r21, r11, 0, MSR_LEbit, MSR_LEbit ; msr bits in srr1 + + ; Get the FDP and F.O. if we were in MSR_LE mode + lwz r25, KDP.PA_FDP(r1) + bne major_0x03548_0x20 + + + rlwinm. r21, r27, 17, 30, 31 ; evaluate hi two bits of XO (or 0 for d-form?) + + rlwinm r17, r27, 16, 6, 15 ; save src and dest register indices in r17 + + mfsprg r1, 0 + + rlwimi r25, r27, 24, 23, 29 ; add constant fields from dsisr (*4) to FDP + + + rlwimi r16, r16, 27, 26, 26 ; AllCpuFeatures: copy bit 21 to bit 26 + + bne @regidx + + ; D-form (immediate-indexed) instruction + lwz r26, FDP_TableBase + 4*(0x40 + 0x20)(r25) ; use upper quarter of table + mfmsr r14 + rlwimi r25, r26, 26, 22, 29 ; third byte of lookup value is a /4 code offset in FDP + mtlr r25 ; so get ready to go there + ori r15, r14, 0x10 + mtcr r26 + rlwimi r17, r26, 6, 26, 5 ; wrap some shite around the register values + crclr cr5_so + blr + +@regidx + ; X-form (register-indexed) instruction + lwz r26, FDP_TableBase(r25) + mfmsr r14 + mtsprg 3, r23 + rlwimi r25, r26, 26, 22, 29 + mtlr r25 + ori r15, r14, 0x10 + mtcr r26 + rlwimi r17, r26, 6, 26, 5 + crclr 23 ; unset bit 23 = cr5_so + bclr BO_IF_NOT, 12 ; jump now if bit 12 is off + + ; if bit 12 was on, turn on paging and fetch the offending insn + ; and also activate the Translation vector table + mtmsr r15 + isync + lwz r27, 0x0000(r10) + mtmsr r14 + isync + mtsprg 3, r24 + blr + + + +major_0x03548 ; OUTSIDE REFERER + sync + mtmsr r14 + isync + mflr r23 + icbi 0, r23 + sync + isync + blr + +major_0x03548_0x20 ; OUTSIDE REFERER + li r8, 0x00 + lis r17, -0x100 + mtcr r8 + mr r19, r18 + rlwimi r17, r27, 7, 31, 31 + xori r17, r17, 0x01 + li r8, ecUnknown24 + b ExceptionMemRetried + + + + align kIntAlign + +MemRetryDSI ; OUTSIDE REFERER + + mfsprg r1, 0 + mfspr r31, dsisr + mfspr r27, dar + andis. r28, r31, 0xc030 + lwz r1, -0x0004(r1) + bne MemRetryDSI_0x1c8 + mfspr r30, srr1 + andi. r28, r30, 0x4000 + mfsprg r30, 0 + beq MemRetryDSI_0x100 + stw r8, -0x00e0(r30) + stw r9, -0x00dc(r30) + mfcr r8 + stw r16, -0x00d8(r30) + stw r17, -0x00d4(r30) + stw r18, -0x00d0(r30) + stw r19, -0x00cc(r30) + stw r8, -0x00c8(r30) + lwz r8, -0x001c(r30) + mr r9, r27 + bl FindAreaAbove + lwz r16, 0x0024(r8) + lwz r17, 0x0028(r8) + cmplw r27, r16 + cmplw cr7, r27, r17 + blt MemRetryDSI_0xe0 + bgt cr7, MemRetryDSI_0xe0 + mr r31, r8 + mr r8, r27 + bl SpaceGetPagePLE ; LogicalPage *r8, Area *r31 // PLE *r30, notfound cr0.eq + beq MemRetryDSI_0xe0 + lwz r8, 0x0000(r30) + lwz r16, 0x0098(r31) + rlwinm r28, r8, 0, 29, 30 + cmpwi cr7, r28, 0x04 + cmpwi r28, 0x02 + beq cr7, MemRetryDSI_0xe0 + beq MemRetryDSI_0xe0 + +MemRetryDSI_0x98 + addi r17, r31, 0x90 + cmpw r16, r17 + addi r17, r16, 0x14 + beq MemRetryDSI_0x158 + lwz r9, 0x0010(r16) + add r9, r9, r17 + +MemRetryDSI_0xb0 + lwz r18, 0x0000(r17) + cmplw cr7, r17, r9 + lwz r19, 0x0004(r17) + bgt cr7, MemRetryDSI_0xd8 + cmplw r27, r18 + cmplw cr7, r27, r19 + blt MemRetryDSI_0xd0 + ble cr7, MemRetryDSI_0xe0 + +MemRetryDSI_0xd0 + addi r17, r17, 0x08 + b MemRetryDSI_0xb0 + +MemRetryDSI_0xd8 + lwz r16, 0x0008(r16) + b MemRetryDSI_0x98 + +MemRetryDSI_0xe0 + mfsprg r30, 0 + mfspr r31, dsisr + lwz r8, -0x00e0(r30) + lwz r9, -0x00dc(r30) + lwz r16, -0x00d8(r30) + lwz r17, -0x00d4(r30) + lwz r18, -0x00d0(r30) + lwz r19, -0x00cc(r30) + +MemRetryDSI_0x100 + andis. r28, r31, 0x800 + addi r29, r1, KDP.BATs + 0xa0 + bnel PagingL2PWithBATs + li r28, 0x43 + and r28, r31, r28 + cmpwi cr7, r28, 0x43 + beql IntPanicIsland + mfsprg r28, 2 + mtlr r28 + bne cr7, MemRetryDSI_0x144 + mfspr r28, srr0 + addi r28, r28, 0x04 + lwz r26, 0x0e90(r1) + mtspr srr0, r28 + addi r26, r26, 0x01 + stw r26, 0x0e90(r1) + b MemRetryDSI_0x19c + +MemRetryDSI_0x144 + andi. r28, r31, 0x03 + li r8, ecDataSupAccessViolation + beq ExceptionMemRetried + li r8, ecDataWriteViolation + b ExceptionMemRetried + +MemRetryDSI_0x158 + mfsprg r30, 0 + lwz r16, 0x0f00(r1) + lwz r8, -0x00c8(r30) + addi r16, r16, 0x01 + mtcr r8 + lwz r9, -0x00dc(r30) + stw r16, 0x0f00(r1) + lwz r16, -0x00d8(r30) + lwz r17, -0x00d4(r30) + lwz r18, -0x00d0(r30) + lwz r19, -0x00cc(r30) + lwz r8, -0x00e0(r30) + mfspr r29, srr1 + mfsprg r28, 2 + _bclr r29, r29, 17 + mtlr r28 + mtspr srr1, r29 + +MemRetryDSI_0x19c + mfsprg r1, 1 + rlwinm r26, r25, 30, 24, 31 + rfi + dcb.b 32, 0 + + +MemRetryDSI_0x1c8 + andis. r28, r31, 0x8010 + bne MemRetryMachineCheck_0x14c + + _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 + + bl PagingFunc1 + _AssertAndRelease PSA.HTABLock, scratch=r28 + mfsprg r28, 2 + mtlr r28 + beq MemRetryDSI_0x19c + li r8, ecDataInvalidAddress + bge ExceptionMemRetried + li r8, ecDataPageFault + b ExceptionMemRetried + + + +MemRetryMachineCheck ; OUTSIDE REFERER + mfsprg r1, 0 + mr r28, r8 + + lwz r27, EWA.CPUBase + CPU.ID(r1) + _log 'CPU ' + mr r8, r27 + bl Printw + + _log 'MemRetry machine check - last EA ' + lwz r1, EWA.PA_KDP(r1) + lwz r27, 0x0694(r1) + mr r8, r27 + bl Printw + + _log ' SRR1 ' + mfspr r8, srr1 + mr r8, r8 + bl Printw + + _log ' SRR0 ' + mfspr r8, srr0 + mr r8, r8 + bl Printw + _log '^n' + + mr r8, r28 + lwz r1, EWA.PA_KDP(r1) + lwz r27, 0x0694(r1) + subf r28, r19, r27 + cmpwi r28, -0x10 + blt MemRetryMachineCheck_0x14c + cmpwi r28, 0x10 + bgt MemRetryMachineCheck_0x14c + + _Lock PSA.HTABLock, scratch1=r28, scratch2=r29 + + lwz r28, 0x0e98(r1) + addi r28, r28, 0x01 + stw r28, 0x0e98(r1) + lwz r29, 0x0698(r1) + li r28, 0x00 + stw r28, 0x0000(r29) + mfspr r28, pvr + rlwinm. r28, r28, 0, 0, 14 + sync + tlbie r27 + beq MemRetryMachineCheck_0x124 + sync + tlbsync + +MemRetryMachineCheck_0x124 + sync + isync + _AssertAndRelease PSA.HTABLock, scratch=r28 + + + +MemRetryMachineCheck_0x14c ; OUTSIDE REFERER + cmplw r10, r19 + li r8, ecDataHardwareFault + bne ExceptionMemRetried + mfsprg r1, 0 + mtsprg 3, r24 + lmw r14, 0x0038(r1) + li r8, ecInstHardwareFault + b Exception + + + + align kIntAlign + +IntISI ; OUTSIDE REFERER + + bl LoadInterruptRegisters + + andis. r8, r11, 0x4020 + beq major_0x039dc_0x14 + mfsprg r8, 0 + stmw r14, 0x0038(r8) + + _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 + + mr r27, r10 + bl PagingFunc1 + _AssertAndRelease PSA.HTABLock, scratch=r28 + mfsprg r8, 0 + bne major_0x039dc + + + ; MemRetry + + mfsprg r24, 3 + mfmsr r14 + ori r15, r14, 0x10 + addi r23, r1, KDP.VecBaseMemRetry + mtsprg 3, r23 + mr r19, r10 + mtmsr r15 + isync + lbz r23, 0x0000(r19) + sync + mtmsr r14 + isync + mfsprg r8, 0 + mtsprg 3, r24 + lmw r14, 0x0038(r8) + b IntReturn + + + +major_0x039dc ; OUTSIDE REFERER + lmw r14, 0x0038(r8) + li r8, ecInstPageFault + blt Exception + li r8, ecInstInvalidAddress + b Exception + +major_0x039dc_0x14 ; OUTSIDE REFERER + andis. r8, r11, 0x800 + li r8, ecInstSupAccessViolation + bne Exception + li r8, ecInstHardwareFault + b Exception + + + +IntMachineCheck ; OUTSIDE REFERER + + bl LoadInterruptRegisters + + lwz r9, EWA.CPUBase + CPU.ID(r8) + _log 'CPU ' + mr r8, r9 + bl Printw + + _log 'Machine check at ' ; srr1/srr0 + mr r8, r11 + bl Printw + mr r8, r10 + bl Printw + + _log '- last unmapped EA ' + lwz r8, 0x0694(r1) + mr r8, r8 + bl Printw + _log '^n' + + rlwinm. r8, r11, 0, 2, 2 + beq @not_L1_data_cache_error + +;L1 data cache error + bl FlushL1CacheUsingMSSCR0 + b IntReturn + +@not_L1_data_cache_error + li r8, ecMachineCheck + b Exception + + + +MaskedInterruptTaken ; OUTSIDE REFERER + _log '*** CPU MALFUNCTION - Masked interrupt punched through. SRR1/0 ' + mr r8, r11 + bl Printw + mr r8, r10 + bl Printw + _log '^n' + lis r10, -0x4523 + ori r10, r10, 0xcb00 + li r8, ecMachineCheck + b Exception + + + + align kIntAlign + +PIHDSI ; OUTSIDE REFERER + mfspr r8, dsisr + rlwimi r11, r8, 0, 0, 9 + andis. r8, r11, 0x4020 + beq major_0x039dc_0x14 + mfsprg r8, 0 + stmw r14, 0x0038(r8) + lwz r1, -0x0004(r8) + + _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 + + mfspr r27, dar + bl PagingFunc1 + _AssertAndRelease PSA.HTABLock, scratch=r28 + mfsprg r8, 0 + bne major_0x039dc + lmw r14, 0x0038(r8) + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + dcb.b 32, 0 + + + + ###### ####### ####### +# # #### # # ###### ##### # # ##### # # # ##### #### # # # # # #### ###### ##### ##### # #### # # +# # # # # # # # # # # # ## # # # # # # ## ## # # # # # # # # # # # # ## # +#### # ###### ##### # # # # # # # # ##### # # # # # ## # ##### ## # ##### # # # # # # # # # +# # # # # # # # # ##### # # # # ##### # # # # # ## # # ##### # # # # # # # +# # # # # # # # # # # # # ## # # # # # # # # # # # # # # # # # # # ## +# # #### # # ###### # #### # # # # # # # #### # # ####### # # #### ###### # # # #### # # + + align kIntAlign + +; dead code? + + 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 + +kcReturnFromException ; OUTSIDE REFERER + + _bset r11, r11, MSR_EEbit + + mtcrf 0x3f, r7 + cmplwi cr1, r3, 1 ; exception handler return value + bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP + + blt cr1, major_0x03be0_0x58 + beq cr1, major_0x03be0_0x90 + + + subi r8, r3, 32 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) + cmplwi r8, 224 + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) + mfsprg r1, 0 + rlwimi r7, r3, 24, 0, 7 + blt major_0x03be0_0xe8 + li r8, ecTrapInstr + b Exception + +major_0x03be0_0x58 + mfsprg r1, 0 + lwz r8, 0x0040(r6) + lwz r10, 0x0084(r6) + rlwimi r7, r8, 0, 17, 7 + lwz r8, 0x0044(r6) + rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] + stw r8, EWA.Enables(r1) + andi. r8, r11, 0x900 + lwz r12, 0x008c(r6) + lwz r3, 0x0094(r6) + lwz r4, 0x009c(r6) + bnel major_0x03e18 + addi r9, r6, 0x40 + b IntReturn + +major_0x03be0_0x90 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) + lwz r8, 0x0040(r6) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) + mfsprg r1, 0 + lwz r10, 0x0084(r6) + rlwimi r7, r8, 0, 17, 7 + lwz r8, 0x0044(r6) + mtcrf 0x0f, r7 + rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] + stw r8, EWA.Enables(r1) + lwz r12, 0x008c(r6) + lwz r3, 0x0094(r6) + lwz r4, 0x009c(r6) + bne cr2, major_0x03be0_0xe8 + bns cr6, major_0x03be0_0xe8 + stmw r14, 0x0038(r1) + lwz r17, 0x0064(r6) + lwz r20, 0x0068(r6) + lwz r21, 0x006c(r6) + lwz r19, ContextBlock.SRR0(r6) + lwz r18, 0x007c(r6) + +major_0x03be0_0xe8 + beq cr2, IntReturnToSystemContext + crclr cr6_so + mfspr r10, srr0 + li r8, ecTrapInstr + b Exception + + + + align 5 + +save_all_registers ; OUTSIDE REFERER + mfsprg r1, 0 + stw r6, 0x0018(r1) + mfsprg r6, 1 + stw r6, 0x0004(r1) + lwz r6, -0x0014(r1) + stw r0, 0x0104(r6) + stw r7, 0x013c(r6) + stw r8, 0x0144(r6) + stw r9, 0x014c(r6) + stw r10, 0x0154(r6) + stw r11, 0x015c(r6) + stw r12, 0x0164(r6) + stw r13, 0x016c(r6) + li r0, 0x00 + mfspr r10, srr0 + mfspr r11, srr1 + mfcr r13 + mfsprg r12, 2 + lwz r7, EWA.Flags(r1) + lwz r1, -0x0004(r1) + +; r6 = ewa + b SchSaveStartingAtR14 +; r8 = sprg0 (not used by me) + + + +# ### ###### +# #### ## ##### # # # ##### ###### ##### ##### # # ##### ##### # # ###### #### # #### ##### ###### ##### #### +# # # # # # # # ## # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # ##### # # # # # # # # # ###### ##### # # #### # ##### # # #### +# # # ###### # # # # # # # # ##### ##### # # ##### # # # # # ### # # # # ##### # +# # # # # # # # # ## # # # # # # # # # # # # # # # # # # # # # # # # +####### #### # # ##### ### # # # ###### # # # # #### # # # # ###### #### # #### # ###### # # #### + +; How we arrive here: +; +; 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. +; +; +; When we arrive here: +; +; r1 is saved in SPRG1 (r1 itself is junk) +; LR is saved in SPRG2 (LR itself contains return addr) +; +; +; Before we return: +; +; Reg Contains Original saved in +; --------------------------------------------- +; r0 0 ContextBlock +; r1 KDP EWA +; r2 (itself) +; r3 (itself) +; r4 (itself) +; r5 (itself) +; r6 ContextBlock EWA +; r7 Flags ContextBlock +; r8 EWA ContextBlock +; r9 (itself) ContextBlock +; r10 SRR0 ContextBlock +; r11 SRR1 ContextBlock +; r12 LR ContextBlock +; r13 CR ContextBlock +; +; +; Can be followed up by a call to SchSaveStartingAtR14, +; (which will put them in the ContextBlock too). + + align 5 + +LoadInterruptRegisters + + ; Get EWA pointer in r1 (phew) + mfsprg r1, 0 + + ; Save r6 in EWA + stw r6, EWA.r6(r1) + + ; Save pre-interrupt r1 (which SPRG1 held) to EWA + mfsprg r6, 1 + stw r6, EWA.r1(r1) + + ; Get ContextBlock pointer in r6 (phew) + lwz r6, EWA.PA_ContextBlock(r1) + + ; Save r0, r7-r13 in ContextBlock + stw r0, ContextBlock.r0(r6) + 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) + + ; Zero r0 (convenient) + li r0, 0 + + ; Make some useful special registers conveniently available + mfspr r10, srr0 + mfspr r11, srr1 + mfcr r13 + mfsprg r12, 2 + + ; Point r8 to EWA + mr r8, r1 + + ; Features in r7, KDP in r8 + lwz r7, EWA.Flags(r1) + lwz r1, EWA.PA_KDP(r1) + + blr diff --git a/NanoKernel/NKIntMisc.s b/NanoKernel/NKIntMisc.s new file mode 100644 index 0000000..0be995a --- /dev/null +++ b/NanoKernel/NKIntMisc.s @@ -0,0 +1,1141 @@ +; AUTO-GENERATED SYMBOL LIST +; IMPORTS: +; NKConsoleLog +; printw +; NKExceptions +; Exception +; IntReturn +; IntReturnToOtherBlueContext +; NKIndex +; LookupID +; NKInit +; ResetBuiltinKernel +; NKIntHandlers +; LoadInterruptRegisters +; MaskedInterruptTaken +; save_all_registers +; NKMPCalls +; kcMPDispatch +; NKPaging +; PagingL2PWithBATs +; NKScheduler +; Restore_v0_v31 +; SchExitInterrupt +; SchRestoreStartingAtR14 +; SchSaveStartingAtR14 +; SchSwitchSpace +; NKSync +; CauseNotification +; NKTranslation +; FDPEmulateInstruction +; EXPORTS: +; HandlePerfMonitorInt (=> NKInit) +; IgnoreSoftwareInt (=> NKInit, NKTranslation) +; IntExternalAlternate (=> NKInit) +; IntExternalSystem (=> NKInit) +; IntPerfMonitor (=> NKInit) +; IntProgram (=> NKInit) +; IntReturnFromSIGP (=> NKExceptions, NKIntHandlers) +; IntSyscall (=> NKInit) +; IntThermalEvent (=> NKInit) +; IntTrace (=> NKInit) +; SIGP (=> NKMPCalls, NKScheduler, NKSleep) +; kcPrioritizeInterrupts (=> NKInit) +; kcResetSystem (=> NKInit) +; kcRunAlternateContext (=> NKInit) +; kcThud (=> NKInit) +; major_0x046d0 (=> NKInit) +; major_0x04a20 (=> NKInit) +; wordfill (=> NKInit, NKPowerCalls) + + + +major_0x04180 ; OUTSIDE REFERER + stw r6, -0x0290(r1) + stw r10, -0x028c(r1) + stw r11, -0x0288(r1) + lwz r6, -0x0014(r1) + lwz r10, 0x00d8(r6) + mfspr r11, srr1 + cmpwi r10, 0x00 + beql major_0x04180_0x9c + oris r11, r11, 0x200 + stw r9, -0x027c(r1) + mtspr srr1, r11 + mfmsr r11 + oris r11, r11, 0x200 + mtmsr r11 + isync + bl Restore_v0_v31 + lwz r8, -0x0004(r1) + lwz r11, 0x0ed4(r8) + addi r11, r11, 0x01 + stw r11, 0x0ed4(r8) + mtcr r13 + lwz r6, -0x0290(r1) + lwz r10, -0x028c(r1) + lwz r11, -0x0288(r1) + lwz r13, -0x0284(r1) + lwz r8, -0x0280(r1) + lwz r9, -0x027c(r1) + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + dcb.b 32, 0 + + +major_0x04180_0x9c + mtcr r13 + lwz r6, -0x0290(r1) + lwz r10, -0x028c(r1) + lwz r11, -0x0288(r1) + lwz r13, -0x0284(r1) + + + bl LoadInterruptRegisters + + li r8, ecInvalidInstr + b Exception + + + +### ###### # # + # # # ##### # # ###### ##### ###### ## ## #### # # # ##### #### ##### + # ## # # # # # # # # # # # # # # ## # # # # # # # + # # # # # ###### ##### # # ##### # # # # # # # # # # # # # # + # # # # # # # ##### # # # # # # # # # # # # ##### + # # ## # # # # # # # # # # # ## # # # # # # +### # # # # ###### # # # # # #### # # # # #### # # + + align kIntAlign + +IntPerfMonitor ; OUTSIDE REFERER + mtlr r1 + mfsprg r1, 0 + stw r8, -0x0280(r1) + stw r13, -0x0284(r1) + mflr r8 + mfcr r13 + cmpwi r8, 0xf20 + beq major_0x04180 + mtcr r13 + lwz r13, -0x0284(r1) + lwz r8, -0x0280(r1) + bl save_all_registers + mr r28, r8 + rlwinm. r9, r11, 0, 16, 16 + beq MaskedInterruptTaken + + _Lock PSA.SchLock, scratch1=r8, scratch2=r9 + + lwz r8, PSA.PMFHandlerID(r1) + +; r8 = id + bl LookupID + cmpwi r9, Notification.kIDClass + + mr r30, r8 + bne IntPerfMonitor_0x88 + lwz r16, -0x0340(r28) + lwz r17, -0x0008(r28) + stw r16, 0x0010(r30) + lwz r16, 0x0000(r17) + stw r16, 0x0014(r30) + mfspr r16, 955 + stw r16, 0x0018(r30) + bl CauseNotification + +IntPerfMonitor_0x88 + _AssertAndRelease PSA.SchLock, scratch=r8 + +; r6 = ewa + bl SchRestoreStartingAtR14 + b IntReturn + + + +; Notify the Thermal Handler + + align kIntAlign + +IntThermalEvent ; OUTSIDE REFERER + bl save_all_registers + mr r28, r8 + rlwinm. r9, r11, 0, 16, 16 + beq MaskedInterruptTaken + _log 'Thermal event^n' + + _Lock PSA.SchLock, scratch1=r8, scratch2=r9 + + lwz r8, PSA.ThermalHandlerID(r1) + bl LookupID + cmpwi r9, Notification.kIDClass + mr r30, r8 + bne @no_thermal_handler + + lwz r16, EWA.CPUBase + CPU.ID(r28) + stw r16, Notification.MsgWord1(r30) + bl CauseNotification +@no_thermal_handler + + _AssertAndRelease PSA.SchLock, scratch=r8 + bl SchRestoreStartingAtR14 + b IntReturn + + + + ###### # ##### +# # #### # # # # # # # # # ##### ###### ##### # # ## ##### ###### # # #### # # ##### ###### # # ##### +# # # # # # # # ## # # # # # # # # ## # # # # # # # # ## # # # # # # +#### # ###### # # # # # # # # # ##### # # # # # # # # ##### # # # # # # # ##### ## # +# # # # # # # # # # ####### # # # ##### # # # ###### # # # # # # # # # # ## # +# # # # # # # # # ## # # # # # # # # ## # # # # # # # # # ## # # # # # +# # #### # # #### # # # # ###### # ###### # # # # # # # ###### ##### #### # # # ###### # # # + +; We can assume that this is being called from the emulator + +; We accept a logical NCB ptr but the kernel needs a physical one. +; So we keep a four-entry cache in KDP, mapping logical NCB ptrs +; to physical ones. But when are there multiple alt contexts? + +; ARG flags? r3, mask r4 + + align kIntAlign + +kcRunAlternateContext + + mtcrf 0x3f, r7 + + bcl BO_IF_NOT, EWA.kFlagBlue, IntReturn + + and. r8, r4, r13 + lwz r9, KDP.NCBCacheLA0(r1) + rlwinm r8, r3, 0, 0, 25 + cmpw cr1, r8, r9 + bne IntReturn + lwz r9, KDP.NCBCachePA0(r1) + bne cr1, @search_cache + + +@found_physical_in_cache ; can come here from below after a more thorough search + + addi r8, r1, KDP.VecBaseAlternate ; the only use of this vector table? + mtsprg 3, r8 + + lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) + mtcrf 0x3f, r7 + mfsprg r1, 0 + clrlwi r7, r7, 8 + stw r8, ContextBlock.LA_EmulatorKernelTrapTable(r9) + + stw r9, EWA.PA_ContextBlock(r1) + + b IntReturnToOtherBlueContext + + +@search_cache + + lwz r9, KDP.NCBCacheLA1(r1) + cmpw cr1, r8, r9 + beq cr1, @found_in_slot_1 + + lwz r9, KDP.NCBCacheLA2(r1) + cmpw cr1, r8, r9 + beq cr1, @found_in_slot_2 + + lwz r9, KDP.NCBCacheLA3(r1) + cmpw cr1, r8, r9 + beq cr1, @found_in_slot_3 + + + ; No luck with the cache + + mfsprg r1, 0 + stmw r14, EWA.r14(r1) + lwz r1, EWA.PA_KDP(r1) + + cmpw cr1, r8, r6 + beq cr1, @fail + + mr r27, r8 + addi r29, r1, KDP.BATs + 0xa0 + bl PagingL2PWithBATs + clrlwi r23, r8, 20 + beq @fail + + cmplwi r23, 0x0d00 + mr r9, r8 + mr r8, r31 + ble @not_straddling_pages + + addi r27, r27, 0x1000 + addi r29, r1, KDP.BATs + 0xa0 + bl PagingL2PWithBATs + beq @fail + + subi r31, r31, 0x1000 + xor r23, r8, r31 + rlwinm. r23, r23, 0, 25, 22 + bne @fail ; because physical pages are discontiguous +@not_straddling_pages + + clrlwi r23, r31, 30 + cmpwi r23, 3 + rlwimi r8, r9, 0, 20, 31 + beq @fail + + + ; Found a non-cached physical address for this NCB! + + lwz r23, KDP.NanoKernelInfo + NKNanoKernelInfo.NCBPtrCacheMissCount(r1) + addi r23, r23, 1 + stw r23, KDP.NanoKernelInfo + NKNanoKernelInfo.NCBPtrCacheMissCount(r1) + + + ; Stick it in cache slot 3 + + mfsprg r1, 0 + lmw r14, EWA.r14(r1) + lwz r1, EWA.PA_KDP(r1) + stw r8, KDP.NCBCachePA3(r1) + + +@found_in_slot_3 ; so promote to slot 2 + + lwz r8, KDP.NCBCacheLA2(r1) + stw r9, KDP.NCBCacheLA2(r1) + stw r8, KDP.NCBCacheLA3(r1) + + lwz r9, KDP.NCBCachePA3(r1) + lwz r8, KDP.NCBCachePA2(r1) + stw r9, KDP.NCBCachePA2(r1) + stw r8, KDP.NCBCachePA3(r1) + + lwz r9, KDP.NCBCacheLA2(r1) + + +@found_in_slot_2 ; so promote to slot 1 + + lwz r8, KDP.NCBCacheLA1(r1) + stw r9, KDP.NCBCacheLA1(r1) + stw r8, KDP.NCBCacheLA2(r1) + + lwz r9, KDP.NCBCachePA2(r1) + lwz r8, KDP.NCBCachePA1(r1) + stw r9, KDP.NCBCachePA1(r1) + stw r8, KDP.NCBCachePA2(r1) + + lwz r9, KDP.NCBCacheLA1(r1) + + +@found_in_slot_1 ; so promote to slot 0, save elsewhere, and push on + + lwz r8, KDP.NCBCacheLA0(r1) + stw r9, KDP.NCBCacheLA0(r1) + stw r9, KDP.LA_NCB(r1) + stw r8, KDP.NCBCacheLA1(r1) + + lwz r9, KDP.NCBCachePA1(r1) + lwz r8, KDP.NCBCachePA0(r1) + stw r9, KDP.NCBCachePA0(r1) + stw r8, KDP.NCBCachePA1(r1) + + b @found_physical_in_cache + + +@fail + + mfsprg r1, 0 + lmw r14, EWA.r14(r1) + lwz r1, EWA.PA_KDP(r1) + li r8, ecTrapInstr + b Exception + + + +; > r8 = dest +; > r22 = len in bytes +; > r23 = fillword + +wordfill ; OUTSIDE REFERER + subic. r22, r22, 4 + stwx r23, r8, r22 + bne wordfill + blr + + + + ###### ##### +# # #### # # ###### #### ###### ##### # # # # #### ##### ###### # # +# # # # # # # # # # # # # # # # ## ## +#### # ###### ##### #### ##### # ##### # #### # ##### # ## # +# # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # +# # #### # # ###### #### ###### # ##### # #### # ###### # # + +; Handle a 68k reset trap. + +; If A0(r3)/A1(r4) == 'Gary'/$05051955, load the register list in A3? Or is this now disabled? + +; New SRR0 = SRR0 & ~r5(D0) | r7(D2) + + align kIntAlign + +kcResetSystem ; OUTSIDE REFERER +; r6 = ewa + bl SchSaveStartingAtR14 +; r8 = sprg0 (not used by me) + + ; Check for 601 (rtc vs timebase) + mfpvr r9 + rlwinm. r9, r9, 0, 0, 14 + + ; This xoris/cmplwi technique is very cool + xoris r8, r3, 'Ga' + + beq @is_601 + mftb r9 + b @endif_601 +@is_601 + dialect POWER + mfrtcl r9 + dialect PowerPC +@endif_601 + + ; Not sure why this would need to hit cr0? + andis. r9, r9, 0xffff + + cmplwi r8, 'ry' + bne NonGaryReset + + ; r4 (i.e. A1) == 5 May 1956? + xoris r8, r4, 0x0505 + cmplwi r8, 0x1956 + bne NonGaryReset + + andc r11, r11, r5 + lwz r8, ContextBlock.r7(r6) + or r11, r11, r8 + + _log 'Skeleton key inserted at' + + mr r8, r11 + bl Printw + + mr r8, r10 + bl Printw + + _log '^n' + + b IntReturn + + + +; NonGaryReset + +; A 68k reset trap without Gary Davidian's magic numbers. + +NonGaryReset + + _log 'ResetSystem trap entered^n' + + lwz r8, KDP.OldKDP(r1) + + cmpwi r8, 0 + beq ResetBuiltinKernel + + _log 'Unplugging the replacement nanokernel^n' + + lwz r8, KDP.OldKDP(r1) + mfsprg r1, 0 + addi r9, r8, KDP.VecBaseSystem + mtsprg 0, r8 ; old NK has only one EWA! + mtsprg 3, r9 + + lwz r9, EWA.r1(r1) + stw r9, EWA.r1(r8) + + lwz r9, EWA.r6(r1) + stw r9, EWA.r6(r8) + + stw r6, 0x065c(r8) + stw r7, 0x0660(r8) ; ?????????? + + lwz r9, EWA.Enables(r1) + stw r9, 0x0664(r8) + +; r6 = ewa + bl SchRestoreStartingAtR14 + subi r10, r10, 4 + lwz r1, -0x0004(r1) + +; sprg0 = for r1 and r6 +; r1 = kdp +; r6 = register restore area +; r7 = flag to insert into XER +; r10 = new srr0 (return location) +; r11 = new srr1 +; r12 = lr restore +; r13 = cr restore + b SchExitInterrupt + + + + ###### ### +# # #### # # ##### # #### ##### # ##### # ###### ###### # # # ##### ###### ##### ##### # # ##### ##### #### +# # # # # # # # # # # # # # # # # # # ## # # # # # # # # # # # # # +#### # ###### # # # # # # # # # # # ##### # # # # # ##### # # # # # # # # # #### +# # # # ##### # # # ##### # # # # # # # # # # # ##### ##### # # ##### # # +# # # # # # # # # # # # # # # # # # # ## # # # # # # # # # # # # +# # #### # # # # #### # # # # # ###### ###### ### # # # ###### # # # # #### # # #### + +; > r1 = kdp + +kcPrioritizeInterrupts ; OUTSIDE REFERER + lwz r9, KDP.PA_InterruptHandler(r1) + mtlr r9 + blr + + + +; Move registers from CB to EWA, and Thud. + + align kIntAlign + +kcThud + + stw r2, EWA.r2(r1) + stw r3, EWA.r3(r1) + stw r4, EWA.r4(r1) + stw r5, EWA.r5(r1) + + lwz r8, ContextBlock.r7(r6) + lwz r9, ContextBlock.r8(r6) + stw r8, EWA.r7(r1) + stw r9, EWA.r8(r1) + + lwz r8, ContextBlock.r9(r6) + lwz r9, ContextBlock.r10(r6) + stw r8, EWA.r9(r1) + stw r9, EWA.r10(r1) + + lwz r8, ContextBlock.r11(r6) + lwz r9, ContextBlock.r12(r6) + stw r8, EWA.r11(r1) + stw r9, EWA.r12(r1) + + lwz r8, ContextBlock.r13(r6) + stw r8, EWA.r13(r1) + + stmw r14, EWA.r14(r1) + + bl IntPanicIsland + + + +major_0x046d0 ; OUTSIDE REFERER + + bl LoadInterruptRegisters + + li r8, ecTrapInstr + b Exception + + + +### ####### # + # # # ##### # # # ##### ###### ##### # # ## # # # # ##### ###### ##### # # ## ##### ###### + # ## # # # # # # # # # ## # # # # # # # # # # # ## # # # # # + # # # # # ##### ## # ##### # # # # # # # # # # # # ##### # # # # # # # # ##### + # # # # # # ## # # ##### # # # ###### # ####### # # # ##### # # # ###### # # + # # ## # # # # # # # # # ## # # # # # # # # # # # ## # # # # +### # # # ####### # # # ###### # # # # # # ###### # # ###### # ###### # # # # # # # ###### + +; For when the alternate context is running? + + align kIntAlign + +IntExternalAlternate + + bl LoadInterruptRegisters + mtcrf 0x3f, r7 + bcl BO_IF_NOT, EWA.kFlagBlue, IntPanicIsland + li r8, ecNoException + b Exception + + + +### ###### + # # # ##### # # ##### #### #### ##### ## # # + # ## # # # # # # # # # # # # # # ## ## + # # # # # ###### # # # # # # # # # # ## # + # # # # # # ##### # # # ### ##### ###### # # + # # ## # # # # # # # # # # # # # # +### # # # # # # #### #### # # # # # # + + align kIntAlign + +IntProgram + + bl LoadInterruptRegisters + + lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) + mtcr r11 ; UNUSUAL to have SRR1 in condition register + xor r8, r10, r8 + bc BO_IF_NOT, 14, @not_trap + + + ; Program interrupt caused by a trap instruction + + + ; From the table of twis in the emulator code image? Then return will be to LR. + + cmplwi cr0, r8, NanoKernelCallTable.ReturnFromException + cmplwi cr1, r8, NanoKernelCallTable.MPDispatch + beq cr0, @emutrap_0_return_from_exception + beq cr1, @emutrap_8_mpdispatch + cmplwi cr0, r8, NanoKernelCallTable.VMDispatch + cmplwi cr1, r8, NanoKernelCallTable.Size + beq cr0, @emutrap_3_vmdispatch + blt cr1, @emutrap_other + + + ; Not from the emulator image? Return will be to next instruction, + ; and we will read the trap instruction from memory + + ; If !MSR[IR], turn on MSR[DR] for just a moment + bc BO_IF_NOT, 26, @_IntProgram_0x58 + stw r14, ContextBlock.r14(r6) + mfsprg r14, 3 + addi r8, r1, PSA.VecBasePIH + mfmsr r9 + mtsprg 3, r8 + _bset r8, r9, 27 ; turn on data paging (MSR[DR]) for just a sec + mtmsr r8 + isync +@_IntProgram_0x58 + + ; Get the offending instruction! + lwz r8, 0(r10) + + ; If !MSR[IR], restore MSR + bc BO_IF_NOT, 26, @_IntProgram_0x74 + isync + mtmsr r9 + isync + mtsprg 3, r14 + lwz r14, ContextBlock.r14(r6) +@_IntProgram_0x74 + + + ; Switch from SRR1-in-CR to Flags-in-CR + + mtcr r7 + + + ; Read the bottom half of the non-emu-image trap instruction, getting trapnum*8 in r8 + xoris r8, r8, 0xfff + cmplwi cr0, r8, NanoKernelCallTable.Size / 4 + cmplwi cr1, r8, NanoKernelCallTable.ReturnFromException / 4 + bge cr0, @trap_too_high + cmplwi cr7, r8, NanoKernelCallTable.MPDispatch / 4 + cmplwi cr0, r8, NanoKernelCallTable.VMDispatch / 4 + slwi r8, r8, 2 + beq cr1, @nonemu_return_from_exception + beq cr7, @nonemu_mpdispatch + beq cr0, @nonemu_vmdispatch + + ; Fall through to some hard truths + bc BO_IF, 16, @_IntProgram_0x150 + bc BO_IF, 8, @_IntProgram_0xac + bc BO_IF_NOT, 9, @_IntProgram_0x150 + +@nonemu_return_from_exception +@nonemu_vmdispatch +@_IntProgram_0xac + add r8, r8, r1 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + +@nonemu_go + lwz r8, KDP.NanoKernelCallTable(r8) + mtlr r8 + addi r10, r10, 4 + rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 + blr + +@nonemu_mpdispatch + lwz r9, ContextBlock.r0(r6) + add r8, r8, r1 + cmpwi r9, -1 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + bne @nonemu_go + + ; Non-emu MPDispatch trap with r0 == -1: muck around a bit? + addi r10, r10, 4 + rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 + mfsprg r8, 0 + rlwimi r13, r7, 8, 2, 2 + lwz r9, EWA.PA_CurTask(r8) + xoris r13, r13, 0x2000 + lwz r8, Task.SomeLabelField(r9) + stw r8, ContextBlock.r0(r6) + b IntReturn + + +@emutrap_other +@_IntProgram_0x110 + mtcr r7 + bc BO_IF, 16, @_IntProgram_0x150 + bc BO_IF, 8, @_IntProgram_0x120 + bc BO_IF_NOT, 9, @_IntProgram_0x150 + +@emutrap_0_return_from_exception +@emutrap_8_mpdispatch +@emutrap_3_vmdispatch +@_IntProgram_0x120 + add r8, r8, r1 + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + lwz r10, KDP.NanoKernelCallTable(r8) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) + mtlr r10 + mr r10, r12 ; return to whatever the emulator left in the PPC link register + rlwimi r7, r7, 27, 26, 26 + blr + + + ; Program interrupt not caused by a trap instruction: consult SRR1 bits 11-13 + +@not_trap + bc BO_IF+1, 12, FDPEmulateInstruction ; illegal instruction exception + bc BO_IF, 13, FDPEmulateInstruction ; privileged instruction exception + bc BO_IF, 11, @floating_point_exception ; floating point exception + +@trap_too_high +@_IntProgram_0x150 + rlwinm r8, r11, 17, 28, 29 ; whoa + addi r8, r8, 0x4b3 + rlwnm r8, r8, r8, 28, 31 + b Exception + +@floating_point_exception + li r8, ecFloatException + + bc BO_IF, 15, Exception ; if SRR0 points to subsequent instr + addi r10, r10, 4 ; if SRR0 points to offending instr + rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 + b Exception + + + + align kIntAlign + +IntExternalSystem + + bl LoadInterruptRegisters + + + ; Sanity check + + rlwinm. r9, r11, 0, MSR_EEbit, MSR_EEbit + beq MaskedInterruptTaken + + + ; How many CPUs? + + lwz r9, EWA.CPUBase + CPU.LLL + LLL.Freeform(r8) + lwz r9, CoherenceGroup.CpuCount(r9) + cmpwi r9, 2 + + + ; Uniprocessor machine: go straight to PIH + + blt kcPrioritizeInterrupts + + + ; Check with the CPU plugin whether this is an interprocessor interrupt + ; (i.e. an alert to flag a scheduler evaluation) + + bl SchSaveStartingAtR14 + + li r9, kSIGP9 + stw r9, EWA.SIGPSelector(r8) + li r8, 1 ; args are in EWA + bl SIGP + bl SchRestoreStartingAtR14 + + cmpwi cr0, r8, -29278 ; real external interrupt + cmpwi cr1, r8, -29277 ; ignore + cmpwi cr2, r8, -29279 ; interprocessor interrupt! + ; else: real external interrupt + + beq cr0, kcPrioritizeInterrupts + beq cr1, IntReturn + bne cr2, kcPrioritizeInterrupts + + mfsprg r9, 0 ; "alert" => run scheduler evaluation + li r8, 1 + stb r8, EWA.SchEvalFlag(r9) + b IntReturn ; goes to SchReturn + + + + ##### ### ##### ###### +# # # # # # # +# # # # # + ##### # # #### ###### + # # # # # +# # # # # # + ##### ### ##### # + +; "SIGnal Plugin": Call the CPU plugin PEF bundle synchronously. +; (blue address space but in supervisor mode without interrupts) + +; ARG: + +; if r8 == 0, i.e. userspace MPCpuPlugin call: +; r3 => routine selector +; executing CPU index => r3 +; r4-10 => r4-10 + +; if r8 != 0, i.e. internal NanoKernel call: +; EWA.SIGPSelector => routine selector +; executing CPU index => r3 +; PlugCallR4-10 => r4-10 + +; For most NK SIGPs, r4 contains the index of the CPU being operated on + + align 5 + +SIGP + + mfsprg r23, 0 + mtcr r7 + + ; r20 = offset into CPU plugin dispatch table = routine number * 4 + ; + lwz r16, EWA.PA_CurAddressSpace(r23) + slwi r20, r3, 2 + stw r16, EWA.SIGPSpacOnResume(r23) + bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP ; not sure about this + cmpwi cr2, r8, 0 + lwz r18, EWA.SIGPSelector(r23) + beq cr2, @args_in_registers + slwi r20, r18, 2 +@args_in_registers + + ; Check that a CPU plugin is installed and that the + ; plugin dispatch table includes this command number. + lwz r22, EWA.CPUBase + CPU.LLL + LLL.Freeform(r23) + li r8, -0x7266 + lwz r17, CoherenceGroup.PA_CpuPluginDesc(r22) + lwz r16, CoherenceGroup.CpuPluginSelectorCount(r22) + mr. r17, r17 + beqlr + slwi r16, r16, 2 + li r8, -0x7267 + cmplw r20, r16 + bgelr + + ; Save some registers in advance of this unusual "upcall". + stw r10, EWA.SIGPSavedR10(r23) + stw r11, EWA.SIGPSavedR11(r23) + stw r12, EWA.SIGPSavedR12(r23) + stw r13, EWA.SIGPSavedR13(r23) + mfxer r16 + mfctr r17 + stw r16, EWA.SIGPSavedXER(r23) + mflr r16 + stw r17, EWA.SIGPSavedCTR(r23) + stw r16, EWA.SIGPSavedLR(r23) ; obviously this is getting revisited somewhere + stw r6, EWA.SIGPSavedR6(r23) + stw r7, EWA.SIGPSavedR7(r23) + + ; Change to the CPU plugin's preferred address space. + lwz r9, EWA.PA_CurAddressSpace(r23) + lwz r8, CoherenceGroup.CpuPluginSpacePtr(r22) + cmpw r9, r8 + beq @noNeedToSwitchSpace + bl SchSwitchSpace +@noNeedToSwitchSpace + + ; Save user registers to ContextBlock (odd way to do this). + lwz r16, EWA.r1(r23) + lwz r17, EWA.r6(r23) + stw r16, ContextBlock.r1(r6) + stw r2, ContextBlock.r2(r6) + stw r3, ContextBlock.r3(r6) + stw r4, ContextBlock.r4(r6) + stw r5, ContextBlock.r5(r6) + stw r17, ContextBlock.r6(r6) + + ; Return address for CPU plugin code (=> twi 31, r31, 0 => kcReturnFromException) + lwz r17, KDP.LA_EmulatorKernelTrapTable + NanoKernelCallTable.ReturnFromException(r1) + + ; Need CPU index to look up the CPU plugin stack pointer in a table + lhz r16, EWA.CPUIndex(r23) + + ; MSR for CPU plugin with EE (external ints) and PR (problem state) switched off + lwz r19, PSA.UserModeMSR(r1) + slwi r16, r16, 2 + rlwinm r19, r19, 0, 18, 15 + + ; SRR0 (=> program counter) = TOC[routine_idx][first long] + ; r1 (stack ptr) = stackPtrs[cpu_idx] + ; r2 (RTOC) = TOC[routine_idx][second long] + lwz r8, CoherenceGroup.PA_CpuPluginTOC(r22) + lwz r9, CoherenceGroup.PA_CpuPluginStackPtrs(r22) + lwzx r20, r8, r20 + lwz r18, 0(r20) + mtlr r17 + mtspr srr0, r18 + mtspr srr1, r19 + lwzx r1, r9, r16 + lwz r2, 4(r20) + + ; r3 (first arg) = CPU index + srwi r3, r16, 2 + + ; Flags |= 0x8000 + _bset r7, r7, EWA.kFlagSIGP + mr r16, r6 + stw r7, EWA.Flags(r23) + + ; Not sure where this ContextBlock comes from? + addi r6, r23, -0x318 + stw r6, EWA.PA_ContextBlock(r23) + + beq cr2, @args_in_registers_2 + +;args not in registers + lwz r4, EWA.SIGPCallR4(r23) + lwz r5, EWA.SIGPCallR5(r23) + lwz r6, EWA.SIGPCallR6(r23) + lwz r7, EWA.SIGPCallR7(r23) + lwz r8, EWA.SIGPCallR8(r23) + lwz r9, EWA.SIGPCallR9(r23) + lwz r10, EWA.SIGPCallR10(r23) + + ; Go. + rfi + +@args_in_registers_2 + lwz r6, ContextBlock.r6(r16) + lwz r7, ContextBlock.r7(r16) + lwz r8, ContextBlock.r8(r16) + lwz r9, ContextBlock.r9(r16) + lwz r10, ContextBlock.r10(r16) + + ; Go. + rfi + + + +major_0x04a20 + + mfsprg r23, 0 + lwz r6, -0x0014(r23) + lwz r7, -0x0010(r23) + lwz r1, -0x0004(r23) + mfspr r10, srr0 + mfspr r11, srr1 + + + +IntReturnFromSIGP + + mfsprg r23, 0 + lwz r7, EWA.SIGPSavedR7(r23) + andis. r8, r11, 0x0002 ; MSR bit 14?? + stw r7, -0x0010(r23) + bne @msr_14_set + li r3, -29285 +@msr_14_set + + ; Restore address space + lwz r8, EWA.SIGPSpacOnResume(r23) + lwz r9, EWA.PA_CurAddressSpace(r23) + cmpw r9, r8 + beq @no_switch_space + bl SchSwitchSpace +@no_switch_space + + lwz r10, EWA.SIGPSavedR10(r23) + lwz r11, EWA.SIGPSavedR11(r23) + lwz r12, EWA.SIGPSavedR12(r23) + lwz r13, EWA.SIGPSavedR13(r23) + lwz r8, EWA.SIGPSavedXER(r23) + lwz r9, EWA.SIGPSavedCTR(r23) + mtxer r8 + lwz r8, EWA.SIGPSavedLR(r23) + lwz r6, EWA.SIGPSavedR6(r23) + mtctr r9 + stw r6, EWA.PA_ContextBlock(r23) + mtlr r8 + mr r8, r3 + mr r9, r4 + lwz r16, ContextBlock.r1(r6) + lwz r2, ContextBlock.r2(r6) + lwz r3, ContextBlock.r3(r6) + lwz r4, ContextBlock.r4(r6) + lwz r5, ContextBlock.r5(r6) + lwz r17, ContextBlock.r6(r6) + stw r16, EWA.r1(r23) + stw r17, EWA.r6(r23) + + blr + + + +### ##### + # # # ##### # # # # #### #### ## # # + # ## # # # # # # # # # # # # + # # # # # ##### # #### # # # # # + # # # # # # # # # ###### # # + # # ## # # # # # # # # # # # # +### # # # ##### # #### #### # # ###### ###### + +; IntSyscall + +; Not fully sure about this one + +IntSyscall ; OUTSIDE REFERER + + ; Only r1 and LR have been saved, so these compares clobber cr0 + + cmpwi r0, -3 + bne @not_minus_3 + + ; sc -3: used by FDP to go back to supervisor mode after instruction emulation. + ; For security reasons, FDP goes into user mode when it emulates loads and stores. + ; This is how it goes back into supervisor mode afterwards. During instruction emulation + ; it has data paging on, but keeps instruction paging off. User Mode code never has instruction + ; paging disabled, so this is not a privilege escalation. + + ; unset MSR_PR bit + mfspr r1, srr1 + rlwinm. r0, r1, 26, 26, 27 ;move MSR_IR bit to sign bit (and a few others that don't matter) + _bclr r1, r1, 17 + blt @not_in_FDP ; only do if MSR_IR = 0 (MSR_IR is sign bit, so it is < 0 if it is true) + mtspr srr1, r1 + @not_in_FDP + + ; restore LR from SPRG2, r1 from SPRG1 + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + + rfi + +@not_minus_3 + cmpwi r0, -1 + mfsprg r1, 0 + bne @not_minus_1 + + ; sc -1: quick-test whether "this task" is blue (cr0.eq if not blue) + + lwz r0, EWA.Flags(r1) + mfsprg r1, 2 + rlwinm. r0, r0, 0, EWA.kFlagBlue, EWA.kFlagBlue + mtlr r1 + mfsprg r1, 1 + rfi + +@not_minus_1 + cmpwi r0, -2 + bne @not_any_special + + ; sc -2: more flag nonsense? + + lwz r0, EWA.Flags(r1) + lwz r1, -0x0008(r1) + rlwinm. r0, r0, 0, 10, 10 + lwz r0, 0x00ec(r1) + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + +@not_any_special + + ; Positive numbered syscalls are a fast path to MPDispatch (twi 31, r31, 8) + + bl LoadInterruptRegisters ; Save the usual suspects and get comfy + + lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts + 32(r1) + addi r9, r9, 1 + stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts + 8*4(r1) + + ; Not sure what to make of these + _bset r11, r11, 14 + rlwimi r7, r7, 27, 26, 26 + + b kcMPDispatch + + + +### ####### + # # # ##### # ##### ## #### ###### + # ## # # # # # # # # # # + # # # # # # # # # # # ##### + # # # # # # ##### ###### # # + # # ## # # # # # # # # # +### # # # # # # # # #### ###### + + align kIntAlign + +IntTrace ; OUTSIDE REFERER + + bl LoadInterruptRegisters + + li r8, ecInstTrace + b Exception + + + +### ##### ### + # #### # # #### ##### ###### # # #### ###### ##### # # ## ##### ###### # # # ##### + # # # ## # # # # # # # # # # # # # # # # # # # ## # # + # # # # # # # # # ##### ##### # # ##### # # # # # # # ##### # # # # # + # # ### # # # # # ##### # # # # # # # ## # ###### ##### # # # # # # + # # # # ## # # # # # # # # # # # ## ## # # # # # # # ## # +### #### # # #### # # ###### ##### #### # # # # # # # # ###### ### # # # + + align kIntAlign + +IgnoreSoftwareInt ; OUTSIDE REFERER + mfspr r1, srr0 + addi r1, r1, 0x04 + mtspr srr0, r1 + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + dcb.b 32, 0 + + + + +# # ###### # # ### +# # ## # # ##### # ###### # # ###### ##### ###### ## ## #### # # # ##### #### ##### # # # ##### +# # # # ## # # # # # # # # # # # # # # # # # ## # # # # # # # # ## # # +####### # # # # # # # # ##### ###### ##### # # ##### # # # # # # # # # # # # # # # # # # # +# # ###### # # # # # # # # # ##### # # # # # # # # # # # # ##### # # # # # +# # # # # ## # # # # # # # # # # # # # # ## # # # # # # # # ## # +# # # # # # ##### ###### ###### # ###### # # # # # #### # # # # #### # # ### # # # + + align kIntAlign + +HandlePerfMonitorInt ; OUTSIDE REFERER + mfspr r1, srr1 + oris r1, r1, 0x200 + mtspr srr1, r1 + mfsprg r1, 2 + mtlr r1 + mfsprg r1, 1 + rfi + dcb.b 32, 0 diff --git a/NanoKernel/NKInterrupts.s b/NanoKernel/NKInterrupts.s deleted file mode 100644 index ec49f23..0000000 --- a/NanoKernel/NKInterrupts.s +++ /dev/null @@ -1,3075 +0,0 @@ -; System = FFFFFFFF, Alt = 7DF2F700 (ecInstPageFault and ecDataPageFault disabled), same +/- VM -ecNoException equ 0 ; Exception -ecSystemCall equ 1 ; ? -ecTrapInstr equ 2 ; Exception -ecFloatException equ 3 ; Exception -ecInvalidInstr equ 4 ; Exception -ecPrivilegedInstr equ 5 ; ? -ecMachineCheck equ 7 ; Exception -ecInstTrace equ 8 ; Exception -ecInstInvalidAddress equ 10 ; Exception -ecInstHardwareFault equ 11 ; Exception -ecInstPageFault equ 12 ; Exception -ecInstSupAccessViolation equ 14 ; Exception - -; Usually from MemRetryDSI (also IntAlignment and IntMachineCheck) -ecDataInvalidAddress equ 18 ; ExceptionMemRetried -ecDataHardwareFault equ 19 ; ExceptionMemRetried -ecDataPageFault equ 20 ; ExceptionMemRetried -ecDataWriteViolation equ 21 ; ExceptionMemRetried -ecDataSupAccessViolation equ 22 ; ExceptionMemRetried -ecDataSupWriteViolation equ 23 ; ? -ecUnknown24 equ 24 ; ExceptionMemRetried - - - -; AUTO-GENERATED SYMBOL LIST -; IMPORTS: -; NKAddressSpaces -; FindAreaAbove -; SpaceGetPagePLE -; SpaceL2PUsingBATs -; NKCache -; FlushL1CacheUsingMSSCR0 -; NKConsoleLog -; printw -; NKIndex -; LookupID -; NKInit -; ResetBuiltinKernel -; NKMPCalls -; BlockMPCall -; kcMPDispatch -; NKPaging -; PagingFunc1 -; PagingL2PWithBATs -; NKPoolAllocator -; PoolAlloc -; NKScheduler -; FlagSchEval -; Restore_v0_v31 -; Save_v0_v31 -; SchEval -; SchExitInterrupt -; SchFiddlePriorityShifty -; SchRdyTaskNow -; SchRestoreStartingAtR14 -; SchReturn -; SchSaveStartingAtR14 -; SchSwitchSpace -; SchTaskUnrdy -; NKSync -; CauseNotification -; EnqueueMessage -; UnblockBlueIfCouldBePolling -; NKTasks -; ThrowTaskToDebugger -; NKThud -; panic -; NKTimers -; TimerDispatch -; NKTranslation -; FDPEmulateInstruction -; FDP_003c -; FDP_011c -; FDP_0DA0 -; EXPORTS: -; Exception (=> NKThud, NKTranslation) -; ExceptionMemRetried (=> NKTranslation) -; FloatLoadJumpTable (=> NKTranslation) -; FloatSaveJumpTable (=> NKTranslation) -; HandlePerfMonitorInt (=> NKInit) -; IgnoreSoftwareInt (=> NKInit, NKTranslation) -; IntAlignment (=> NKInit) -; IntDSI (=> NKInit) -; IntDecrementer (=> NKInit) -; IntExternalAlternate (=> NKInit) -; IntExternalSystem (=> NKInit) -; IntFPUnavail (=> NKInit) -; IntHandleSpecialFPException (=> NKRTASCalls) -; IntISI (=> NKInit) -; IntMachineCheck (=> NKInit) -; IntPerfMonitor (=> NKInit) -; IntProgram (=> NKInit) -; IntReturn (=> NKCache, NKMPCalls, NKPowerCalls, NKPrimaryIntHandlers, NKRTASCalls, NKVMCalls) -; IntSyscall (=> NKInit) -; IntThermalEvent (=> NKInit) -; IntTrace (=> NKInit) -; LoadInterruptRegisters (=> NKTranslation) -; MemRetryDSI (=> NKInit) -; MemRetryMachineCheck (=> NKInit) -; PIHDSI (=> NKInit) -; SIGP (=> NKMPCalls, NKScheduler, NKSleep) -; bugger_around_with_floats (=> NKRTASCalls) -; kcPrioritizeInterrupts (=> NKInit) -; kcResetSystem (=> NKInit) -; kcReturnFromException (=> NKInit) -; kcRunAlternateContext (=> NKInit) -; kcThud (=> NKInit) -; major_0x03324 (=> NKTranslation) -; major_0x03548 (=> NKTranslation) -; major_0x046d0 (=> NKInit) -; major_0x04a20 (=> NKInit) -; wordfill (=> NKInit, NKPowerCalls) - - - -IntPanicIsland - b panic - -IntLocalBlockMPCall - b BlockMPCall - - - -; ARG EC r8, nuFlags r16, ? r17, ? r19, ? r23, vecTable *r24 - - align 5 - -ExceptionMemRetried - - mfsprg r1, 0 - mtsprg 3, r24 - - lwz r9, EWA.Enables(r1) - rlwinm r23, r17, (32-1), 27, 31 - rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) - - bcl BO_IF, EWA.kFlag15, major_0x02980_0x100 - - lwz r6, EWA.PA_ContextBlock(r1) - - _bset r7, r16, 27 - - neg r23, r23 - mtcrf 0x3f, r7 - add r19, r19, r23 - - ; Exception code in high byte of flags - rlwimi r7, r8, 24, 0xFF000000 - - - ; Increment counter, easy enough - lwz r1, EWA.PA_KDP(r1) - slwi r8, r8, 2 - 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 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) - - - ; 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 - - cmpwi cr1, r9, ecDataPageFault - - 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 - lwz r12, KDP.LA_EmulatorKernelTrapTable + NanoKernelCallTable.ReturnFromException(r1) - - bcl BO_IF, EWA.kFlagLowSaves, PreferRegistersFromEWASavingContextBlock - - rlwinm r7, r7, 0, 29, 16 ; unset 17-28 - 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) - 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) - blr - - - -; This is the only path to UnhandledCodeFault - -Exception - - mfsprg r1, 0 - mtcrf 0x3f, r7 - - lwz r9, EWA.Enables(r1) - lwz r1, EWA.PA_KDP(r1) - - rlwnm. r9, r9, r8, 0, 0 ; cr0.lt = (exception enabled?) - - ; Exception code in high byte of flags - rlwimi r7, r8, 24, 0xFF000000 - - ; Increment counter, easy enough - slwi r8, r8, 2 - 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 - - ; 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 - - 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 - mtsprg 3, r8 - - ; Exception came from emulator! Can't handle that with a 68k interrupt, can we? - bcl BO_IF, EWA.kFlagEmu, SuspendBlueTask - - - -; Swap the blue task between the system and alternate contexts - -; 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) -@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) - mfctr r8 - stw r10, ContextBlock.CodePtr(r6) - stw r8, ContextBlock.KernelCTR(r6) - - bc BO_IF_NOT, EWA.kFlagHasMQ, @no_mq - lwz r8, ContextBlock.MQ(r9) - mfspr r12, mq - mtspr mq, r8 - stw r12, ContextBlock.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) - - bnel bugger_around_with_floats - - bc BO_IF_NOT, EWA.kFlagVec, @no_vec - bl Save_v0_v31 -@no_vec - - stw r11, ContextBlock.MSR(r6) - - - ; 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) - mtxer r8 - lwz r8, ContextBlock.KernelCTR(r6) - lwz r10, ContextBlock.CodePtr(r6) - mtctr r8 - - bnel IntHandleSpecialFPException - - lwarx r8, 0, r1 - sync - stwcx. r8, 0, r1 - - lwz r29, ContextBlock.VectorSaveArea(r6) - lwz r8, ContextBlock.r1(r6) - cmpwi r29, 0 - 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) - - - -; Almost always goes straight through to SchReturn. Zeros a word in EWA. - -; ARG flags_to_set r7 - -IntReturn ; OUTSIDE REFERER - - 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 - - - -; Almost never called (by above func) - -major_0x02ccc ; OUTSIDE REFERER - - mtcrf 0x3f, r7 - - bc BO_IF_NOT, EWA.kFlagLowSaves, @major_0x02ccc_0x18 - _bclr r7, r7, EWA.kFlagLowSaves - - bc BO_IF, EWA.kFlag31, major_0x02ccc_0x30 - _bclr r7, r7, EWA.kFlag26 - - b @return -@major_0x02ccc_0x18 - - bc BO_IF_NOT, EWA.kFlag26, @return - _bclr r7, r7, EWA.kFlag26 - - stw r7, EWA.Flags(r1) - li r8, ecInstTrace - b Exception -@return - - blr - -major_0x02ccc_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 - 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 - mtcrf 0x10, r26 ; so the second nybble of the entry is copied to cr3 - lha r22, 0x0c00(r25) - addi r23, r8, KDP.VecBaseMemRetry - add r22, r22, r25 - mfsprg r24, 3 - mtlr r22 - mtsprg 3, r23 - mfmsr r14 - 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! - 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 IntLocalBlockMPCall - - - -@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 - - - -#### ## ## ######## ## ## ### ## ## ######## ## ######## ######## ###### - ## ### ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## - ## #### ## ## ## ## ## ## #### ## ## ## ## ## ## ## ## - ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ###### ######## ###### - ## ## #### ## ## ## ######### ## #### ## ## ## ## ## ## ## - ## ## ### ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## -#### ## ## ## ## ## ## ## ## ## ######## ######## ######## ## ## ###### - - align kIntAlign - -IntDecrementer ; OUTSIDE REFERER - - bl LoadInterruptRegisters - - lwz r8, KDP.OldKDP(r1) - rlwinm. r9, r11, 0, 16, 16 - cmpwi cr1, r8, 0x00 - beq MaskedInterruptTaken - beq cr1, IntDecrementer_0x54 - - stw r16, ContextBlock.r16(r6) - stw r17, ContextBlock.r17(r6) - stw r18, ContextBlock.r18(r6) - stw r25, ContextBlock.r25(r6) - - bl SchFiddlePriorityShifty - ble IntDecrementer_0x48 - - lwz r8, PSA.CriticalReadyQ + ReadyQueue.Timecake + 4(r1) - mtspr dec, r8 - - lwz r16, ContextBlock.r16(r6) - lwz r17, ContextBlock.r17(r6) - lwz r18, ContextBlock.r18(r6) - b IntReturn - -IntDecrementer_0x48 - lwz r16, 0x0184(r6) - lwz r17, 0x018c(r6) - lwz r18, 0x0194(r6) - -IntDecrementer_0x54 -; r6 = ewa - bl SchSaveStartingAtR14 -; r8 = sprg0 (not used by me) - - - _Lock PSA.SchLock, scratch1=r8, scratch2=r9 - - lwz r8, 0x0e8c(r1) - addi r8, r8, 0x01 - stw r8, 0x0e8c(r1) - bl TimerDispatch - _AssertAndRelease PSA.SchLock, scratch=r8 - - bl SchRestoreStartingAtR14 - b IntReturn - - - -### ###### ##### ### - # # # ##### # # # # # - # ## # # # # # # - # # # # # # # ##### # - # # # # # # # # # - # # ## # # # # # # -### # # # ###### ##### ### - -; Kick it to the FDP-associated MemRetryDSI - - align kIntAlign - -IntDSI - - mfsprg r1, 0 - stmw r2, EWA.r2(r1) - mfsprg r11, 1 - - stw r0, EWA.r0(r1) - stw r11, EWA.r1(r1) ; Why? - - li r0, 0 - - mfspr r10, srr0 - mfspr r11, srr1 - mfsprg r12, 2 - mfcr r13 - mfsprg r24, 3 - - lwz r16, EWA.Flags(r1) - lwz r1, EWA.PA_KDP(r1) - - mfspr r26, dsisr - - ; Activate the Translation vecTable, and test DSISR bit 5 - ; ("Set if the access is due to a lwarx, ldarx, stwcx., or stdcx. - ; instruction that addresses memory that is Write Through - ; Required or Caching Inhibited; otherwise cleared") - addi r23, r1, KDP.VecBaseMemRetry - andis. r28, r26, 0x400 ; test bit 5 (see cmt above) - mtsprg 3, r23 - - mfmsr r14 - bne HandleDSIDueToIllegalSyncPrimitive - - _bset r15, r14, 27 ; temp set MSR[DR] - mtmsr r15 - isync - - lwz r27, 0(r10) ; get instruction (should be fine!) - - mtmsr r14 ; restore MSR - isync - - - -major_0x03324 ; OUTSIDE REFERER - rlwinm. r18, r27, 18, 25, 29 - lwz r25, 0x0650(r1) - li r21, 0x00 - mfsprg r1, 0 - beq major_0x03324_0x18 - lwzx r18, r1, r18 - -major_0x03324_0x18 - andis. r26, r27, 0xec00 - lwz r16, EWA.Flags(r1) - rlwinm r17, r27, 0, 6, 15 - rlwimi r16, r16, 27, 26, 26 - bge major_0x03324_0x58 - rlwimi r25, r27, 7, 26, 29 - rlwimi r25, r27, 12, 25, 25 - lwz r26, 0x0b80(r25) - extsh r23, r27 - rlwimi r25, r26, 26, 22, 29 - mtlr r25 - mtcr r26 - add r18, r18, r23 - crclr cr5_so - rlwimi r17, r26, 6, 26, 5 - blr - -major_0x03324_0x58 - rlwimi r25, r27, 27, 26, 29 - rlwimi r25, r27, 0, 25, 25 - rlwimi r25, r27, 6, 23, 24 - rlwimi r25, r27, 4, 22, 22 - lwz r26, 0x0800(r25) - rlwinm r23, r27, 23, 25, 29 - rlwimi r25, r26, 26, 22, 29 - mtlr r25 - mtcr r26 - lwzx r23, r1, r23 - crclr cr5_so - rlwimi r17, r26, 6, 26, 5 - add r18, r18, r23 - bclr BO_IF_NOT, 13 - neg r23, r23 - add r18, r18, r23 - blr - - - -HandleDSIDueToIllegalSyncPrimitive ; OUTSIDE REFERER - - ori r15, r14, 0x10 - mr r28, r16 - mfspr r18, dar - mfspr r19, dsisr - mtmsr r15 - isync - lwz r27, 0x0000(r10) - mtmsr r14 - isync - mtsprg 3, r24 - lwz r1, -0x0004(r1) - mr r31, r19 - mr r8, r18 - li r9, 0x00 - bl SpaceL2PUsingBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17 - mr r16, r28 - crset cr3_so - mfsprg r1, 0 - beq major_0x03324_0x12c - mr r18, r8 - rlwinm r28, r27, 13, 25, 29 - andis. r9, r31, 0x200 - rlwimi r18, r17, 0, 0, 19 - beq major_0x03324_0x118 - lwzx r31, r1, r28 - stwcx. r31, 0, r18 - sync - dcbf 0, r18 - mfcr r31 - rlwimi r13, r31, 0, 0, 3 - b FDP_0da0 - -major_0x03324_0x118 - lwarx r31, 0, r18 - sync - dcbf 0, r18 - stwx r31, r1, r28 - b FDP_0da0 - -major_0x03324_0x12c - subi r10, r10, 4 - b FDP_0da0 - - - -; This int handler is our best foothold into the FDP! - - align kIntAlign - -IntAlignment ; OUTSIDE REFERER - mfsprg r1, 0 - stmw r2, 0x0008(r1) - mfsprg r11, 1 - stw r0, 0x0000(r1) - stw r11, 0x0004(r1) - li r0, 0x00 - - lwz r11, EWA.PA_CurTask(r1) - lwz r16, EWA.Flags(r1) - lwz r21, Task.Flags(r11) - lwz r1, -0x0004(r1) ; wha??? - - lwz r11, KDP.NanoKernelInfo + NKNanoKernelInfo.MisalignmentCount(r1) - addi r11, r11, 1 - stw r11, KDP.NanoKernelInfo + NKNanoKernelInfo.MisalignmentCount(r1) - - mfspr r10, srr0 - mfspr r11, srr1 - mfsprg r12, 2 - mfcr r13 - mfsprg r24, 3 - mfspr r27, dsisr - mfspr r18, dar - - rlwinm. r21, r21, 0, Task.kFlagTakesAllExceptions, Task.kFlagTakesAllExceptions - - addi r23, r1, KDP.VecBaseMemRetry - - bne major_0x03548_0x20 - - ; DSISR for misaligned X-form instruction: - - ; (0) 0 (14)||(15) 29:30 (16)||(17) 25 (17)||(18) 21:24 (21)||(22) rD (26)||(27) rA? (31) - - ; DSISR for misaligned D-form instruction: - - ; (0) zero (16)||(17) 5 (17)||(18) 1:4 (21)||(22) rD (26)||(27) rA? (31) - -FDP_TableBase equ 0xa00 - - ; Virtual PC might put the thing in MSR_LE mode - rlwinm. r21, r11, 0, MSR_LEbit, MSR_LEbit ; msr bits in srr1 - - ; Get the FDP and F.O. if we were in MSR_LE mode - lwz r25, KDP.PA_FDP(r1) - bne major_0x03548_0x20 - - - rlwinm. r21, r27, 17, 30, 31 ; evaluate hi two bits of XO (or 0 for d-form?) - - rlwinm r17, r27, 16, 6, 15 ; save src and dest register indices in r17 - - mfsprg r1, 0 - - rlwimi r25, r27, 24, 23, 29 ; add constant fields from dsisr (*4) to FDP - - - rlwimi r16, r16, 27, 26, 26 ; AllCpuFeatures: copy bit 21 to bit 26 - - bne @regidx - - ; D-form (immediate-indexed) instruction - lwz r26, FDP_TableBase + 4*(0x40 + 0x20)(r25) ; use upper quarter of table - mfmsr r14 - rlwimi r25, r26, 26, 22, 29 ; third byte of lookup value is a /4 code offset in FDP - mtlr r25 ; so get ready to go there - ori r15, r14, 0x10 - mtcr r26 - rlwimi r17, r26, 6, 26, 5 ; wrap some shite around the register values - crclr cr5_so - blr - -@regidx - ; X-form (register-indexed) instruction - lwz r26, FDP_TableBase(r25) - mfmsr r14 - mtsprg 3, r23 - rlwimi r25, r26, 26, 22, 29 - mtlr r25 - ori r15, r14, 0x10 - mtcr r26 - rlwimi r17, r26, 6, 26, 5 - crclr 23 ; unset bit 23 = cr5_so - bclr BO_IF_NOT, 12 ; jump now if bit 12 is off - - ; if bit 12 was on, turn on paging and fetch the offending insn - ; and also activate the Translation vector table - mtmsr r15 - isync - lwz r27, 0x0000(r10) - mtmsr r14 - isync - mtsprg 3, r24 - blr - - - -major_0x03548 ; OUTSIDE REFERER - sync - mtmsr r14 - isync - mflr r23 - icbi 0, r23 - sync - isync - blr - -major_0x03548_0x20 ; OUTSIDE REFERER - li r8, 0x00 - lis r17, -0x100 - mtcr r8 - mr r19, r18 - rlwimi r17, r27, 7, 31, 31 - xori r17, r17, 0x01 - li r8, ecUnknown24 - b ExceptionMemRetried - - - - align kIntAlign - -MemRetryDSI ; OUTSIDE REFERER - - mfsprg r1, 0 - mfspr r31, dsisr - mfspr r27, dar - andis. r28, r31, 0xc030 - lwz r1, -0x0004(r1) - bne MemRetryDSI_0x1c8 - mfspr r30, srr1 - andi. r28, r30, 0x4000 - mfsprg r30, 0 - beq MemRetryDSI_0x100 - stw r8, -0x00e0(r30) - stw r9, -0x00dc(r30) - mfcr r8 - stw r16, -0x00d8(r30) - stw r17, -0x00d4(r30) - stw r18, -0x00d0(r30) - stw r19, -0x00cc(r30) - stw r8, -0x00c8(r30) - lwz r8, -0x001c(r30) - mr r9, r27 - bl FindAreaAbove - lwz r16, 0x0024(r8) - lwz r17, 0x0028(r8) - cmplw r27, r16 - cmplw cr7, r27, r17 - blt MemRetryDSI_0xe0 - bgt cr7, MemRetryDSI_0xe0 - mr r31, r8 - mr r8, r27 - bl SpaceGetPagePLE ; LogicalPage *r8, Area *r31 // PLE *r30, notfound cr0.eq - beq MemRetryDSI_0xe0 - lwz r8, 0x0000(r30) - lwz r16, 0x0098(r31) - rlwinm r28, r8, 0, 29, 30 - cmpwi cr7, r28, 0x04 - cmpwi r28, 0x02 - beq cr7, MemRetryDSI_0xe0 - beq MemRetryDSI_0xe0 - -MemRetryDSI_0x98 - addi r17, r31, 0x90 - cmpw r16, r17 - addi r17, r16, 0x14 - beq MemRetryDSI_0x158 - lwz r9, 0x0010(r16) - add r9, r9, r17 - -MemRetryDSI_0xb0 - lwz r18, 0x0000(r17) - cmplw cr7, r17, r9 - lwz r19, 0x0004(r17) - bgt cr7, MemRetryDSI_0xd8 - cmplw r27, r18 - cmplw cr7, r27, r19 - blt MemRetryDSI_0xd0 - ble cr7, MemRetryDSI_0xe0 - -MemRetryDSI_0xd0 - addi r17, r17, 0x08 - b MemRetryDSI_0xb0 - -MemRetryDSI_0xd8 - lwz r16, 0x0008(r16) - b MemRetryDSI_0x98 - -MemRetryDSI_0xe0 - mfsprg r30, 0 - mfspr r31, dsisr - lwz r8, -0x00e0(r30) - lwz r9, -0x00dc(r30) - lwz r16, -0x00d8(r30) - lwz r17, -0x00d4(r30) - lwz r18, -0x00d0(r30) - lwz r19, -0x00cc(r30) - -MemRetryDSI_0x100 - andis. r28, r31, 0x800 - addi r29, r1, KDP.BATs + 0xa0 - bnel PagingL2PWithBATs - li r28, 0x43 - and r28, r31, r28 - cmpwi cr7, r28, 0x43 - beql IntPanicIsland - mfsprg r28, 2 - mtlr r28 - bne cr7, MemRetryDSI_0x144 - mfspr r28, srr0 - addi r28, r28, 0x04 - lwz r26, 0x0e90(r1) - mtspr srr0, r28 - addi r26, r26, 0x01 - stw r26, 0x0e90(r1) - b MemRetryDSI_0x19c - -MemRetryDSI_0x144 - andi. r28, r31, 0x03 - li r8, ecDataSupAccessViolation - beq ExceptionMemRetried - li r8, ecDataWriteViolation - b ExceptionMemRetried - -MemRetryDSI_0x158 - mfsprg r30, 0 - lwz r16, 0x0f00(r1) - lwz r8, -0x00c8(r30) - addi r16, r16, 0x01 - mtcr r8 - lwz r9, -0x00dc(r30) - stw r16, 0x0f00(r1) - lwz r16, -0x00d8(r30) - lwz r17, -0x00d4(r30) - lwz r18, -0x00d0(r30) - lwz r19, -0x00cc(r30) - lwz r8, -0x00e0(r30) - mfspr r29, srr1 - mfsprg r28, 2 - _bclr r29, r29, 17 - mtlr r28 - mtspr srr1, r29 - -MemRetryDSI_0x19c - mfsprg r1, 1 - rlwinm r26, r25, 30, 24, 31 - rfi - dcb.b 32, 0 - - -MemRetryDSI_0x1c8 - andis. r28, r31, 0x8010 - bne MemRetryMachineCheck_0x14c - - _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 - - bl PagingFunc1 - _AssertAndRelease PSA.HTABLock, scratch=r28 - mfsprg r28, 2 - mtlr r28 - beq MemRetryDSI_0x19c - li r8, ecDataInvalidAddress - bge ExceptionMemRetried - li r8, ecDataPageFault - b ExceptionMemRetried - - - -MemRetryMachineCheck ; OUTSIDE REFERER - mfsprg r1, 0 - mr r28, r8 - - lwz r27, EWA.CPUBase + CPU.ID(r1) - _log 'CPU ' - mr r8, r27 - bl Printw - - _log 'MemRetry machine check - last EA ' - lwz r1, EWA.PA_KDP(r1) - lwz r27, 0x0694(r1) - mr r8, r27 - bl Printw - - _log ' SRR1 ' - mfspr r8, srr1 - mr r8, r8 - bl Printw - - _log ' SRR0 ' - mfspr r8, srr0 - mr r8, r8 - bl Printw - _log '^n' - - mr r8, r28 - lwz r1, EWA.PA_KDP(r1) - lwz r27, 0x0694(r1) - subf r28, r19, r27 - cmpwi r28, -0x10 - blt MemRetryMachineCheck_0x14c - cmpwi r28, 0x10 - bgt MemRetryMachineCheck_0x14c - - _Lock PSA.HTABLock, scratch1=r28, scratch2=r29 - - lwz r28, 0x0e98(r1) - addi r28, r28, 0x01 - stw r28, 0x0e98(r1) - lwz r29, 0x0698(r1) - li r28, 0x00 - stw r28, 0x0000(r29) - mfspr r28, pvr - rlwinm. r28, r28, 0, 0, 14 - sync - tlbie r27 - beq MemRetryMachineCheck_0x124 - sync - tlbsync - -MemRetryMachineCheck_0x124 - sync - isync - _AssertAndRelease PSA.HTABLock, scratch=r28 - - - -MemRetryMachineCheck_0x14c ; OUTSIDE REFERER - cmplw r10, r19 - li r8, ecDataHardwareFault - bne ExceptionMemRetried - mfsprg r1, 0 - mtsprg 3, r24 - lmw r14, 0x0038(r1) - li r8, ecInstHardwareFault - b Exception - - - - align kIntAlign - -IntISI ; OUTSIDE REFERER - - bl LoadInterruptRegisters - - andis. r8, r11, 0x4020 - beq major_0x039dc_0x14 - mfsprg r8, 0 - stmw r14, 0x0038(r8) - - _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 - - mr r27, r10 - bl PagingFunc1 - _AssertAndRelease PSA.HTABLock, scratch=r28 - mfsprg r8, 0 - bne major_0x039dc - - - ; MemRetry - - mfsprg r24, 3 - mfmsr r14 - ori r15, r14, 0x10 - addi r23, r1, KDP.VecBaseMemRetry - mtsprg 3, r23 - mr r19, r10 - mtmsr r15 - isync - lbz r23, 0x0000(r19) - sync - mtmsr r14 - isync - mfsprg r8, 0 - mtsprg 3, r24 - lmw r14, 0x0038(r8) - b IntReturn - - - -major_0x039dc ; OUTSIDE REFERER - lmw r14, 0x0038(r8) - li r8, ecInstPageFault - blt Exception - li r8, ecInstInvalidAddress - b Exception - -major_0x039dc_0x14 ; OUTSIDE REFERER - andis. r8, r11, 0x800 - li r8, ecInstSupAccessViolation - bne Exception - li r8, ecInstHardwareFault - b Exception - - - -IntMachineCheck ; OUTSIDE REFERER - - bl LoadInterruptRegisters - - lwz r9, EWA.CPUBase + CPU.ID(r8) - _log 'CPU ' - mr r8, r9 - bl Printw - - _log 'Machine check at ' ; srr1/srr0 - mr r8, r11 - bl Printw - mr r8, r10 - bl Printw - - _log '- last unmapped EA ' - lwz r8, 0x0694(r1) - mr r8, r8 - bl Printw - _log '^n' - - rlwinm. r8, r11, 0, 2, 2 - beq @not_L1_data_cache_error - -;L1 data cache error - bl FlushL1CacheUsingMSSCR0 - b IntReturn - -@not_L1_data_cache_error - li r8, ecMachineCheck - b Exception - - - -MaskedInterruptTaken ; OUTSIDE REFERER - _log '*** CPU MALFUNCTION - Masked interrupt punched through. SRR1/0 ' - mr r8, r11 - bl Printw - mr r8, r10 - bl Printw - _log '^n' - lis r10, -0x4523 - ori r10, r10, 0xcb00 - li r8, ecMachineCheck - b Exception - - - - align kIntAlign - -PIHDSI ; OUTSIDE REFERER - mfspr r8, dsisr - rlwimi r11, r8, 0, 0, 9 - andis. r8, r11, 0x4020 - beq major_0x039dc_0x14 - mfsprg r8, 0 - stmw r14, 0x0038(r8) - lwz r1, -0x0004(r8) - - _Lock PSA.HTABLock, scratch1=r28, scratch2=r31 - - mfspr r27, dar - bl PagingFunc1 - _AssertAndRelease PSA.HTABLock, scratch=r28 - mfsprg r8, 0 - bne major_0x039dc - lmw r14, 0x0038(r8) - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - dcb.b 32, 0 - - - - - ###### ####### ####### -# # #### # # ###### ##### # # ##### # # # ##### #### # # # # # #### ###### ##### ##### # #### # # -# # # # # # # # # # # # ## # # # # # # ## ## # # # # # # # # # # # # ## # -#### # ###### ##### # # # # # # # # ##### # # # # # ## # ##### ## # ##### # # # # # # # # # -# # # # # # # # # ##### # # # # ##### # # # # # ## # # ##### # # # # # # # -# # # # # # # # # # # # # ## # # # # # # # # # # # # # # # # # # # ## -# # #### # # ###### # #### # # # # # # # #### # # ####### # # #### ###### # # # #### # # - - align kIntAlign - -; dead code? - - 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 - -kcReturnFromException ; OUTSIDE REFERER - - _bset r11, r11, MSR_EEbit - - mtcrf 0x3f, r7 - cmplwi cr1, r3, 1 ; exception handler return value - bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP - - blt cr1, major_0x03be0_0x58 - beq cr1, major_0x03be0_0x90 - - - subi r8, r3, 32 - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) - cmplwi r8, 224 - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionForcedCount(r1) - mfsprg r1, 0 - rlwimi r7, r3, 24, 0, 7 - blt major_0x03be0_0xe8 - li r8, ecTrapInstr - b Exception - -major_0x03be0_0x58 - mfsprg r1, 0 - lwz r8, 0x0040(r6) - lwz r10, 0x0084(r6) - rlwimi r7, r8, 0, 17, 7 - lwz r8, 0x0044(r6) - rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] - stw r8, EWA.Enables(r1) - andi. r8, r11, 0x900 - lwz r12, 0x008c(r6) - lwz r3, 0x0094(r6) - lwz r4, 0x009c(r6) - bnel major_0x03e18 - addi r9, r6, 0x40 - b IntReturn - -major_0x03be0_0x90 - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) - lwz r8, 0x0040(r6) - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.ExceptionPropagateCount(r1) - mfsprg r1, 0 - lwz r10, 0x0084(r6) - rlwimi r7, r8, 0, 17, 7 - lwz r8, 0x0044(r6) - mtcrf 0x0f, r7 - rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] - stw r8, EWA.Enables(r1) - lwz r12, 0x008c(r6) - lwz r3, 0x0094(r6) - lwz r4, 0x009c(r6) - bne cr2, major_0x03be0_0xe8 - bns cr6, major_0x03be0_0xe8 - stmw r14, 0x0038(r1) - lwz r17, 0x0064(r6) - lwz r20, 0x0068(r6) - lwz r21, 0x006c(r6) - lwz r19, ContextBlock.SRR0(r6) - lwz r18, 0x007c(r6) - -major_0x03be0_0xe8 - beq cr2, IntReturnToSystemContext - crclr cr6_so - mfspr r10, srr0 - li r8, ecTrapInstr - b Exception - - - - align 5 - -save_all_registers ; OUTSIDE REFERER - mfsprg r1, 0 - stw r6, 0x0018(r1) - mfsprg r6, 1 - stw r6, 0x0004(r1) - lwz r6, -0x0014(r1) - stw r0, 0x0104(r6) - stw r7, 0x013c(r6) - stw r8, 0x0144(r6) - stw r9, 0x014c(r6) - stw r10, 0x0154(r6) - stw r11, 0x015c(r6) - stw r12, 0x0164(r6) - stw r13, 0x016c(r6) - li r0, 0x00 - mfspr r10, srr0 - mfspr r11, srr1 - mfcr r13 - mfsprg r12, 2 - lwz r7, EWA.Flags(r1) - lwz r1, -0x0004(r1) - -; r6 = ewa - b SchSaveStartingAtR14 -; r8 = sprg0 (not used by me) - - - -# ### ###### -# #### ## ##### # # # ##### ###### ##### ##### # # ##### ##### # # ###### #### # #### ##### ###### ##### #### -# # # # # # # # ## # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # ##### # # # # # # # # # ###### ##### # # #### # ##### # # #### -# # # ###### # # # # # # # # ##### ##### # # ##### # # # # # ### # # # # ##### # -# # # # # # # # # ## # # # # # # # # # # # # # # # # # # # # # # # # -####### #### # # ##### ### # # # ###### # # # # #### # # # # ###### #### # #### # ###### # # #### - -; How we arrive here: -; -; 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. -; -; -; When we arrive here: -; -; r1 is saved in SPRG1 (r1 itself is junk) -; LR is saved in SPRG2 (LR itself contains return addr) -; -; -; Before we return: -; -; Reg Contains Original saved in -; --------------------------------------------- -; r0 0 ContextBlock -; r1 KDP EWA -; r2 (itself) -; r3 (itself) -; r4 (itself) -; r5 (itself) -; r6 ContextBlock EWA -; r7 Flags ContextBlock -; r8 EWA ContextBlock -; r9 (itself) ContextBlock -; r10 SRR0 ContextBlock -; r11 SRR1 ContextBlock -; r12 LR ContextBlock -; r13 CR ContextBlock -; -; -; Can be followed up by a call to SchSaveStartingAtR14, -; (which will put them in the ContextBlock too). - - align 5 - -LoadInterruptRegisters - - ; Get EWA pointer in r1 (phew) - mfsprg r1, 0 - - ; Save r6 in EWA - stw r6, EWA.r6(r1) - - ; Save pre-interrupt r1 (which SPRG1 held) to EWA - mfsprg r6, 1 - stw r6, EWA.r1(r1) - - ; Get ContextBlock pointer in r6 (phew) - lwz r6, EWA.PA_ContextBlock(r1) - - ; Save r0, r7-r13 in ContextBlock - stw r0, ContextBlock.r0(r6) - 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) - - ; Zero r0 (convenient) - li r0, 0 - - ; Make some useful special registers conveniently available - mfspr r10, srr0 - mfspr r11, srr1 - mfcr r13 - mfsprg r12, 2 - - ; Point r8 to EWA - mr r8, r1 - - ; Features in r7, KDP in r8 - lwz r7, EWA.Flags(r1) - lwz r1, EWA.PA_KDP(r1) - - blr - - - -### ####### ###### # # - # # # ##### # # # # # # # ## # # ## # # - # ## # # # # # # # ## # # # # # # # # # - # # # # # ##### ###### # # # # # # # # # # # # # - # # # # # # # # # # # # ###### # # ###### # # - # # ## # # # # # # ## # # # # # # # # -### # # # # # ##### # # # # ## # # # ###### - - align kIntAlign - -IntFPUnavail ; OUTSIDE REFERER - mfsprg r1, 0 - stw r11, -0x0290(r1) - stw r6, -0x028c(r1) - lwz r6, -0x0004(r1) - lwz r11, 0x0e88(r6) - addi r11, r11, 0x01 - stw r11, 0x0e88(r6) - mfspr r11, srr1 - ori r11, r11, 0x2000 - mtspr srr1, r11 - mfmsr r11 - ori r11, r11, 0x2000 - lwz r6, -0x0014(r1) - mtmsr r11 - isync - bl LoadFloatsFromContextBlock - lwz r11, -0x0290(r1) - lwz r6, -0x028c(r1) - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - dcb.b 32, 0 - - - - -major_0x03e18 ; OUTSIDE REFERER - rlwinm. r8, r11, 0, 18, 18 - bnelr - -IntHandleSpecialFPException ; OUTSIDE REFERER - lwz r8, 0x00e4(r6) - rlwinm. r8, r8, 1, 0, 0 - mfmsr r8 - ori r8, r8, 0x2000 - beqlr - mtmsr r8 - isync - ori r11, r11, 0x2000 - -LoadFloatsFromContextBlock ; OUTSIDE REFERER - lfd f31, 0x00e0(r6) - lfd f0, 0x0200(r6) - lfd f1, 0x0208(r6) - lfd f2, 0x0210(r6) - lfd f3, 0x0218(r6) - lfd f4, 0x0220(r6) - lfd f5, 0x0228(r6) - lfd f6, 0x0230(r6) - lfd f7, 0x0238(r6) - mtfsf 0xff, f31 - lfd f8, 0x0240(r6) - lfd f9, 0x0248(r6) - lfd f10, 0x0250(r6) - lfd f11, 0x0258(r6) - lfd f12, 0x0260(r6) - lfd f13, 0x0268(r6) - lfd f14, 0x0270(r6) - lfd f15, 0x0278(r6) - lfd f16, 0x0280(r6) - lfd f17, 0x0288(r6) - lfd f18, 0x0290(r6) - lfd f19, 0x0298(r6) - lfd f20, 0x02a0(r6) - lfd f21, 0x02a8(r6) - lfd f22, 0x02b0(r6) - lfd f23, 0x02b8(r6) - lfd f24, 0x02c0(r6) - lfd f25, 0x02c8(r6) - lfd f26, 0x02d0(r6) - lfd f27, 0x02d8(r6) - lfd f28, 0x02e0(r6) - lfd f29, 0x02e8(r6) - lfd f30, 0x02f0(r6) - lfd f31, 0x02f8(r6) - blr - - - - - -bugger_around_with_floats ; OUTSIDE REFERER - mfmsr r8 - ori r8, r8, 0x2000 - mtmsr r8 - isync - _bclr r11, r11, 18 - stfd f0, 0x0200(r6) - stfd f1, 0x0208(r6) - stfd f2, 0x0210(r6) - stfd f3, 0x0218(r6) - stfd f4, 0x0220(r6) - stfd f5, 0x0228(r6) - stfd f6, 0x0230(r6) - stfd f7, 0x0238(r6) - stfd f8, 0x0240(r6) - stfd f9, 0x0248(r6) - stfd f10, 0x0250(r6) - stfd f11, 0x0258(r6) - stfd f12, 0x0260(r6) - stfd f13, 0x0268(r6) - stfd f14, 0x0270(r6) - stfd f15, 0x0278(r6) - stfd f16, 0x0280(r6) - stfd f17, 0x0288(r6) - stfd f18, 0x0290(r6) - stfd f19, 0x0298(r6) - stfd f20, 0x02a0(r6) - stfd f21, 0x02a8(r6) - stfd f22, 0x02b0(r6) - stfd f23, 0x02b8(r6) - mffs f0 - stfd f24, 0x02c0(r6) - stfd f25, 0x02c8(r6) - stfd f26, 0x02d0(r6) - stfd f27, 0x02d8(r6) - stfd f28, 0x02e0(r6) - stfd f29, 0x02e8(r6) - stfd f30, 0x02f0(r6) - stfd f31, 0x02f8(r6) - stfd f0, 0x00e0(r6) - blr - - - - -; indexed emulation code, mofo - -;two instructions per load-store register - - macro - CreateFloatJumpTable &opcode, &dest, &highest==31 - - if &highest > 0 - CreateFloatJumpTable &opcode, &dest, highest = (&highest) - 1 - endif - - &opcode (&highest), -0x2e0(r1) - b &dest - - endm - - -FloatLoadJumpTable - CreateFloatJumpTable lfd, FDP_0da0 - - -FloatSaveJumpTable - CreateFloatJumpTable stfd, FDP_003c - - - - - align 6 - -major_0x04180 ; OUTSIDE REFERER - stw r6, -0x0290(r1) - stw r10, -0x028c(r1) - stw r11, -0x0288(r1) - lwz r6, -0x0014(r1) - lwz r10, 0x00d8(r6) - mfspr r11, srr1 - cmpwi r10, 0x00 - beql major_0x04180_0x9c - oris r11, r11, 0x200 - stw r9, -0x027c(r1) - mtspr srr1, r11 - mfmsr r11 - oris r11, r11, 0x200 - mtmsr r11 - isync - bl Restore_v0_v31 - lwz r8, -0x0004(r1) - lwz r11, 0x0ed4(r8) - addi r11, r11, 0x01 - stw r11, 0x0ed4(r8) - mtcr r13 - lwz r6, -0x0290(r1) - lwz r10, -0x028c(r1) - lwz r11, -0x0288(r1) - lwz r13, -0x0284(r1) - lwz r8, -0x0280(r1) - lwz r9, -0x027c(r1) - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - dcb.b 32, 0 - - -major_0x04180_0x9c - mtcr r13 - lwz r6, -0x0290(r1) - lwz r10, -0x028c(r1) - lwz r11, -0x0288(r1) - lwz r13, -0x0284(r1) - - - bl LoadInterruptRegisters - - li r8, ecInvalidInstr - b Exception - - - -### ###### # # - # # # ##### # # ###### ##### ###### ## ## #### # # # ##### #### ##### - # ## # # # # # # # # # # # # # # ## # # # # # # # - # # # # # ###### ##### # # ##### # # # # # # # # # # # # # # - # # # # # # # ##### # # # # # # # # # # # # ##### - # # ## # # # # # # # # # # # ## # # # # # # -### # # # # ###### # # # # # #### # # # # #### # # - - align kIntAlign - -IntPerfMonitor ; OUTSIDE REFERER - mtlr r1 - mfsprg r1, 0 - stw r8, -0x0280(r1) - stw r13, -0x0284(r1) - mflr r8 - mfcr r13 - cmpwi r8, 0xf20 - beq major_0x04180 - mtcr r13 - lwz r13, -0x0284(r1) - lwz r8, -0x0280(r1) - bl save_all_registers - mr r28, r8 - rlwinm. r9, r11, 0, 16, 16 - beq MaskedInterruptTaken - - _Lock PSA.SchLock, scratch1=r8, scratch2=r9 - - lwz r8, PSA.PMFHandlerID(r1) - -; r8 = id - bl LookupID - cmpwi r9, Notification.kIDClass - - mr r30, r8 - bne IntPerfMonitor_0x88 - lwz r16, -0x0340(r28) - lwz r17, -0x0008(r28) - stw r16, 0x0010(r30) - lwz r16, 0x0000(r17) - stw r16, 0x0014(r30) - mfspr r16, 955 - stw r16, 0x0018(r30) - bl CauseNotification - -IntPerfMonitor_0x88 - _AssertAndRelease PSA.SchLock, scratch=r8 - -; r6 = ewa - bl SchRestoreStartingAtR14 - b IntReturn - - - -; Notify the Thermal Handler - - align kIntAlign - -IntThermalEvent ; OUTSIDE REFERER - bl save_all_registers - mr r28, r8 - rlwinm. r9, r11, 0, 16, 16 - beq MaskedInterruptTaken - _log 'Thermal event^n' - - _Lock PSA.SchLock, scratch1=r8, scratch2=r9 - - lwz r8, PSA.ThermalHandlerID(r1) - bl LookupID - cmpwi r9, Notification.kIDClass - mr r30, r8 - bne @no_thermal_handler - - lwz r16, EWA.CPUBase + CPU.ID(r28) - stw r16, Notification.MsgWord1(r30) - bl CauseNotification -@no_thermal_handler - - _AssertAndRelease PSA.SchLock, scratch=r8 - bl SchRestoreStartingAtR14 - b IntReturn - - - - ###### # ##### -# # #### # # # # # # # # # ##### ###### ##### # # ## ##### ###### # # #### # # ##### ###### # # ##### -# # # # # # # # ## # # # # # # # # ## # # # # # # # # ## # # # # # # -#### # ###### # # # # # # # # # ##### # # # # # # # # ##### # # # # # # # ##### ## # -# # # # # # # # # # ####### # # # ##### # # # ###### # # # # # # # # # # ## # -# # # # # # # # # ## # # # # # # # # ## # # # # # # # # # ## # # # # # -# # #### # # #### # # # # ###### # ###### # # # # # # # ###### ##### #### # # # ###### # # # - -; We can assume that this is being called from the emulator - -; We accept a logical NCB ptr but the kernel needs a physical one. -; So we keep a four-entry cache in KDP, mapping logical NCB ptrs -; to physical ones. But when are there multiple alt contexts? - -; ARG flags? r3, mask r4 - - align kIntAlign - -kcRunAlternateContext - - mtcrf 0x3f, r7 - - bcl BO_IF_NOT, EWA.kFlagBlue, IntReturn - - and. r8, r4, r13 - lwz r9, KDP.NCBCacheLA0(r1) - rlwinm r8, r3, 0, 0, 25 - cmpw cr1, r8, r9 - bne IntReturn - lwz r9, KDP.NCBCachePA0(r1) - bne cr1, @search_cache - - -@found_physical_in_cache ; can come here from below after a more thorough search - - addi r8, r1, KDP.VecBaseAlternate ; the only use of this vector table? - mtsprg 3, r8 - - lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) - mtcrf 0x3f, r7 - mfsprg r1, 0 - clrlwi r7, r7, 8 - stw r8, ContextBlock.LA_EmulatorKernelTrapTable(r9) - - stw r9, EWA.PA_ContextBlock(r1) - - b IntReturnToOtherBlueContext - - -@search_cache - - lwz r9, KDP.NCBCacheLA1(r1) - cmpw cr1, r8, r9 - beq cr1, @found_in_slot_1 - - lwz r9, KDP.NCBCacheLA2(r1) - cmpw cr1, r8, r9 - beq cr1, @found_in_slot_2 - - lwz r9, KDP.NCBCacheLA3(r1) - cmpw cr1, r8, r9 - beq cr1, @found_in_slot_3 - - - ; No luck with the cache - - mfsprg r1, 0 - stmw r14, EWA.r14(r1) - lwz r1, EWA.PA_KDP(r1) - - cmpw cr1, r8, r6 - beq cr1, @fail - - mr r27, r8 - addi r29, r1, KDP.BATs + 0xa0 - bl PagingL2PWithBATs - clrlwi r23, r8, 20 - beq @fail - - cmplwi r23, 0x0d00 - mr r9, r8 - mr r8, r31 - ble @not_straddling_pages - - addi r27, r27, 0x1000 - addi r29, r1, KDP.BATs + 0xa0 - bl PagingL2PWithBATs - beq @fail - - subi r31, r31, 0x1000 - xor r23, r8, r31 - rlwinm. r23, r23, 0, 25, 22 - bne @fail ; because physical pages are discontiguous -@not_straddling_pages - - clrlwi r23, r31, 30 - cmpwi r23, 3 - rlwimi r8, r9, 0, 20, 31 - beq @fail - - - ; Found a non-cached physical address for this NCB! - - lwz r23, KDP.NanoKernelInfo + NKNanoKernelInfo.NCBPtrCacheMissCount(r1) - addi r23, r23, 1 - stw r23, KDP.NanoKernelInfo + NKNanoKernelInfo.NCBPtrCacheMissCount(r1) - - - ; Stick it in cache slot 3 - - mfsprg r1, 0 - lmw r14, EWA.r14(r1) - lwz r1, EWA.PA_KDP(r1) - stw r8, KDP.NCBCachePA3(r1) - - -@found_in_slot_3 ; so promote to slot 2 - - lwz r8, KDP.NCBCacheLA2(r1) - stw r9, KDP.NCBCacheLA2(r1) - stw r8, KDP.NCBCacheLA3(r1) - - lwz r9, KDP.NCBCachePA3(r1) - lwz r8, KDP.NCBCachePA2(r1) - stw r9, KDP.NCBCachePA2(r1) - stw r8, KDP.NCBCachePA3(r1) - - lwz r9, KDP.NCBCacheLA2(r1) - - -@found_in_slot_2 ; so promote to slot 1 - - lwz r8, KDP.NCBCacheLA1(r1) - stw r9, KDP.NCBCacheLA1(r1) - stw r8, KDP.NCBCacheLA2(r1) - - lwz r9, KDP.NCBCachePA2(r1) - lwz r8, KDP.NCBCachePA1(r1) - stw r9, KDP.NCBCachePA1(r1) - stw r8, KDP.NCBCachePA2(r1) - - lwz r9, KDP.NCBCacheLA1(r1) - - -@found_in_slot_1 ; so promote to slot 0, save elsewhere, and push on - - lwz r8, KDP.NCBCacheLA0(r1) - stw r9, KDP.NCBCacheLA0(r1) - stw r9, KDP.LA_NCB(r1) - stw r8, KDP.NCBCacheLA1(r1) - - lwz r9, KDP.NCBCachePA1(r1) - lwz r8, KDP.NCBCachePA0(r1) - stw r9, KDP.NCBCachePA0(r1) - stw r8, KDP.NCBCachePA1(r1) - - b @found_physical_in_cache - - -@fail - - mfsprg r1, 0 - lmw r14, EWA.r14(r1) - lwz r1, EWA.PA_KDP(r1) - li r8, ecTrapInstr - b Exception - - - -; > r8 = dest -; > r22 = len in bytes -; > r23 = fillword - -wordfill ; OUTSIDE REFERER - subic. r22, r22, 4 - stwx r23, r8, r22 - bne wordfill - blr - - - - ###### ##### -# # #### # # ###### #### ###### ##### # # # # #### ##### ###### # # -# # # # # # # # # # # # # # # # ## ## -#### # ###### ##### #### ##### # ##### # #### # ##### # ## # -# # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # -# # #### # # ###### #### ###### # ##### # #### # ###### # # - -; Handle a 68k reset trap. - -; If A0(r3)/A1(r4) == 'Gary'/$05051955, load the register list in A3? Or is this now disabled? - -; New SRR0 = SRR0 & ~r5(D0) | r7(D2) - - align kIntAlign - -kcResetSystem ; OUTSIDE REFERER -; r6 = ewa - bl SchSaveStartingAtR14 -; r8 = sprg0 (not used by me) - - ; Check for 601 (rtc vs timebase) - mfpvr r9 - rlwinm. r9, r9, 0, 0, 14 - - ; This xoris/cmplwi technique is very cool - xoris r8, r3, 'Ga' - - beq @is_601 - mftb r9 - b @endif_601 -@is_601 - dialect POWER - mfrtcl r9 - dialect PowerPC -@endif_601 - - ; Not sure why this would need to hit cr0? - andis. r9, r9, 0xffff - - cmplwi r8, 'ry' - bne NonGaryReset - - ; r4 (i.e. A1) == 5 May 1956? - xoris r8, r4, 0x0505 - cmplwi r8, 0x1956 - bne NonGaryReset - - andc r11, r11, r5 - lwz r8, ContextBlock.r7(r6) - or r11, r11, r8 - - _log 'Skeleton key inserted at' - - mr r8, r11 - bl Printw - - mr r8, r10 - bl Printw - - _log '^n' - - b IntReturn - - - -; NonGaryReset - -; A 68k reset trap without Gary Davidian's magic numbers. - -NonGaryReset - - _log 'ResetSystem trap entered^n' - - lwz r8, KDP.OldKDP(r1) - - cmpwi r8, 0 - beq ResetBuiltinKernel - - _log 'Unplugging the replacement nanokernel^n' - - lwz r8, KDP.OldKDP(r1) - mfsprg r1, 0 - addi r9, r8, KDP.VecBaseSystem - mtsprg 0, r8 ; old NK has only one EWA! - mtsprg 3, r9 - - lwz r9, EWA.r1(r1) - stw r9, EWA.r1(r8) - - lwz r9, EWA.r6(r1) - stw r9, EWA.r6(r8) - - stw r6, 0x065c(r8) - stw r7, 0x0660(r8) ; ?????????? - - lwz r9, EWA.Enables(r1) - stw r9, 0x0664(r8) - -; r6 = ewa - bl SchRestoreStartingAtR14 - subi r10, r10, 4 - lwz r1, -0x0004(r1) - -; sprg0 = for r1 and r6 -; r1 = kdp -; r6 = register restore area -; r7 = flag to insert into XER -; r10 = new srr0 (return location) -; r11 = new srr1 -; r12 = lr restore -; r13 = cr restore - b SchExitInterrupt - - - - ###### ### -# # #### # # ##### # #### ##### # ##### # ###### ###### # # # ##### ###### ##### ##### # # ##### ##### #### -# # # # # # # # # # # # # # # # # # # ## # # # # # # # # # # # # # -#### # ###### # # # # # # # # # # # ##### # # # # # ##### # # # # # # # # # #### -# # # # ##### # # # ##### # # # # # # # # # # # ##### ##### # # ##### # # -# # # # # # # # # # # # # # # # # # # ## # # # # # # # # # # # # -# # #### # # # # #### # # # # # ###### ###### ### # # # ###### # # # # #### # # #### - -; > r1 = kdp - -kcPrioritizeInterrupts ; OUTSIDE REFERER - lwz r9, KDP.PA_InterruptHandler(r1) - mtlr r9 - blr - - - -; Move registers from CB to EWA, and Thud. - - align kIntAlign - -kcThud - - stw r2, EWA.r2(r1) - stw r3, EWA.r3(r1) - stw r4, EWA.r4(r1) - stw r5, EWA.r5(r1) - - lwz r8, ContextBlock.r7(r6) - lwz r9, ContextBlock.r8(r6) - stw r8, EWA.r7(r1) - stw r9, EWA.r8(r1) - - lwz r8, ContextBlock.r9(r6) - lwz r9, ContextBlock.r10(r6) - stw r8, EWA.r9(r1) - stw r9, EWA.r10(r1) - - lwz r8, ContextBlock.r11(r6) - lwz r9, ContextBlock.r12(r6) - stw r8, EWA.r11(r1) - stw r9, EWA.r12(r1) - - lwz r8, ContextBlock.r13(r6) - stw r8, EWA.r13(r1) - - stmw r14, EWA.r14(r1) - - bl IntPanicIsland - - - -major_0x046d0 ; OUTSIDE REFERER - - bl LoadInterruptRegisters - - li r8, ecTrapInstr - b Exception - - - -### ####### # - # # # ##### # # # ##### ###### ##### # # ## # # # # ##### ###### ##### # # ## ##### ###### - # ## # # # # # # # # # ## # # # # # # # # # # # ## # # # # # - # # # # # ##### ## # ##### # # # # # # # # # # # # ##### # # # # # # # # ##### - # # # # # # ## # # ##### # # # ###### # ####### # # # ##### # # # ###### # # - # # ## # # # # # # # # # ## # # # # # # # # # # # ## # # # # -### # # # ####### # # # ###### # # # # # # ###### # # ###### # ###### # # # # # # # ###### - -; For when the alternate context is running? - - align kIntAlign - -IntExternalAlternate - - bl LoadInterruptRegisters - mtcrf 0x3f, r7 - bcl BO_IF_NOT, EWA.kFlagBlue, IntPanicIsland - li r8, ecNoException - b Exception - - - -### ###### - # # # ##### # # ##### #### #### ##### ## # # - # ## # # # # # # # # # # # # # # ## ## - # # # # # ###### # # # # # # # # # # ## # - # # # # # # ##### # # # ### ##### ###### # # - # # ## # # # # # # # # # # # # # # -### # # # # # # #### #### # # # # # # - - align kIntAlign - -IntProgram - - bl LoadInterruptRegisters - - lwz r8, KDP.LA_EmulatorKernelTrapTable(r1) - mtcr r11 ; UNUSUAL to have SRR1 in condition register - xor r8, r10, r8 - bc BO_IF_NOT, 14, @not_trap - - - ; Program interrupt caused by a trap instruction - - - ; From the table of twis in the emulator code image? Then return will be to LR. - - cmplwi cr0, r8, NanoKernelCallTable.ReturnFromException - cmplwi cr1, r8, NanoKernelCallTable.MPDispatch - beq cr0, @emutrap_0_return_from_exception - beq cr1, @emutrap_8_mpdispatch - cmplwi cr0, r8, NanoKernelCallTable.VMDispatch - cmplwi cr1, r8, NanoKernelCallTable.Size - beq cr0, @emutrap_3_vmdispatch - blt cr1, @emutrap_other - - - ; Not from the emulator image? Return will be to next instruction, - ; and we will read the trap instruction from memory - - ; If !MSR[IR], turn on MSR[DR] for just a moment - bc BO_IF_NOT, 26, @_IntProgram_0x58 - stw r14, ContextBlock.r14(r6) - mfsprg r14, 3 - addi r8, r1, PSA.VecBasePIH - mfmsr r9 - mtsprg 3, r8 - _bset r8, r9, 27 ; turn on data paging (MSR[DR]) for just a sec - mtmsr r8 - isync -@_IntProgram_0x58 - - ; Get the offending instruction! - lwz r8, 0(r10) - - ; If !MSR[IR], restore MSR - bc BO_IF_NOT, 26, @_IntProgram_0x74 - isync - mtmsr r9 - isync - mtsprg 3, r14 - lwz r14, ContextBlock.r14(r6) -@_IntProgram_0x74 - - - ; Switch from SRR1-in-CR to Flags-in-CR - - mtcr r7 - - - ; Read the bottom half of the non-emu-image trap instruction, getting trapnum*8 in r8 - xoris r8, r8, 0xfff - cmplwi cr0, r8, NanoKernelCallTable.Size / 4 - cmplwi cr1, r8, NanoKernelCallTable.ReturnFromException / 4 - bge cr0, @trap_too_high - cmplwi cr7, r8, NanoKernelCallTable.MPDispatch / 4 - cmplwi cr0, r8, NanoKernelCallTable.VMDispatch / 4 - slwi r8, r8, 2 - beq cr1, @nonemu_return_from_exception - beq cr7, @nonemu_mpdispatch - beq cr0, @nonemu_vmdispatch - - ; Fall through to some hard truths - bc BO_IF, 16, @_IntProgram_0x150 - bc BO_IF, 8, @_IntProgram_0xac - bc BO_IF_NOT, 9, @_IntProgram_0x150 - -@nonemu_return_from_exception -@nonemu_vmdispatch -@_IntProgram_0xac - add r8, r8, r1 - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - -@nonemu_go - lwz r8, KDP.NanoKernelCallTable(r8) - mtlr r8 - addi r10, r10, 4 - rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 - blr - -@nonemu_mpdispatch - lwz r9, ContextBlock.r0(r6) - add r8, r8, r1 - cmpwi r9, -1 - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - bne @nonemu_go - - ; Non-emu MPDispatch trap with r0 == -1: muck around a bit? - addi r10, r10, 4 - rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 - mfsprg r8, 0 - rlwimi r13, r7, 8, 2, 2 - lwz r9, EWA.PA_CurTask(r8) - xoris r13, r13, 0x2000 - lwz r8, Task.SomeLabelField(r9) - stw r8, ContextBlock.r0(r6) - b IntReturn - - -@emutrap_other -@_IntProgram_0x110 - mtcr r7 - bc BO_IF, 16, @_IntProgram_0x150 - bc BO_IF, 8, @_IntProgram_0x120 - bc BO_IF_NOT, 9, @_IntProgram_0x150 - -@emutrap_0_return_from_exception -@emutrap_8_mpdispatch -@emutrap_3_vmdispatch -@_IntProgram_0x120 - add r8, r8, r1 - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - lwz r10, KDP.NanoKernelCallTable(r8) - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts(r8) - mtlr r10 - mr r10, r12 ; return to whatever the emulator left in the PPC link register - rlwimi r7, r7, 27, 26, 26 - blr - - - ; Program interrupt not caused by a trap instruction: consult SRR1 bits 11-13 - -@not_trap - bc BO_IF+1, 12, FDPEmulateInstruction ; illegal instruction exception - bc BO_IF, 13, FDPEmulateInstruction ; privileged instruction exception - bc BO_IF, 11, @floating_point_exception ; floating point exception - -@trap_too_high -@_IntProgram_0x150 - rlwinm r8, r11, 17, 28, 29 ; whoa - addi r8, r8, 0x4b3 - rlwnm r8, r8, r8, 28, 31 - b Exception - -@floating_point_exception - li r8, ecFloatException - - bc BO_IF, 15, Exception ; if SRR0 points to subsequent instr - addi r10, r10, 4 ; if SRR0 points to offending instr - rlwimi r7, r7, 27, 26, 26 ; copy EWA.kFlagBE into EWA.kFlag26 - b Exception - - - - align kIntAlign - -IntExternalSystem - - bl LoadInterruptRegisters - - - ; Sanity check - - rlwinm. r9, r11, 0, MSR_EEbit, MSR_EEbit - beq MaskedInterruptTaken - - - ; How many CPUs? - - lwz r9, EWA.CPUBase + CPU.LLL + LLL.Freeform(r8) - lwz r9, CoherenceGroup.CpuCount(r9) - cmpwi r9, 2 - - - ; Uniprocessor machine: go straight to PIH - - blt kcPrioritizeInterrupts - - - ; Check with the CPU plugin whether this is an interprocessor interrupt - ; (i.e. an alert to flag a scheduler evaluation) - - bl SchSaveStartingAtR14 - - li r9, kSIGP9 - stw r9, EWA.SIGPSelector(r8) - li r8, 1 ; args are in EWA - bl SIGP - bl SchRestoreStartingAtR14 - - cmpwi cr0, r8, -29278 ; real external interrupt - cmpwi cr1, r8, -29277 ; ignore - cmpwi cr2, r8, -29279 ; interprocessor interrupt! - ; else: real external interrupt - - beq cr0, kcPrioritizeInterrupts - beq cr1, IntReturn - bne cr2, kcPrioritizeInterrupts - - mfsprg r9, 0 ; "alert" => run scheduler evaluation - li r8, 1 - stb r8, EWA.SchEvalFlag(r9) - b IntReturn ; goes to SchReturn - - - - ##### ### ##### ###### -# # # # # # # -# # # # # - ##### # # #### ###### - # # # # # -# # # # # # - ##### ### ##### # - -; "SIGnal Plugin": Call the CPU plugin PEF bundle synchronously. -; (blue address space but in supervisor mode without interrupts) - -; ARG: - -; if r8 == 0, i.e. userspace MPCpuPlugin call: -; r3 => routine selector -; executing CPU index => r3 -; r4-10 => r4-10 - -; if r8 != 0, i.e. internal NanoKernel call: -; EWA.SIGPSelector => routine selector -; executing CPU index => r3 -; PlugCallR4-10 => r4-10 - -; For most NK SIGPs, r4 contains the index of the CPU being operated on - - align 5 - -SIGP - - mfsprg r23, 0 - mtcr r7 - - ; r20 = offset into CPU plugin dispatch table = routine number * 4 - ; - lwz r16, EWA.PA_CurAddressSpace(r23) - slwi r20, r3, 2 - stw r16, EWA.SIGPSpacOnResume(r23) - bc BO_IF, EWA.kFlagSIGP, IntReturnFromSIGP ; not sure about this - cmpwi cr2, r8, 0 - lwz r18, EWA.SIGPSelector(r23) - beq cr2, @args_in_registers - slwi r20, r18, 2 -@args_in_registers - - ; Check that a CPU plugin is installed and that the - ; plugin dispatch table includes this command number. - lwz r22, EWA.CPUBase + CPU.LLL + LLL.Freeform(r23) - li r8, -0x7266 - lwz r17, CoherenceGroup.PA_CpuPluginDesc(r22) - lwz r16, CoherenceGroup.CpuPluginSelectorCount(r22) - mr. r17, r17 - beqlr - slwi r16, r16, 2 - li r8, -0x7267 - cmplw r20, r16 - bgelr - - ; Save some registers in advance of this unusual "upcall". - stw r10, EWA.SIGPSavedR10(r23) - stw r11, EWA.SIGPSavedR11(r23) - stw r12, EWA.SIGPSavedR12(r23) - stw r13, EWA.SIGPSavedR13(r23) - mfxer r16 - mfctr r17 - stw r16, EWA.SIGPSavedXER(r23) - mflr r16 - stw r17, EWA.SIGPSavedCTR(r23) - stw r16, EWA.SIGPSavedLR(r23) ; obviously this is getting revisited somewhere - stw r6, EWA.SIGPSavedR6(r23) - stw r7, EWA.SIGPSavedR7(r23) - - ; Change to the CPU plugin's preferred address space. - lwz r9, EWA.PA_CurAddressSpace(r23) - lwz r8, CoherenceGroup.CpuPluginSpacePtr(r22) - cmpw r9, r8 - beq @noNeedToSwitchSpace - bl SchSwitchSpace -@noNeedToSwitchSpace - - ; Save user registers to ContextBlock (odd way to do this). - lwz r16, EWA.r1(r23) - lwz r17, EWA.r6(r23) - stw r16, ContextBlock.r1(r6) - stw r2, ContextBlock.r2(r6) - stw r3, ContextBlock.r3(r6) - stw r4, ContextBlock.r4(r6) - stw r5, ContextBlock.r5(r6) - stw r17, ContextBlock.r6(r6) - - ; Return address for CPU plugin code (=> twi 31, r31, 0 => kcReturnFromException) - lwz r17, KDP.LA_EmulatorKernelTrapTable + NanoKernelCallTable.ReturnFromException(r1) - - ; Need CPU index to look up the CPU plugin stack pointer in a table - lhz r16, EWA.CPUIndex(r23) - - ; MSR for CPU plugin with EE (external ints) and PR (problem state) switched off - lwz r19, PSA.UserModeMSR(r1) - slwi r16, r16, 2 - rlwinm r19, r19, 0, 18, 15 - - ; SRR0 (=> program counter) = TOC[routine_idx][first long] - ; r1 (stack ptr) = stackPtrs[cpu_idx] - ; r2 (RTOC) = TOC[routine_idx][second long] - lwz r8, CoherenceGroup.PA_CpuPluginTOC(r22) - lwz r9, CoherenceGroup.PA_CpuPluginStackPtrs(r22) - lwzx r20, r8, r20 - lwz r18, 0(r20) - mtlr r17 - mtspr srr0, r18 - mtspr srr1, r19 - lwzx r1, r9, r16 - lwz r2, 4(r20) - - ; r3 (first arg) = CPU index - srwi r3, r16, 2 - - ; Flags |= 0x8000 - _bset r7, r7, EWA.kFlagSIGP - mr r16, r6 - stw r7, EWA.Flags(r23) - - ; Not sure where this ContextBlock comes from? - addi r6, r23, -0x318 - stw r6, EWA.PA_ContextBlock(r23) - - beq cr2, @args_in_registers_2 - -;args not in registers - lwz r4, EWA.SIGPCallR4(r23) - lwz r5, EWA.SIGPCallR5(r23) - lwz r6, EWA.SIGPCallR6(r23) - lwz r7, EWA.SIGPCallR7(r23) - lwz r8, EWA.SIGPCallR8(r23) - lwz r9, EWA.SIGPCallR9(r23) - lwz r10, EWA.SIGPCallR10(r23) - - ; Go. - rfi - -@args_in_registers_2 - lwz r6, ContextBlock.r6(r16) - lwz r7, ContextBlock.r7(r16) - lwz r8, ContextBlock.r8(r16) - lwz r9, ContextBlock.r9(r16) - lwz r10, ContextBlock.r10(r16) - - ; Go. - rfi - - - -major_0x04a20 - - mfsprg r23, 0 - lwz r6, -0x0014(r23) - lwz r7, -0x0010(r23) - lwz r1, -0x0004(r23) - mfspr r10, srr0 - mfspr r11, srr1 - - - -IntReturnFromSIGP - - mfsprg r23, 0 - lwz r7, EWA.SIGPSavedR7(r23) - andis. r8, r11, 0x0002 ; MSR bit 14?? - stw r7, -0x0010(r23) - bne @msr_14_set - li r3, -29285 -@msr_14_set - - ; Restore address space - lwz r8, EWA.SIGPSpacOnResume(r23) - lwz r9, EWA.PA_CurAddressSpace(r23) - cmpw r9, r8 - beq @no_switch_space - bl SchSwitchSpace -@no_switch_space - - lwz r10, EWA.SIGPSavedR10(r23) - lwz r11, EWA.SIGPSavedR11(r23) - lwz r12, EWA.SIGPSavedR12(r23) - lwz r13, EWA.SIGPSavedR13(r23) - lwz r8, EWA.SIGPSavedXER(r23) - lwz r9, EWA.SIGPSavedCTR(r23) - mtxer r8 - lwz r8, EWA.SIGPSavedLR(r23) - lwz r6, EWA.SIGPSavedR6(r23) - mtctr r9 - stw r6, EWA.PA_ContextBlock(r23) - mtlr r8 - mr r8, r3 - mr r9, r4 - lwz r16, ContextBlock.r1(r6) - lwz r2, ContextBlock.r2(r6) - lwz r3, ContextBlock.r3(r6) - lwz r4, ContextBlock.r4(r6) - lwz r5, ContextBlock.r5(r6) - lwz r17, ContextBlock.r6(r6) - stw r16, EWA.r1(r23) - stw r17, EWA.r6(r23) - - blr - - - -### ##### - # # # ##### # # # # #### #### ## # # - # ## # # # # # # # # # # # # - # # # # # ##### # #### # # # # # - # # # # # # # # # ###### # # - # # ## # # # # # # # # # # # # -### # # # ##### # #### #### # # ###### ###### - -; IntSyscall - -; Not fully sure about this one - -IntSyscall ; OUTSIDE REFERER - - ; Only r1 and LR have been saved, so these compares clobber cr0 - - cmpwi r0, -3 - bne @not_minus_3 - - ; sc -3: used by FDP to go back to supervisor mode after instruction emulation. - ; For security reasons, FDP goes into user mode when it emulates loads and stores. - ; This is how it goes back into supervisor mode afterwards. During instruction emulation - ; it has data paging on, but keeps instruction paging off. User Mode code never has instruction - ; paging disabled, so this is not a privilege escalation. - - ; unset MSR_PR bit - mfspr r1, srr1 - rlwinm. r0, r1, 26, 26, 27 ;move MSR_IR bit to sign bit (and a few others that don't matter) - _bclr r1, r1, 17 - blt @not_in_FDP ; only do if MSR_IR = 0 (MSR_IR is sign bit, so it is < 0 if it is true) - mtspr srr1, r1 - @not_in_FDP - - ; restore LR from SPRG2, r1 from SPRG1 - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - - rfi - -@not_minus_3 - cmpwi r0, -1 - mfsprg r1, 0 - bne @not_minus_1 - - ; sc -1: quick-test whether "this task" is blue (cr0.eq if not blue) - - lwz r0, EWA.Flags(r1) - mfsprg r1, 2 - rlwinm. r0, r0, 0, EWA.kFlagBlue, EWA.kFlagBlue - mtlr r1 - mfsprg r1, 1 - rfi - -@not_minus_1 - cmpwi r0, -2 - bne @not_any_special - - ; sc -2: more flag nonsense? - - lwz r0, EWA.Flags(r1) - lwz r1, -0x0008(r1) - rlwinm. r0, r0, 0, 10, 10 - lwz r0, 0x00ec(r1) - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - -@not_any_special - - ; Positive numbered syscalls are a fast path to MPDispatch (twi 31, r31, 8) - - bl LoadInterruptRegisters ; Save the usual suspects and get comfy - - lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts + 32(r1) - addi r9, r9, 1 - stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.NanoKernelCallCounts + 8*4(r1) - - ; Not sure what to make of these - _bset r11, r11, 14 - rlwimi r7, r7, 27, 26, 26 - - b kcMPDispatch - - - -### ####### - # # # ##### # ##### ## #### ###### - # ## # # # # # # # # # # - # # # # # # # # # # # ##### - # # # # # # ##### ###### # # - # # ## # # # # # # # # # -### # # # # # # # # #### ###### - - align kIntAlign - -IntTrace ; OUTSIDE REFERER - - bl LoadInterruptRegisters - - li r8, ecInstTrace - b Exception - - - -### ##### ### - # #### # # #### ##### ###### # # #### ###### ##### # # ## ##### ###### # # # ##### - # # # ## # # # # # # # # # # # # # # # # # # # ## # # - # # # # # # # # # ##### ##### # # ##### # # # # # # # ##### # # # # # - # # ### # # # # # ##### # # # # # # # ## # ###### ##### # # # # # # - # # # # ## # # # # # # # # # # # ## ## # # # # # # # ## # -### #### # # #### # # ###### ##### #### # # # # # # # # ###### ### # # # - - align kIntAlign - -IgnoreSoftwareInt ; OUTSIDE REFERER - mfspr r1, srr0 - addi r1, r1, 0x04 - mtspr srr0, r1 - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - dcb.b 32, 0 - - - - -# # ###### # # ### -# # ## # # ##### # ###### # # ###### ##### ###### ## ## #### # # # ##### #### ##### # # # ##### -# # # # ## # # # # # # # # # # # # # # # # # ## # # # # # # # # ## # # -####### # # # # # # # # ##### ###### ##### # # ##### # # # # # # # # # # # # # # # # # # # -# # ###### # # # # # # # # # ##### # # # # # # # # # # # # ##### # # # # # -# # # # # ## # # # # # # # # # # # # # # ## # # # # # # # # ## # -# # # # # # ##### ###### ###### # ###### # # # # # #### # # # # #### # # ### # # # - - align kIntAlign - -HandlePerfMonitorInt ; OUTSIDE REFERER - mfspr r1, srr1 - oris r1, r1, 0x200 - mtspr srr1, r1 - mfsprg r1, 2 - mtlr r1 - mfsprg r1, 1 - rfi - dcb.b 32, 0 - diff --git a/NanoKernel/NKMPCalls.s b/NanoKernel/NKMPCalls.s index d1efd4c..b50246c 100644 --- a/NanoKernel/NKMPCalls.s +++ b/NanoKernel/NKMPCalls.s @@ -20,13 +20,14 @@ ; printh ; prints ; printw +; NKExceptions +; IntReturn ; NKIndex ; DeleteID ; GetNextIDOfClass ; LookupID ; MakeID -; NKInterrupts -; IntReturn +; NKIntMisc ; SIGP ; NKPaging ; PagingL2PWithBATs @@ -64,7 +65,7 @@ ; RemovePageFromTLB ; VMSecondLastExportedFunc ; EXPORTS: -; BlockMPCall (=> NKInterrupts, NKSync) +; BlockMPCall (=> NKExceptions, NKSync) ; CommonMPCallReturnPath (=> NKAddressSpaces, NKSleep, NKTasks) ; MPCall_6_0x78 (=> NKTasks) ; ReleaseAndMPCallWasBad (=> NKAddressSpaces) @@ -83,7 +84,7 @@ ; ReturnParamErrFromMPCall (=> NKAddressSpaces, NKPrimaryIntHandlers, NKSleep) ; ReturnZeroFromMPCall (=> NKAddressSpaces, NKSleep, NKSync) ; ScrambleMPCall (=> NKSync) -; kcMPDispatch (=> NKInit, NKInterrupts) +; kcMPDispatch (=> NKInit, NKIntMisc) ; major_0x0b0cc (=> NKAddressSpaces) diff --git a/NanoKernel/NKPaging.s b/NanoKernel/NKPaging.s index e67aaf2..4aeade7 100644 --- a/NanoKernel/NKPaging.s +++ b/NanoKernel/NKPaging.s @@ -15,10 +15,10 @@ Local_Panic set * ; panic ; EXPORTS: ; PagingFlushTLB (=> NKInit, NKScheduler, NKSleep) -; PagingFunc1 (=> NKInit, NKInterrupts, NKThud, NKVMCalls) +; PagingFunc1 (=> NKInit, NKIntHandlers, NKThud, NKVMCalls) ; PagingFunc2 (=> NKInit) ; PagingFunc2AndAHalf (=> NKSleep) -; PagingL2PWithBATs (=> NKInterrupts, NKMPCalls, NKRTASCalls, NKSleep) +; PagingL2PWithBATs (=> NKIntHandlers, NKIntMisc, NKMPCalls, NKRTASCalls, NKSleep) ; PagingL2PWithoutBATs (=> NKInit, NKScreenConsole, NKThud) diff --git a/NanoKernel/NKPoolAllocator.s b/NanoKernel/NKPoolAllocator.s index 18053d9..94396b1 100644 --- a/NanoKernel/NKPoolAllocator.s +++ b/NanoKernel/NKPoolAllocator.s @@ -45,7 +45,7 @@ ; EXPORTS: ; ExtendPool (=> NKMPCalls) ; InitPool (=> NKInit) -; PoolAlloc (=> NKInterrupts, NKSync, NKTasks) +; PoolAlloc (=> NKExceptions, NKSync, NKTasks) ; PoolAllocClear (=> NKAddressSpaces, NKIndex, NKInit, NKMPCalls, NKSync, NKTasks, NKTimers, NKVMCalls) ; PoolFree (=> NKAddressSpaces, NKMPCalls, NKSync, NKTasks, NKTimers) diff --git a/NanoKernel/NKPowerCalls.s b/NanoKernel/NKPowerCalls.s index d3cddc3..a2dc64e 100644 --- a/NanoKernel/NKPowerCalls.s +++ b/NanoKernel/NKPowerCalls.s @@ -2,8 +2,9 @@ ; IMPORTS: ; NKCache ; FlushCaches -; NKInterrupts +; NKExceptions ; IntReturn +; NKIntMisc ; wordfill ; NKThud ; panic diff --git a/NanoKernel/NKPrimaryIntHandlers.s b/NanoKernel/NKPrimaryIntHandlers.s index c37510b..aa71754 100644 --- a/NanoKernel/NKPrimaryIntHandlers.s +++ b/NanoKernel/NKPrimaryIntHandlers.s @@ -1,9 +1,9 @@ ; AUTO-GENERATED SYMBOL LIST ; IMPORTS: +; NKExceptions +; IntReturn ; NKIndex ; LookupID -; NKInterrupts -; IntReturn ; NKMPCalls ; ReturnMPCallOOM ; ReturnParamErrFromMPCall diff --git a/NanoKernel/NKRTASCalls.s b/NanoKernel/NKRTASCalls.s index 0e79c24..bead1a0 100644 --- a/NanoKernel/NKRTASCalls.s +++ b/NanoKernel/NKRTASCalls.s @@ -1,8 +1,9 @@ ; AUTO-GENERATED SYMBOL LIST ; IMPORTS: -; NKInterrupts -; IntHandleSpecialFPException +; NKExceptions ; IntReturn +; NKFloatInts +; IntHandleSpecialFPException ; bugger_around_with_floats ; NKPaging ; PagingL2PWithBATs diff --git a/NanoKernel/NKScheduler.s b/NanoKernel/NKScheduler.s index 211c3f3..e84adcc 100644 --- a/NanoKernel/NKScheduler.s +++ b/NanoKernel/NKScheduler.s @@ -3,7 +3,7 @@ ; NKConsoleLog ; printh ; printw -; NKInterrupts +; NKIntMisc ; SIGP ; NKPaging ; PagingFlushTLB @@ -17,27 +17,27 @@ ; TimebaseTicksPerPeriod ; EXPORTS: ; CalculateTimeslice (=> NKInit, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers) -; FlagSchEval (=> NKInit, NKInterrupts, NKMPCalls, NKTasks) +; FlagSchEval (=> NKExceptions, NKInit, NKMPCalls, NKTasks) ; FlagSchEvaluationIfTaskRequires (=> NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers) ; NewCpuEntryPoint (=> NKMPCalls) -; Restore_v0_v31 (=> NKInterrupts) +; Restore_v0_v31 (=> NKIntMisc) ; Save_f0_f31 (=> NKSleep) -; Save_v0_v31 (=> NKInterrupts, NKMPCalls, NKSleep) -; SchEval (=> NKInterrupts, NKMPCalls) -; SchExitInterrupt (=> NKInterrupts) -; SchFiddlePriorityShifty (=> NKInterrupts) +; Save_v0_v31 (=> NKExceptions, NKMPCalls, NKSleep) +; SchEval (=> NKExceptions, NKMPCalls) +; SchExitInterrupt (=> NKIntMisc) +; SchFiddlePriorityShifty (=> NKIntHandlers) ; SchIdleTask (=> NKInit, NKMPCalls) ; SchIdleTaskStopper (=> NKMPCalls) ; SchInit (=> NKInit) ; SchRdyTaskLater (=> NKMPCalls, NKPrimaryIntHandlers, NKSync) -; SchRdyTaskNow (=> NKInit, NKInterrupts, NKMPCalls, NKSync, NKTasks, NKTimers) -; SchRestoreStartingAtR14 (=> NKInit, NKInterrupts, NKMPCalls, NKPrimaryIntHandlers, NKVMCalls) +; SchRdyTaskNow (=> NKExceptions, NKInit, NKMPCalls, NKSync, NKTasks, NKTimers) +; SchRestoreStartingAtR14 (=> NKExceptions, NKInit, NKIntHandlers, NKIntMisc, NKMPCalls, NKPrimaryIntHandlers, NKVMCalls) ; SchRestoreStartingAtR20 (=> NKPrimaryIntHandlers) -; SchReturn (=> NKInterrupts) -; SchSaveStartingAtR14 (=> NKInterrupts, NKMPCalls, NKVMCalls) +; SchReturn (=> NKExceptions) +; SchSaveStartingAtR14 (=> NKExceptions, NKIntHandlers, NKIntMisc, NKMPCalls, NKVMCalls) ; SchSaveStartingAtR20 (=> NKPrimaryIntHandlers) -; SchSwitchSpace (=> NKInit, NKInterrupts, NKSleep) -; SchTaskUnrdy (=> NKInterrupts, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers) +; SchSwitchSpace (=> NKInit, NKIntMisc, NKSleep) +; SchTaskUnrdy (=> NKExceptions, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers) ; clear_cr0_lt (=> NKTimers) ; major_0x149d4 (=> NKTimers) diff --git a/NanoKernel/NKSleep.s b/NanoKernel/NKSleep.s index 762d940..3b1a05d 100644 --- a/NanoKernel/NKSleep.s +++ b/NanoKernel/NKSleep.s @@ -1,6 +1,6 @@ ; AUTO-GENERATED SYMBOL LIST ; IMPORTS: -; NKInterrupts +; NKIntMisc ; SIGP ; NKMPCalls ; CommonMPCallReturnPath diff --git a/NanoKernel/NKSync.s b/NanoKernel/NKSync.s index b423675..d830a81 100644 --- a/NanoKernel/NKSync.s +++ b/NanoKernel/NKSync.s @@ -36,11 +36,11 @@ ; GetTime ; TimebaseTicksPerPeriod ; EXPORTS: -; CauseNotification (=> NKAddressSpaces, NKInterrupts, NKPrimaryIntHandlers) -; EnqueueMessage (=> NKInterrupts, NKTasks, NKTimers) +; CauseNotification (=> NKAddressSpaces, NKExceptions, NKIntMisc, NKPrimaryIntHandlers) +; EnqueueMessage (=> NKExceptions, NKTasks, NKTimers) ; SetEvent (=> NKAddressSpaces, NKTimers) ; SignalSemaphore (=> NKTimers) -; UnblockBlueIfCouldBePolling (=> NKInterrupts) +; UnblockBlueIfCouldBePolling (=> NKExceptions) ####### ## ## ######## ## ## ######## ###### diff --git a/NanoKernel/NKTasks.s b/NanoKernel/NKTasks.s index 8f07db2..4a2fef4 100644 --- a/NanoKernel/NKTasks.s +++ b/NanoKernel/NKTasks.s @@ -36,7 +36,7 @@ ; EXPORTS: ; CreateTask (=> NKInit, NKMPCalls) ; TasksFuncThatIsNotAMPCall (=> NKScheduler) -; ThrowTaskToDebugger (=> NKInterrupts) +; ThrowTaskToDebugger (=> NKExceptions) ; This file mostly provides MPCall implementations related to multitasking. diff --git a/NanoKernel/NKThud.s b/NanoKernel/NKThud.s index 2ebd61c..4d78f96 100644 --- a/NanoKernel/NKThud.s +++ b/NanoKernel/NKThud.s @@ -7,16 +7,16 @@ ; printh ; prints ; printw +; NKExceptions +; Exception ; NKIndex ; GetNextIDOfClass ; LookupID -; NKInterrupts -; Exception ; NKPaging ; PagingFunc1 ; PagingL2PWithoutBATs ; EXPORTS: -; panic (=> NKAddressSpaces, NKIndex, NKInit, NKInterrupts, NKMPCalls, NKPaging, NKPoolAllocator, NKPowerCalls, NKRTASCalls, NKScheduler, NKSleep, NKSync, NKTasks, NKTimers, NKTranslation, NKVMCalls) +; panic (=> NKAddressSpaces, NKIndex, NKInit, NKMPCalls, NKPaging, NKPoolAllocator, NKPowerCalls, NKRTASCalls, NKScheduler, NKSleep, NKSync, NKTasks, NKTimers, NKTranslation, NKVMCalls) ; panic_non_interactive (=> NKTimers) diff --git a/NanoKernel/NKTimers.s b/NanoKernel/NKTimers.s index 2b6d66c..96471db 100644 --- a/NanoKernel/NKTimers.s +++ b/NanoKernel/NKTimers.s @@ -34,7 +34,7 @@ ; SetTimesliceFromCurTime (=> NKScheduler) ; StartTimeslicing (=> NKInit) ; TimebaseTicksPerPeriod (=> NKScheduler, NKSync) -; TimerDispatch (=> NKInterrupts) +; TimerDispatch (=> NKIntHandlers) Local_Panic set * diff --git a/NanoKernel/NKTranslation.s b/NanoKernel/NKTranslation.s index 732d214..f7d992a 100644 --- a/NanoKernel/NKTranslation.s +++ b/NanoKernel/NKTranslation.s @@ -16,23 +16,26 @@ ; AUTO-GENERATED SYMBOL LIST ; IMPORTS: -; NKInterrupts +; NKExceptions ; Exception ; ExceptionMemRetried +; NKFloatInts ; FloatLoadJumpTable ; FloatSaveJumpTable -; IgnoreSoftwareInt +; NKIntHandlers ; LoadInterruptRegisters ; major_0x03324 ; major_0x03548 +; NKIntMisc +; IgnoreSoftwareInt ; NKThud ; panic ; EXPORTS: ; FDP (=> NKBuiltinInit, NKReplacementInit) -; FDPEmulateInstruction (=> NKInterrupts) -; FDP_003c (=> NKInterrupts) -; FDP_011c (=> NKInterrupts) -; FDP_0DA0 (=> NKInterrupts) +; FDPEmulateInstruction (=> NKIntMisc) +; FDP_003c (=> NKFloatInts) +; FDP_011c (=> NKExceptions) +; FDP_0DA0 (=> NKFloatInts, NKIntHandlers) ; FDP_1c40 (=> NKInit) ; ProbePerfMonitor (=> NKInit) diff --git a/NanoKernel/NKVMCalls.s b/NanoKernel/NKVMCalls.s index 64c50c5..1e49d23 100644 --- a/NanoKernel/NKVMCalls.s +++ b/NanoKernel/NKVMCalls.s @@ -10,7 +10,7 @@ ; SpaceGetPagePLE ; NKConsoleLog ; printw -; NKInterrupts +; NKExceptions ; IntReturn ; NKPaging ; PagingFunc1 diff --git a/NanoKernel/NanoKernel.s b/NanoKernel/NanoKernel.s index 0786996..7f3aa8d 100644 --- a/NanoKernel/NanoKernel.s +++ b/NanoKernel/NanoKernel.s @@ -11,8 +11,18 @@ NKTop include 'NKInit.s' + align 5 - include 'NKInterrupts.s' +IntPanicIsland + b Panic + include 'NKExceptions.s' + align 5 + include 'NKIntHandlers.s' + align 5 + include 'NKFloatInts.s' + align 6 + include 'NKIntMisc.s' + align 5 include 'NKPaging.s' align 5