powermac-rom/NanoKernel/NKMPCalls.s

2180 lines
41 KiB
ArmAsm

; Important note: If you want more than r3-r5, get them from ECB!!!
; Unimplemented MPCalls from MPLibrary:
; NKSetPrInfoPageSize 109
; NKSetPrInfoILockSizes 110
; NKSetPrInfoTransCache 111
; NKSetPrInfoL1Cache 112
; NKSetPrInfoL2Cache 113
; AUTO-GENERATED SYMBOL LIST
; IMPORTS:
; NKAddressSpaces
; SpaceL2PIgnoringBATs
; SpaceL2PUsingBATs
; NKConsoleLog
; printb
; printd
; printh
; prints
; printw
; NKIndex
; DeleteID
; GetNextIDOfClass
; LookupID
; MakeID
; NKInterrupts
; IntReturn
; SIGP
; NKPaging
; PagingL2PWithBATs
; NKPoolAllocator
; ExtendPool
; PoolAllocClear
; PoolFree
; NKScheduler
; CalculateTimeslice
; FlagSchEval
; FlagSchEvaluationIfTaskRequires
; NewCpuEntryPoint
; Save_v0_v31
; SchEval
; SchIdleTask
; SchIdleTaskStopper
; SchRdyTaskLater
; SchRdyTaskNow
; SchRestoreStartingAtR14
; SchSaveStartingAtR14
; SchTaskUnrdy
; NKScreenConsole
; ScreenConsole_redraw
; NKTasks
; CreateTask
; NKThud
; panic
; NKTimers
; DequeueTimer
; EnqueueTimer
; GetTime
; NKVMCalls
; EditPTEInHTAB
; GetPARPageInfo
; RemovePageFromTLB
; VMSecondLastExportedFunc
; EXPORTS:
; BlockMPCall (=> NKInterrupts, NKSync)
; CommonMPCallReturnPath (=> NKAddressSpaces, NKSleep, NKTasks)
; MPCall_6_0x78 (=> NKTasks)
; ReleaseAndMPCallWasBad (=> NKAddressSpaces)
; ReleaseAndReturnMPCall (=> NKAddressSpaces, NKSync, NKTasks)
; ReleaseAndReturnMPCallBlueBlocking (=> NKSync)
; ReleaseAndReturnMPCallInvalidIDErr (=> NKAddressSpaces, NKSync, NKTasks)
; ReleaseAndReturnMPCallOOM (=> NKAddressSpaces, NKSync, NKTasks)
; ReleaseAndReturnMPCallPrivilegedErr (=> NKAddressSpaces)
; ReleaseAndReturnMPCallTaskAborted (=> NKSync)
; ReleaseAndReturnParamErrFromMPCall (=> NKAddressSpaces, NKSync)
; ReleaseAndReturnZeroFromMPCall (=> NKAddressSpaces, NKSync, NKTasks)
; ReleaseAndScrambleMPCall (=> NKAddressSpaces, NKSync, NKTasks)
; ReleaseAndTimeoutMPCall (=> NKSync)
; ReturnMPCallInvalidIDErr (=> NKAddressSpaces, NKTasks)
; ReturnMPCallOOM (=> NKAddressSpaces, NKPrimaryIntHandlers, NKSleep, NKSync, NKTasks)
; ReturnParamErrFromMPCall (=> NKAddressSpaces, NKPrimaryIntHandlers, NKSleep)
; ReturnZeroFromMPCall (=> NKAddressSpaces, NKSleep, NKSync)
; ScrambleMPCall (=> NKSync)
; kcMPDispatch (=> NKInit, NKInterrupts)
; major_0x0b0cc (=> NKAddressSpaces)
;MPCall_Panic set MPCall_Panic
if &TYPE('NKDebugShim') != 'UNDEFINED'
MaxMPCallCount equ 300
else
MaxMPCallCount equ 134
endif
MACRO
DeclareMPCall &n, &code
@h
org MPCallTable + 4*&n
dc.l &code - NKTop - 4*&n
org @h
ENDM
; Creates a blank table without overflowing PPCAsm's default
; macro stack size :)
MACRO
CreateMPCallTbl &n
if &n >= 1
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 2
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 3
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 4
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 5
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 6
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 7
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 8
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 9
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 10
dc.l (MPCallBad - NKTop) - (* - MPCallTable)
endif
if &n >= 11
CreateMPCallTbl (&n) - 10
endif
ENDM
kcMPDispatch ; reached by `sc`, or `twi *, *, 8`
bl SchSaveStartingAtR14
lwz r8, EWA.r6(r8) ; clobbers our EWA pointer :(
lwz r14, KDP.PA_NanoKernelCode(r1) ; but r14...
lwz r15, ContextBlock.r0(r6) ; ...and r15 were saved
stw r8, ContextBlock.r6(r6) ; why move r6 from EWA to ContextBlock?
b MPCallTableEnd
MPCallTable
CreateMPCallTbl MaxMPCallCount
MPCallTableEnd
; Not sure where this counter table is?
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.MPDispatchCountTblPtr(r1)
rlwinm r17, r15, 2, 20, 29
cmplwi r16, 0
beq @no_count
lwzx r18, r16, r17
addi r18, r18, 1
stwx r18, r16, r17
@no_count
cmplwi r15, MaxMPCallCount
rlwimi r14, r15, 2, 21, 29
llabel r16, MPCallTable
lwzx r15, r16, r14
add r15, r15, r14
mtlr r15
bltlr
; Handler for out-of-range or unimplemented (debug)
; MPCalls.
MPCallBad ; OUTSIDE REFERER
li r3, -4
b CommonMPCallReturnPath
ReleaseAndMPCallWasBad ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
b MPCallBad
; > r1 = kdp
ReleaseAndReturnZeroFromMPCall ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
ReturnZeroFromMPCall ; OUTSIDE REFERER
li r3, 0x00
b CommonMPCallReturnPath
ReleaseAndScrambleMPCall ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
; I'd really live a name for this.
ScrambleMPCall ; OUTSIDE REFERER
mfspr r16, pvr
rlwinm. r16, r16, 0, 0, 14
beq @is_601
mftb r4
b @not_601
@is_601
mfspr r4, rtcl
@not_601
xori r16, r4, 0x1007
xoris r16, r16, 0x1950
stw r16, PSA.ScrambledMPCallTime(r1)
li r3, -29294
b CommonMPCallReturnPath
; dead code?
li r3, kMPDeletedErr
b CommonMPCallReturnPath
ReleaseAndTimeoutMPCall ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
li r3, kMPTimeOutErr
b CommonMPCallReturnPath
ReleaseAndReturnMPCallTaskAborted ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
li r3, kMPTaskAbortedErr
b CommonMPCallReturnPath
ReleaseAndReturnMPCallOOM ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
ReturnMPCallOOM ; OUTSIDE REFERER
li r3, kMPInsufficientResourcesErr
b CommonMPCallReturnPath
ReleaseAndReturnMPCallBlueBlocking ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
ReturnMPCallBlueBlocking ; OUTSIDE REFERER
li r3, kMPBlueBlockingErr
b CommonMPCallReturnPath
ReleaseAndReturnParamErrFromMPCall ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
ReturnParamErrFromMPCall ; OUTSIDE REFERER
li r3, -0x32
b CommonMPCallReturnPath
ReleaseAndReturnMPCallPrivilegedErr ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
li r3, kMPPrivilegedErr
b CommonMPCallReturnPath
ReleaseAndReturnMPCallInvalidIDErr ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
ReturnMPCallInvalidIDErr ; OUTSIDE REFERER
li r3, kMPInvalidIDErr
b CommonMPCallReturnPath
major_0x0b0cc ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
li r3, -0x725a
b CommonMPCallReturnPath
ReturnZeroFromMPCall_again ; OUTSIDE REFERER
li r3, 0x00
b CommonMPCallReturnPath
BlockMPCall ; OUTSIDE REFERER
crclr 10
b TrulyCommonMPCallReturnPath
ReleaseAndReturnMPCall ; OUTSIDE REFERER
_AssertAndRelease PSA.SchLock, scratch=r16
CommonMPCallReturnPath ; OUTSIDE REFERER
crset 10
TrulyCommonMPCallReturnPath ; OUTSIDE REFERER
mfsprg r8, 0
lwz r9, 0x0134(r6)
stw r9, 0x0018(r8)
bc BO_IF_NOT, 10, @block
;return immediately
bl SchRestoreStartingAtR14
b IntReturn
@block
b SchEval
; Called after MPLibrary creates a new structure
DeclareMPCall 0, MPCall_0
MPCall_0 ; OUTSIDE REFERER
andi. r16, r3, 0xfff
mr r30, r7
mr r29, r6
bne ReturnMPCallOOM
; Fail if this page is outside of the PAR
rlwinm. r4, r3, 20, 12, 31
lwz r9, KDP.VMLogicalPages(r1)
beq ReturnMPCallOOM
cmplw r4, r9
bge ReturnMPCallOOM
_Lock PSA.HTABLock, scratch1=r17, scratch2=r18
bl GetPARPageInfo
bge cr4, MPCall_0_0xd8
bgt cr5, MPCall_0_0xd8
bns cr7, MPCall_0_0xd8
bgt cr7, MPCall_0_0xd8
bltl cr5, RemovePageFromTLB
bgel cr5, VMSecondLastExportedFunc
ori r16, r16, 0x404
li r31, 0x03
rlwimi r9, r31, 0, 30, 31
bl EditPTEInHTAB
mr r7, r30
mr r6, r29
_AssertAndRelease PSA.HTABLock, scratch=r16
_Lock PSA.PoolLock, scratch1=r16, scratch2=r17
rlwinm r8, r9, 0, 0, 19
mr r9, r3
; r1 = kdp
; r8 = anywhere in new page (phys)
; r9 = page_virt
bl ExtendPool
_AssertAndRelease PSA.PoolLock, scratch=r16
b ReturnZeroFromMPCall
MPCall_0_0xd8
mr r7, r30
mr r6, r29
_AssertAndRelease PSA.HTABLock, scratch=r16
b ReturnMPCallOOM
; MPCall_1
DeclareMPCall 1, MPCall_1
MPCall_1 ; OUTSIDE REFERER
b ReturnZeroFromMPCall_again
; ARG MPCoherenceGroupID r3, CpuPluginPtr r4, CpuPluginSize r5, CpuPluginDesc r6
; RET OSStatus r3
DeclareMPCall 2, MPRegisterCpuPlugin
MPRegisterCpuPlugin
; _log 'MPRegisterCpuPlugin '
; mr r8, r3
; bl Printw
; mr r8, r4
; bl Printw
; mr r8, r5
; bl Printw
; mr r8, r6
; bl Printw
; _log '^n'
mfsprg r14, 0
lwz r15, EWA.PA_CurTask(r14)
lwz r16, ContextBlock.r6(r6)
; Check that address of CPU plugin is page-aligned,
; and that CPU plugin size if page-aligned and nonzero.
andi. r8, r4, 0xfff
bne ReturnMPCallOOM
andi. r8, r5, 0xfff
cmpwi cr1, r5, 0
bne ReturnMPCallOOM
beq cr1, ReturnMPCallOOM
_Lock PSA.SchLock, scratch1=r18, scratch2=r19
; r14 = coherence group ptr (motherpboard CGRP if not specified in first argument)
mr. r8, r3
bne @use_specified_cgrp
mfsprg r15, 0
lwz r14, EWA.CPUBase + CPU.LLL + LLL.Freeform(r15)
b @cgrp_done
@use_specified_cgrp
bl LookupID
cmpwi r9, CoherenceGroup.kIDClass
mr r14, r8
bne ReturnMPCallInvalidIDErr
@cgrp_done
; Fail if no CPU plugin descriptor is passed in fourth argument
cmpwi r16, 0
bne @no_table_ptr
stw r16, CoherenceGroup.PA_CpuPluginDesc(r14)
stw r16, CoherenceGroup.LA_CpuPluginDesc(r14)
b ReleaseAndReturnMPCallInvalidIDErr
@no_table_ptr
; Fail if CPU plugin descriptor lies within CPU plugin
add r17, r4, r5
cmplw r16, r4
cmplw cr1, r16, r17
blt ReleaseAndReturnMPCallOOM
bge cr1, ReleaseAndReturnMPCallOOM
; What the hell? Wouldn't this always fail?
lwz r19, CoherenceGroup.PA_CpuPluginDesc(r14)
mr. r19, r19
bne ReleaseAndReturnMPCallInvalidIDErr
; r18 = physical address of plugin (assumes page-aligned)
mr r27, r4
addi r29, r1, KDP.BATs + 0xa0
bl PagingL2PWithBATs
beq ReleaseAndReturnMPCallOOM
rlwinm r18, r31, 0, 0, 19
; r18 = physical address of descriptor (does not assume page-aligned)
mr r27, r16
mr r19, r16
addi r29, r1, KDP.BATs + 0xa0
bl PagingL2PWithBATs
beq ReleaseAndReturnMPCallOOM
rlwimi r19, r31, 0, 0, 19
; Populate the coherence group structure.
; Save (page-aligned) address of main plugin (second argument)
stw r4, CoherenceGroup.LA_CpuPlugin(r14)
stw r18, CoherenceGroup.PA_CpuPlugin(r14)
; Save size of main plugin (third argument)
stw r5, CoherenceGroup.CpuPluginSize(r14)
; Save (non-page-aligned) address of descriptor (fourth argument)
stw r16, CoherenceGroup.LA_CpuPluginDesc(r14)
stw r19, CoherenceGroup.PA_CpuPluginDesc(r14)
; Get physical ptr to table of stack pointers (one per CPU)
lwz r27, 0(r19)
addi r29, r1, KDP.BATs + 0xa0
bl PagingL2PWithBATs
beq ReleaseAndReturnMPCallOOM
rlwimi r27, r31, 0, 0, 19
stw r27, CoherenceGroup.PA_CpuPluginStackPtrs(r14)
mfsprg r16, 0
; The cpup should operate in the caller's address space
lwz r17, EWA.PA_CurAddressSpace(r16)
stw r17, CoherenceGroup.CpuPluginSpacePtr(r14)
; Get ptr to dispatch table at descriptor + 32
addi r16, r19, 0x20
stw r16, CoherenceGroup.PA_CpuPluginTOC(r14)
subi r16, r16, 4 ; prepare for loop below
; Get number of entries in the dispatch table
lwz r17, 0x1c(r19)
cmplwi r17, 64
stw r17, CoherenceGroup.CpuPluginSelectorCount(r14)
bgt ReleaseAndReturnMPCallOOM
; Convert those entries to physical addresses
@table_convert_loop
lwzu r27, 4(r16)
addi r29, r1, KDP.BATs + 0xa0
bl PagingL2PWithBATs
beq ReleaseAndReturnMPCallOOM
subi r17, r17, 1
rlwimi r27, r31, 0, 0, 19
cmpwi r17, 0
stw r27, 0(r16)
bgt @table_convert_loop
_log 'CPU plugin registered^n'
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
; Called by MPProcessors and MPProcessorsScheduled
; ARG bool r3 scheduled_only
; RET int r3
DeclareMPCall 3, MPProcessors
MPProcessors
mfsprg r15, 0
lwz r14, EWA.CPUBase + CPU.LLL + LLL.Freeform(r15)
mr. r8, r3
lwz r3, CoherenceGroup.CpuCount(r14)
beq CommonMPCallReturnPath
lwz r3, CoherenceGroup.ScheduledCpuCount(r14)
b CommonMPCallReturnPath
; ARG AddressSpaceID r3
; RET AddressSpaceID r3, ??? r4, ProcessStructID r5
DeclareMPCall 4, MPCreateProcess
MPCreateProcess
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr. r8, r3
bne @spac_id_supplied
lwz r3, PSA.SystemAddressSpaceID(r1)
mr r8, r3
@spac_id_supplied
bl LookupID
; r8 = something not sure what
; r9 = 0:inval, 1:proc, 2:task, 3:timer, 4:q, 5:sema, 6:cr, 7:cpu, 8:addrspc, 9:evtg, 10:cohg, 11:area, 12:not, 13:log
cmpwi r9, AddressSpace.kIDClass
mr r30, r8
bne ReleaseAndReturnMPCallInvalidIDErr
li r8, 0x20 ;Process.Size
bl PoolAllocClear
mr. r31, r8
beq ReleaseAndScrambleMPCall
li r9, Process.kIDClass
bl MakeID
cmpwi r8, 0x00
bne @did_not_fail
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@did_not_fail
stw r8, Process.ID(r31)
lisori r16, Process.kSignature
stw r16, Process.Signature(r31)
stw r3, Process.SystemAddressSpaceID(r31) ; NOT SYSTEM -- fix struct
stw r30, Process.SystemAddressSpacePtr(r31)
lwz r17, Process.AddressSpaceCount(r31)
addi r17, r17, 1
stw r17, Process.AddressSpaceCount(r31)
mr r5, r8
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 5, MPTerminateProcess
MPTerminateProcess
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, Process.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, 0x0008(r31)
rlwinm. r17, r16, 0, 30, 30
bne ReleaseAndReturnMPCallOOM
ori r16, r16, 0x02
stw r16, 0x0008(r31)
mr r8, r3
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
; ARG ProcessID r3
; RET OSStatus r3
DeclareMPCall 6, MPDeleteProcess
MPDeleteProcess
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Process.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, Process.Flags(r31)
lwz r17, Process.TaskCount(r31)
rlwinm. r8, r16, 0, Process.kFlag30, Process.kFlag30
cmpwi cr1, r17, 0
beq ReleaseAndReturnMPCallOOM
bne cr1, ReleaseAndReturnMPCallOOM
mr r8, r3
bl DeleteID
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
mr r8, r31
bl PoolFree
b ReturnZeroFromMPCall
MPCall_6_0x78 ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mfsprg r16, 0
rlwinm. r8, r7, 0, 10, 10
lwz r17, KDP.PA_ECB(r1)
lwz r31, EWA.PA_CurTask(r16)
beq MPCall_6_0xb4
lwz r8, ContextBlock.PriorityShifty(r17)
rlwinm r8, r8, 0, 24, 21
oris r8, r8, 0x8000
stw r8, ContextBlock.PriorityShifty(r17)
MPCall_6_0xb4
mr r8, r31
bl SchTaskUnrdy
li r16, Task.kNominalPriority
stb r16, Task.Priority(r31)
bl SchRdyTaskNow
mr r8, r31
bl FlagSchEvaluationIfTaskRequires
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
b CommonMPCallReturnPath
; Implements MPYield (null argument)
; Caller gets its priority set to nominal
; ARG TaskID r3 (null for MPYield)
; RET OSStatus r3
DeclareMPCall 13, MPYieldWithHint
MPYieldWithHint
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mfsprg r16, 0
rlwinm. r8, r7, 0, 10, 10
lwz r17, KDP.PA_ECB(r1)
lwz r31, EWA.PA_CurTask(r16)
beq @i_am_important ; not 68k mode?
clrlwi. r8, r3, 31
lwz r8, ContextBlock.PriorityShifty(r17)
rlwinm r8, r8, 0, 24, 21
oris r8, r8, 0x8000
stw r8, ContextBlock.PriorityShifty(r17)
beq @i_am_important ; MPYield call
; If this task is
lbz r16, Task.Priority(r31)
cmpwi r16, Task.kNominalPriority
bge @return
mr r8, r31
bl SchTaskUnrdy
li r16, Task.kNominalPriority
stb r16, Task.Priority(r31)
bl SchRdyTaskLater
b @return
@i_am_important
mr r8, r31
bl SchTaskUnrdy
li r16, Task.kNominalPriority
stb r16, Task.Priority(r31)
bl SchRdyTaskNow
@return
mr r8, r31
bl FlagSchEvaluationIfTaskRequires
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
b CommonMPCallReturnPath
; ARG AbsoluteTime r3/r4
; RET OSStatus r3
DeclareMPCall 33, MPDelayUntil
MPDelayUntil
rlwinm. r8, r7, 0, EWA.kFlagBlue, EWA.kFlagBlue
bne ReturnMPCallBlueBlocking
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
b _MPDelayUntilCommon
; This version is allowed while the blue task is running
; ARG AbsoluteTime r3/r4
; RET OSStatus r3
DeclareMPCall 55, MPDelayUntilSys
MPDelayUntilSys
rlwinm. r8, r7, 0, EWA.kFlagBlue, EWA.kFlagBlue
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.ExternalIntCount(r1)
beq _MPDelayUntilCommon
; Why the hell are we counting interrupts?
lwz r17, PSA.OtherSystemContextPtr(r1)
lwz r18, KDP.PA_ECB(r1)
cmpw r16, r17
stw r16, PSA.OtherSystemContextPtr(r1)
bne ReturnZeroFromMPCall
lwz r8, ContextBlock.PriorityShifty(r18)
rlwinm r8, r8, 0, 24, 21
oris r8, r8, 0x8000
stw r8, ContextBlock.PriorityShifty(r18)
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
lwz r16, PSA.BlueSpinningOn(r1)
cmpwi r16, -1
li r16, 0
bne _MPDelayUntilCommon
stw r16, PSA.BlueSpinningOn(r1)
b ReleaseAndReturnZeroFromMPCall
_MPDelayUntilCommon
mfsprg r16, 0
li r17, 1
lwz r31, EWA.PA_CurTask(r16)
addi r16, r31, Task.Timer
stb r17, Timer.Kind(r16)
; High bit is possibly suspect? Or a flag?
clrlwi r3, r3, 1
stw r3, Timer.Time(r16)
stw r4, Timer.Time+4(r16)
stw r31, Timer.ParentTaskPtr(r16)
mr r8, r16
bl EnqueueTimer
mr r8, r31
bl SchTaskUnrdy
addi r16, r1, PSA.DelayQueue
addi r17, r31, Timer.QueueLLL
stw r16, LLL.Freeform(r17)
InsertAsPrev r17, r16, scratch=r18
li r3, 0
b BlockMPCall
DeclareMPCall 34, MPCall_34
MPCall_34 ; OUTSIDE REFERER
mr r8, r3
mr r9, r4
; r1 = kdp
; r9 = kind
bl MakeID
cmpwi r8, 0x00
beq ScrambleMPCall
mr r5, r8
b ReturnZeroFromMPCall
DeclareMPCall 35, MPCall_35
MPCall_35 ; OUTSIDE REFERER
mr r8, r3
bl DeleteID
cmpwi r8, 0x01
beq ReturnZeroFromMPCall
b ReturnMPCallInvalidIDErr
DeclareMPCall 36, MPCall_36
MPCall_36 ; OUTSIDE REFERER
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, 0 ; invalid
mr r4, r9
mr r5, r8
bne ReturnZeroFromMPCall
b ReturnMPCallInvalidIDErr
; Replace the provided process/coherence/console ID with
; the "next" one. IDs were opaque but were only longs.
; Wrapped by MPGetNext*ID, which indirects the opaque ID
; structure.
; From MP docs: A coherence group is the set of processors
; and other bus controllers that have cache-coherent
; access to memory. Mac OS 9 defines only one coherence
; group, which is all the processors that can access
; internal memory (RAM). Other coherence groups are
; possible; for example, a PCI card with its own memory
; and processors can comprise a coherence group.
; > r3 = kind (process=1,coherence=10,console=13)
; > r4 = prev_id
; < r3 = MP result code
; < r4 = next_id
DeclareMPCall 37, MPGetNextID
MPGetNextID
mr r8, r4
mr r9, r3
bl GetNextIDOfClass
cmpwi r8, 0x00
mr r4, r8
bne ReturnZeroFromMPCall
b ReturnMPCallInvalidIDErr
; Replace the provided address
; space/task/queue/semaphore/critical
; region/timer/event/notification ID with the "next" one.
; IDs were opaque but were only longs. Wrapped by
; MPGetNext*ID, which indirects the opaque ID structure.
; Differs from KCGetNextID because it deals in
; objects owned by a particular process.
; Useful info about some poorly understood structures
; ARG ProcessID r3, IDClass r4, ID r5
; RET MPErr r3, IDClass r4, ID r5
DeclareMPCall 116, MPGetNextIDOwnedByProcess
MPGetNextIDOwnedByProcess
; Confirm that owner ID in r3 is a Process
mr r8, r3
bl LookupID
cmpwi r9, Process.kIDClass
bne ReturnMPCallInvalidIDErr
; Loop over IDs (and resolve them) until one is owned by the Process
@try_another_id
mr r8, r5
mr r9, r4
; ARG ID r8, IDClass r9
bl GetNextIDOfClass
; RET ID r8
mr. r5, r8
beq ReturnMPCallInvalidIDErr
; ARG ID r8
bl LookupID
; RET Ptr r8, IDClass r9
cmpwi r4, Task.kIDClass
cmpwi cr1, r4, Timer.kIDClass
beq @task
beq cr1, @timer
cmpwi r4, Queue.kIDClass
cmpwi cr1, r4, Semaphore.kIDClass
beq @queue
beq cr1, @semaphore
cmpwi r4, CriticalRegion.kIDClass
cmpwi cr1, r4, AddressSpace.kIDClass
beq @critical_region
beq cr1, @address_space
cmpwi r4, EventGroup.kIDClass
cmpwi cr1, r4, Area.kIDClass
beq @event_group
beq cr1, @area
cmpwi r4, Notification.kIDClass
cmpwi cr1, r4, ConsoleLog.kIDClass
beq @notification
beq cr1, @console_log
b ReturnParamErrFromMPCall
@task
lwz r17, Task.Flags(r8)
lwz r9, Task.ProcessID(r8)
rlwinm. r17, r17, 0, 15, 15
beq @not_owned_by_blue_process
lwz r9, PSA.blueProcessPtr(r1)
lwz r9, Task.ID(r9)
@not_owned_by_blue_process
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@timer
lwz r9, Timer.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@queue
lwz r9, Queue.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@semaphore
lwz r9, Semaphore.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@critical_region
lwz r9, CriticalRegion.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@address_space
lwz r9, AddressSpace.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@event_group
lwz r9, EventGroup.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@area
lwz r9, Area.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@notification
lwz r9, Notification.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
@console_log
lwz r9, ConsoleLog.ProcessID(r8)
cmpw r9, r3
bne @try_another_id
b ReturnZeroFromMPCall
DeclareMPCall 38, MPCall_38
MPCall_38 ; OUTSIDE REFERER
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, Process.kIDClass
bne ReturnMPCallInvalidIDErr
mr r31, r8
MPCall_38_0x14
mr r8, r4
li r9, 0x02
bl GetNextIDOfClass
cmpwi r8, 0x00
beq ReturnMPCallInvalidIDErr
mr r4, r8
; r8 = id
bl LookupID
; r8 = something not sure what
; r9 = 0:inval, 1:proc, 2:task, 3:timer, 4:q, 5:sema, 6:cr, 7:cpu, 8:addrspc, 9:evtg, 10:cohg, 11:area, 12:not, 13:log
lwz r17, 0x0064(r8)
lwz r16, 0x0060(r8)
rlwinm. r17, r17, 0, 15, 15
beq MPCall_38_0x48
lwz r16, PSA.blueProcessPtr(r1)
lwz r16, 0x0000(r16)
MPCall_38_0x48
cmpw r16, r3
beq ReturnZeroFromMPCall
b MPCall_38_0x14
DeclareMPCall 62, MPGetNextCpuID
MPGetNextCpuID
mr. r8, r3
bne @r3_nonzero
;r3 zero
mfsprg r15, 0
lwz r31, EWA.CPUBase + CPU.LLL + LLL.Freeform(r15)
lwz r3, 0(r31)
b @endif
@r3_nonzero
bl LookupID
cmpwi r9, CoherenceGroup.kIDClass
bne ReturnMPCallInvalidIDErr
@endif
@loop
mr r8, r4
li r9, CPU.kIDClass
bl GetNextIDOfClass
cmpwi r8, 0
beq ReturnMPCallInvalidIDErr
mr r4, r8
bl LookupID
lwz r16, CPU.LLL + LLL.Freeform(r8)
lwz r17, CPU.ID(r16)
cmpw r17, r3
bne @loop
b ReturnZeroFromMPCall
DeclareMPCall 42, MPCreateProcessor
MPCreateProcessor
mr. r8, r3
bne @cgrpProvided
mfsprg r15, 0
lwz r30, EWA.CPUBase + CPU.LLL + LLL.Freeform(r15)
b @gotCgrp
@cgrpProvided
bl LookupID
cmpwi r9, CoherenceGroup.kIDClass
mr r30, r8
bne ReturnMPCallInvalidIDErr
@gotCgrp
li r8, CPU.Size
bl PoolAllocClear
mr. r31, r8
beq ScrambleMPCall
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, CPU.kIDClass
bl MakeID
cmpwi r8, 0
bne+ @success
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@success
stw r8, CPU.ID(r31)
lisori r16, CPU.kSignature
stw r8, ContextBlock.r6(r6) ; return ID in r6
stw r16, CPU.Signature(r31)
lwz r17, 0x0020(r30)
addi r17, r17, 0x01
stw r17, 0x0020(r30)
addi r16, r31, 0x08
stw r30, 0x0000(r16)
InsertAsPrev r16, r30, scratch=r17
lisori r8, 11
lisori r8, 6
stw r8, CPU.Flags(r31)
addi r30, r31, CPU.EWABase
addi r8, r1, PSA.Base
stw r8, EWA.PA_PSA - EWA.Base(r30)
stw r1, EWA.PA_KDP - EWA.Base(r30)
li r8, 0
stw r8, EWA.PA_CurTask - EWA.Base(r30)
; Matches code in Init.s quite closely
li r8, -0x01
sth r4, 0x020a(r30)
stb r8, 0x0209(r30) ; interesting...
lwz r8, EWA.PA_IRP(r1)
stw r8, EWA.PA_IRP - EWA.Base(r30)
lisori r8, 'time'
stw r8, EWA.TimeList - EWA.Base + LLL.Signature(r30)
li r8, 0x04
stb r8, 0x0014(r30)
li r8, 0x01
stb r8, 0x0016(r30)
li r8, 0x00
stb r8, 0x0017(r30)
lisori r8, 0x7fffffff
stw r8, 0x0038(r30)
oris r8, r8, 0xffff
stw r8, 0x003c(r30)
b ReleaseAndReturnZeroFromMPCall
; Simple MPLibrary wrapper
DeclareMPCall 43, MPDeleteProcessor
MPDeleteProcessor
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, CPU.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lwz r16, CPU.Flags(r31)
lisori r17, 9
and. r17, r17, r16
bne ReleaseAndReturnMPCallOOM
mfsprg r15, 0
li r16, kResetProcessor
stw r16, EWA.SIGPSelector(r15)
lhz r16, CPU.EWA + EWA.CPUIndex(r31)
stw r16, EWA.SIGPCallR4(r15)
li r8, 2 ; args in EWA
bl SIGP
lwz r17, 0x0008(r31)
addi r16, r31, 0x08
lwz r18, 0x0020(r17)
addi r18, r18, -0x01
stw r18, 0x0020(r17)
RemoveFromList r16, scratch1=r17, scratch2=r18
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 44, MPStartScheduling
; ARG CpuID r3
MPStartScheduling
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, CPU.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r30, r8
lwz r16, CPU.Flags(r30)
rlwinm. r8, r16, 0, 28, 28
bne ReleaseAndReturnZeroFromMPCall
mfsprg r15, 0
li r16, kResetProcessor
stw r16, EWA.SIGPSelector(r15)
lhz r16, CPU.EWA + EWA.CPUIndex(r30)
stw r16, EWA.SIGPCallR4(r15)
; Put the boots in?
_log 'SIGP kResetProcessor^n'
li r8, 2 ; args in EWA
bl SIGP
cmpwi r8, -0x7264
cmpwi cr1, r8, 0
beq ReleaseAndReturnMPCallOOM
bne cr1, ReleaseAndReturnMPCallOOM
; Every CPU gets an idle task
_log 'Creating idle task^n'
mr r31, r7
rlwinm r7, r7, 0, 13, 11
lwz r8, PSA.blueProcessPtr(r1)
; ARG Flags r7, Process *r8
bl CreateTask
; RET Task *r8
mr r7, r31
mr. r31, r8
beq ReleaseAndScrambleMPCall
stw r31, CPU.IdleTaskPtr(r30)
lisori r8, 'idle'
stw r8, Task.Name(r31)
lisori r8, 0x80040 ; (Z>>Task.kFlag12)| (Z>>Task.kFlag25)
stw r8, Task.Flags(r31)
li r8, 1
stw r8, Task.Weight(r31)
li r8, Task.kIdlePriority
stb r8, Task.Priority(r31)
; whoa -- cpu structs arent this big?
lhz r8, CPU.EWA + EWA.CPUIndex(r30)
sth r8, Task.CPUIndex(r31)
lwz r8, Task.ContextBlock + ContextBlock.Flags(r31)
_bset r8, r8, 9
stw r8, Task.ContextBlock + ContextBlock.Flags(r31)
lwz r8, KDP.PA_NanoKernelCode(r1)
llabel r26, SchIdleTask
add r8, r8, r26
stw r8, Task.ContextBlock + ContextBlock.CodePtr(r31)
; better compare this with init code idle task
lwz r8, Task.ContextBlock + ContextBlock.MSR(r31)
andi. r8, r8, 0xbfcf
stw r8, Task.ContextBlock + ContextBlock.MSR(r31)
_AssertAndRelease PSA.SchLock, scratch=r16
mfsprg r15, 0
li r16, kSynchClock
stw r16, EWA.SIGPSelector(r15)
lhz r16, CPU.EWA + EWA.CPUIndex(r30)
stw r16, EWA.SIGPCallR4(r15)
MPCall_44_0x15c
_log 'SIGP kSynchClock^n'
li r8, 2 ; args in EWA
bl SIGP
cmpwi r8, -0x7264
cmpwi cr1, r8, 0x00
beq MPCall_44_0x15c
bne cr1, MPCall_Panic
mfsprg r15, 0
li r16, kStartProcessor
stw r16, EWA.SIGPSelector(r15)
lhz r16, CPU.EWA + EWA.CPUIndex(r30)
stw r16, EWA.SIGPCallR4(r15)
lwz r16, KDP.PA_NanoKernelCode(r1)
llabel r17, NewCpuEntryPoint
add r16, r16, r17
stw r16, EWA.SIGPCallR5(r15)
stw r30, EWA.SIGPCallR6(r15) ; cpu struct
@retry
_log 'SIGP kStartProcessor^n'
li r8, 4 ; args in EWA
bl SIGP
cmpwi r8, -0x7264
cmpwi cr1, r8, 0
beq @retry
bne cr1, MPCall_Panic
_log 'Processor scheduled^n'
b ReturnZeroFromMPCall
DeclareMPCall 45, MPStopScheduling
MPStopScheduling
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, CPU.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r30, r8
lwz r16, CPU.Flags(r30)
rlwinm. r8, r16, 0, CPU.kFlagScheduled, CPU.kFlagScheduled
beq ReleaseAndReturnZeroFromMPCall
lwz r31, CPU.IdleTaskPtr(r30)
rlwinm. r8, r16, 0, CPU.kFlag31, CPU.kFlag31
bne ReleaseAndReturnMPCallOOM
lbz r17, Task.Priority(r31)
cmpwi r17, Task.kCriticalPriority
beq @running_critical_task
lwz r17, Task.Flags(r31)
_bset r17, r17, Task.kFlag8
stw r17, Task.Flags(r31)
mr r8, r31
bl SchTaskUnrdy
li r17, Task.kCriticalPriority
stb r17, Task.Priority(r31)
mr r8, r31
bl SchRdyTaskLater
bl CalculateTimeslice
mr r8, r31
bl FlagSchEval
lwz r8, KDP.PA_NanoKernelCode(r1)
llabel r9, SchIdleTaskStopper
add r8, r8, r9
stw r8, Task.ContextBlock + ContextBlock.CodePtr(r31)
@running_critical_task
_AssertAndRelease PSA.SchLock + Lock.Count, scratch=r16
b MPCall_6_0x78
; Directly wrapped by MPLibrary
; ARG selector r3, arbitrary args r4...
; RET arbitrary
DeclareMPCall 46, MPCpuPlugin
MPCpuPlugin
; Arguments in registers
li r8, 0
; Hopefully returns via kcSchExitInterrupt? Geez...
bl SIGP
mr r3, r8
mr r4, r9 ; r4 not accessible calling MPLibrary func from C
b CommonMPCallReturnPath
DeclareMPCall 47, MPCall_47
MPCall_47 ; OUTSIDE REFERER
rlwinm. r8, r7, 0, EWA.kFlagVec, EWA.kFlagVec
lwz r15, 0x00d8(r6)
beq ReturnMPCallOOM
cmpwi r15, 0x00
mr r16, r2
beq ReturnMPCallOOM
mr r17, r3
mr r18, r4
mr r19, r5
bl Save_v0_v31
mr r2, r16
mr r3, r17
mr r4, r18
mr r5, r19
b ReturnZeroFromMPCall
; MPCall_48_Bad
DeclareMPCall 48, MPCall_48_Bad
MPCall_48_Bad ; OUTSIDE REFERER
b MPCallBad
; MPDebugPutString
DeclareMPCall 96, MPDebugPutString
MPDebugPutString ; OUTSIDE REFERER
rlwinm. r9, r11, 0, 27, 27
mr r8, r3
beq MPDebugPutString_0x1c
li r9, 0x00
bl SpaceL2PUsingBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17
beq MPDebugPutString_0x24
rlwimi r8, r17, 0, 0, 19
MPDebugPutString_0x1c
bl PrintS
b ReturnZeroFromMPCall
MPDebugPutString_0x24
_log 'NKxprintf (V->P translation error)^n'
b ReturnMPCallOOM
; ARG long r3, int r4 size (1:byte, 2:half, else:word)
DeclareMPCall 97, MPDebugPutHex
MPDebugPutHex
mr r8, r3
cmpwi r4, 1
cmpwi cr1, r4, 2
beq @byte
beq cr1, @half
bl Printw
b CommonMPCallReturnPath
@half
bl Printh
b CommonMPCallReturnPath
@byte
bl Printb
b CommonMPCallReturnPath
DeclareMPCall 124, MPDebugPutDec
MPDebugPutDec
mr r8, r3
bl Printd
b CommonMPCallReturnPath
DeclareMPCall 99, MPSetBlueProcessID
MPSetBlueProcessID
mfsprg r16, 0
rlwinm. r8, r7, 0, EWA.kFlagBlue, EWA.kFlagBlue
lwz r31, EWA.PA_CurTask(r16)
beq ReturnMPCallOOM ; not in blue -> fail
mr r8, r3
bl LookupID
cmpwi r9, Process.kIDClass
bne ReturnMPCallInvalidIDErr
stw r3, Task.ProcessID(r31)
stw r4, Task.SomeLabelField(r31)
b ReturnZeroFromMPCall
DeclareMPCall 104, MPRegisterThermalHandler
MPRegisterThermalHandler
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr. r8, r3
beq @is_zero
bl LookupID
cmpwi r9, Notification.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
@is_zero
stw r3, PSA.ThermalHandlerID(r1)
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 105, MPRegisterPMFHandler
MPRegisterPMFHandler
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr. r8, r3
beq @is_zero
bl LookupID
cmpwi r9, Notification.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
@is_zero
stw r3, PSA.PMFHandlerID(r1)
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 106, MPMarkPMFTask
MPMarkPMFTask
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mfsprg r30, 0
mr. r8, r3
lwz r31, EWA.PA_CurTask(r30)
beq @use_this_task_instead
bl LookupID
cmpwi r9, Task.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
@use_this_task_instead
; Insert bit 31 of r4 into bit 21 of these flags
lwz r17, Task.Flags(r31)
rlwimi r17, r4, 10, Task.kFlagPerfMon, Task.kFlagPerfMon
stw r17, Task.Flags(r31)
; Don't know what this does!
mr r8, r31
bl FlagSchEval
b ReleaseAndReturnZeroFromMPCall
; ARG int r6:
; 2: SystemInfo
; 3: DiagInfo
; 4: NanoKernelInfo
; 5: ProcessorInfo
; 6: HWInfo
; 7: ProcessorState
; RET Ptr r4, short r5 ver, short r6 len
DeclareMPCall 107, NKLocateInfoRecord
NKLocateInfoRecord
cmpwi r3, 5
cmpwi cr1, r3, 2
beq @ProcessorInfo
beq cr1, @SystemInfo
cmpwi r3, 3
cmpwi cr1, r3, 4
beq @DiagInfo
beq cr1, @NanoKernelInfo
cmpwi r3, 7
cmpwi cr1, r3, 6
beq @ProcessorState
bne cr1, ReturnParamErrFromMPCall
lwz r4, KDP.InfoRecord + InfoRecord.NKHWInfoPtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKHWInfoLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKHWInfoVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
@ProcessorState
lwz r4, KDP.InfoRecord + InfoRecord.NKProcessorStatePtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKProcessorStateLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKProcessorStateVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
@ProcessorInfo
lwz r4, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
@NanoKernelInfo
lwz r4, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoPtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
@DiagInfo
lwz r4, KDP.InfoRecord + InfoRecord.NKDiagInfoPtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKDiagInfoLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKDiagInfoVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
@SystemInfo
lwz r4, KDP.InfoRecord + InfoRecord.NKSystemInfoPtr(r1)
lhz r16, KDP.InfoRecord + InfoRecord.NKSystemInfoLen(r1)
lhz r5, KDP.InfoRecord + InfoRecord.NKSystemInfoVer(r1)
stw r16, ContextBlock.r6(r6)
b ReturnZeroFromMPCall
; ARG int r3 stop
; long r4 CpuClockRateHz
; long r5 BusClockRateHz
; long r6 DecClockRateHz
; RET OSStatus r3
DeclareMPCall 108, NKSetPrInfoClockRates
NKSetPrInfoClockRates
cmplwi r3, 2
bge ReturnParamErrFromMPCall
mulli r17, r3, 16
addi r18, r1, KDP.ProcessorInfo + NKProcessorInfo.ClockRates
add r18, r17, r18
lwz r16, ContextBlock.r6(r6)
stw r4, 0(r18)
stw r5, 4(r18)
stw r16, 8(r18)
_log 'Clock rates for step '
mr r8, r3
bl Printd
_log '- Cpu '
mr r8, r4
bl Printd
_log '- Bus '
mr r8, r5
bl Printd
_log '- Dec '
mr r8, r16
bl Printd
_log 'Hz^n'
b ReturnZeroFromMPCall
; NKSetClockStep
; Debug string matches MPLibrary!
; 0xf7e(r1) = clock_step (half-word)
; > r3 = new_clock_step # (half-word)
DeclareMPCall 131, NKSetClockStep
NKSetClockStep ; OUTSIDE REFERER
mfsprg r9, 0
lwz r8, EWA.CPUBase + CPU.LLL + LLL.Freeform(r9)
lwz r9, 0x0024(r8)
cmpwi r9, 0x01
bgt ReturnMPCallOOM
lhz r19, 0x0f7e(r1)
_log 'NKSetClockStep - current '
mr r8, r19
bl Printd
_log ' new '
mr r8, r3
bl Printd
_log '^n'
cmplwi r3, 0x02
cmpw cr1, r3, r19
bge ReturnParamErrFromMPCall
beq cr1, ReturnMPCallOOM
mulli r17, r3, 0x10
addi r18, r1, 0xf80
sth r17, 0x0f7e(r1)
add r18, r17, r18
lwz r16, 0x0000(r18)
lwz r17, 0x0004(r18)
stw r16, 0x0f24(r1)
stw r17, 0x0f28(r1)
lwz r16, 0x0f88(r1)
stw r16, 0x0f2c(r1)
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
lwz r16, 0x0008(r18)
stw r16, PSA.DecClockRateHzCopy(r1)
bgt cr1, NKSetClockStep_0xec
lwz r31, PSA.OtherTimerQueuePtr(r1)
lbz r18, 0x0017(r31)
cmpwi r18, 0x00
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
mr r8, r31
bl DequeueTimer
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
NKSetClockStep_0xec
lwz r31, PSA.OtherTimerQueuePtr(r1)
lbz r18, 0x0017(r31)
cmpwi r18, 0x01
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
bl GetTime
stw r8, 0x0038(r31)
stw r9, 0x003c(r31)
mr r8, r31
bl EnqueueTimer
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
; NKSetClockDriftCorrection
; There's a one-billion constant in here, for fractional
; expression.
; PSA._36c(r1) = tb_drift_numerator
; PSA._368(r1) = tb_drift_denominator
; > r3 = to
DeclareMPCall 132, NKSetClockDriftCorrection
NKSetClockDriftCorrection ; OUTSIDE REFERER
lwz r31, PSA._364(r1)
mfsprg r9, 0
cmpwi r31, 0x00
beq ReturnMPCallOOM
lwz r8, EWA.CPUBase + CPU.LLL + LLL.Freeform(r9)
lwz r9, 0x0024(r8)
cmpwi r9, 0x01
bgt ReturnMPCallOOM
lwz r19, 0x0fa0(r1)
cmpwi r3, 0x00
cmpw cr1, r3, r19
stw r3, 0x0fa0(r1)
beq NKSetClockDriftCorrection_0x12c
beq cr1, ReturnZeroFromMPCall
lis r16, 0x3b9a
ori r16, r16, 0xca00
lwz r17, 0x0f88(r1)
srwi r17, r17, 7
divw r18, r16, r3
cmpw r18, r17
bge NKSetClockDriftCorrection_0x64
divw r16, r16, r17
mr r18, r17
divw r17, r3, r16
b NKSetClockDriftCorrection_0x6c
NKSetClockDriftCorrection_0x64
rlwinm r17, r3, 2, 30, 30
addi r17, r17, 0x01
NKSetClockDriftCorrection_0x6c
stw r17, PSA._36c(r1)
stw r18, PSA._368(r1)
_log 'TB drift adjusted to '
mr r8, r3
bl Printd
_log ' ppb ( '
mr r8, r17
bl Printd
_log '/ '
mr r8, r18
bl Printd
_log ')^n'
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
lwz r31, PSA._364(r1)
lbz r18, 0x0017(r31)
cmpwi r18, 0x01
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
bl GetTime
stw r8, 0x0038(r31)
stw r9, 0x003c(r31)
mr r8, r31
bl EnqueueTimer
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
NKSetClockDriftCorrection_0x12c
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r17, 0x00
stw r17, PSA._36c(r1)
stw r17, PSA._368(r1)
lwz r31, PSA._364(r1)
lbz r18, 0x0017(r31)
cmpwi r18, 0x00
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
mr r8, r31
bl DequeueTimer
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 115, MPCall_115
MPCall_115 ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, ConsoleLog.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lwz r30, 0x000c(r31)
cmpwi r30, 0x00
bne MPCall_115_0x94
_Lock PSA.DbugLock, scratch1=r16, scratch2=r17
lwz r30, PSA._404(r1)
MPCall_115_0x54
addi r30, r30, 0x01
andi. r29, r30, 0xfff
bne MPCall_115_0x64
lwz r30, -0x1000(r30)
MPCall_115_0x64
lbz r16, 0x0000(r30)
cmpwi r16, 0x00
beq MPCall_115_0x54
stw r30, 0x000c(r31)
_AssertAndRelease PSA.DbugLock, scratch=r16
MPCall_115_0x94
cmpwi r5, 0x00
ble ReleaseAndReturnMPCallOOM
rlwinm. r9, r11, 0, 27, 27
mr r8, r4
crmove 30, 2
beq MPCall_115_0xd0
li r9, 0x00
bl SpaceL2PIgnoringBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17
beq ReleaseAndReturnMPCallOOM
add r8, r4, r5
li r9, 0x00
addi r8, r8, -0x01
mr r30, r8
bl SpaceL2PIgnoringBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17
beq ReleaseAndReturnMPCallOOM
MPCall_115_0xd0
lwz r28, PSA._404(r1)
lwz r29, 0x000c(r31)
li r5, 0x00
not r27, r4
MPCall_115_0xe0
cmpw r28, r29
cmplw cr1, r4, r30
beq MPCall_115_0x144
bgt cr1, MPCall_115_0x144
rlwinm r16, r4, 0, 0, 19
mr r8, r4
beq cr7, MPCall_115_0x11c
cmpw r16, r27
mr r17, r26
beq MPCall_115_0x11c
mr r27, r16
li r9, 0x00
bl SpaceL2PIgnoringBATs ; LogicalPage *r8, MPAddressSpace *r9 // PhysicalPage *r17
beq ReleaseAndReturnMPCallOOM
mr r26, r17
MPCall_115_0x11c
rlwimi r17, r4, 0, 20, 31
lbz r8, 0x0000(r29)
addi r29, r29, 0x01
andi. r16, r29, 0xfff
bne+ MPCall_115_0x134
lwz r29, -0x1000(r29)
MPCall_115_0x134
stb r8, 0x0000(r17)
addi r5, r5, 0x01
addi r4, r4, 0x01
b MPCall_115_0xe0
MPCall_115_0x144
stw r29, 0x000c(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
; Point external interrupts (thing PIHes) towards this notification
DeclareMPCall 121, MPRegisterExternalHandler
MPRegisterExternalHandler
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr. r8, r3
beq @zero
bl LookupID
cmpwi r9, Notification.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
@zero
stw r3, PSA.ExternalHandlerID(r1)
b ReleaseAndReturnZeroFromMPCall
DeclareMPCall 133, MPCall_133
MPCall_133 ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
cmpw r3, r0
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
li r17, 0x0b
blt MPCall_133_0x34
and r3, r3, r17
or r16, r16, r3
b MPCall_133_0x3c
MPCall_133_0x34
orc r3, r3, r17
and r16, r16, r3
MPCall_133_0x3c
stw r16, 0x0edc(r1)
srawi r16, r4, 16
extsh r17, r4
cmpwi r16, -0x01
cmpwi cr1, r17, -0x01
beq MPCall_133_0x60
bgt MPCall_133_0x5c
li r16, 0x00
MPCall_133_0x5c
sth r16, PSA._360(r1)
MPCall_133_0x60
beq cr1, MPCall_133_0x70
bgt cr1, MPCall_133_0x6c
li r17, 0x00
MPCall_133_0x6c
sth r17, PSA._35e(r1)
MPCall_133_0x70
srawi r16, r5, 16
extsh r17, r5
cmpwi r16, -0x01
cmpwi cr1, r17, -0x01
beq MPCall_133_0x90
bgt MPCall_133_0x8c
li r16, 0x00
MPCall_133_0x8c
sth r16, PSA._35c(r1)
MPCall_133_0x90
beq cr1, MPCall_133_0xa0
bgt cr1, MPCall_133_0x9c
li r17, 0x00
MPCall_133_0x9c
sth r17, PSA._35a(r1)
MPCall_133_0xa0
; r1 = kdp
bl ScreenConsole_redraw
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_Panic
b panic