2018-03-23 09:22:56 +00:00
|
|
|
|
; SEGMENTS
|
|
|
|
|
;
|
|
|
|
|
; The pool is made up of segments of contiguous memory. The first segment
|
|
|
|
|
; to be created is about 25k, running from 0x7000 below r1 to the start of
|
|
|
|
|
; the Primary System Area. It is initialised by InitPool. Every subsequent
|
|
|
|
|
; segment occupies a single page, plucked from the system free list by
|
|
|
|
|
; ExtendPool.
|
|
|
|
|
;
|
|
|
|
|
;
|
|
|
|
|
; BLOCKS
|
|
|
|
|
;
|
|
|
|
|
; Each segment is an array of variously sized blocks, with no gaps between
|
|
|
|
|
; them. The first block is a Begin (<28>BGN) block, the last block is an End
|
|
|
|
|
; block (<28>END), and all others are Allocated (<28>loc) or Free (free) blocks.
|
|
|
|
|
; To allow the data in each Allocated block to be 16b-aligned, all
|
|
|
|
|
; Allocated and Free blocks start 8b below a 16b boundary.
|
|
|
|
|
;
|
|
|
|
|
;
|
|
|
|
|
; SINGLY LINKED LIST OF SEGMENTS
|
|
|
|
|
;
|
|
|
|
|
; PSA.FirstPoolSeg points to the start of the most recently added pool
|
|
|
|
|
; segment, i.e. to its Begin block. The OffsetToNext field of a Begin
|
|
|
|
|
; block points not to the block immediately beyond it in memory, but to
|
|
|
|
|
; the segment's End block. The OffsetToNext field of the End block points
|
|
|
|
|
; to the start of the next most recently added pool segment. If there is
|
|
|
|
|
; none, it contains zero.
|
|
|
|
|
;
|
|
|
|
|
;
|
|
|
|
|
; DOUBLY LINKED LIST OF FREE BLOCKS
|
|
|
|
|
;
|
|
|
|
|
; Every free block is a member of PSA.FreePool, a doubly linked list of
|
|
|
|
|
; free segments. The "LLL" structure occupies the first 16 bytes of the
|
|
|
|
|
; block.
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-06-30 08:00:35 +00:00
|
|
|
|
; AUTO-GENERATED SYMBOL LIST
|
|
|
|
|
; IMPORTS:
|
|
|
|
|
; NKConsoleLog
|
|
|
|
|
; printc
|
|
|
|
|
; printd
|
|
|
|
|
; printw
|
|
|
|
|
; NKThud
|
|
|
|
|
; panic
|
|
|
|
|
; EXPORTS:
|
|
|
|
|
; ExtendPool (=> NKMPCalls)
|
|
|
|
|
; InitPool (=> NKInit)
|
2018-07-04 11:26:33 +00:00
|
|
|
|
; PoolAlloc (=> NKExceptions, NKSync, NKTasks)
|
2018-06-30 08:00:35 +00:00
|
|
|
|
; PoolAllocClear (=> NKAddressSpaces, NKIndex, NKInit, NKMPCalls, NKSync, NKTasks, NKTimers, NKVMCalls)
|
|
|
|
|
; PoolFree (=> NKAddressSpaces, NKMPCalls, NKSync, NKTasks, NKTimers)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
Block record
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
kBeginSize equ 8
|
|
|
|
|
kEndSize equ 24
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
kPoolSig equ 'POOL'
|
|
|
|
|
kBeginSig equ '<EFBFBD>BGN'
|
|
|
|
|
kEndSig equ '<EFBFBD>END'
|
|
|
|
|
kAllocSig equ '<EFBFBD>loc'
|
|
|
|
|
kFreeSig equ 'free'
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; For free and allocated blocks, points to the next block
|
|
|
|
|
; For begin blocks, points to corresponding end block
|
|
|
|
|
; For end blocks, points to another begin block (or zero)
|
|
|
|
|
OffsetToNext ds.l 1 ; 0
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
Signature ds.l 1 ; 4
|
|
|
|
|
|
|
|
|
|
Data
|
|
|
|
|
LogiNextSeg
|
|
|
|
|
FreeNext ds.l 1 ; 8
|
|
|
|
|
|
|
|
|
|
FreePrev ds.l 1 ; c
|
|
|
|
|
|
|
|
|
|
endr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_PoolPanic
|
|
|
|
|
|
|
|
|
|
b panic
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Use all the memory from r1 - 0x7000 to PSA
|
|
|
|
|
|
|
|
|
|
InitPool
|
|
|
|
|
|
|
|
|
|
; Add first segment to global singly linked list
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
lwz r8, KDP.PA_ConfigInfo(r1)
|
|
|
|
|
lwz r8, NKConfigurationInfo.LA_KernelData(r8)
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r9, -kPoolOffsetFromGlobals
|
2017-11-19 04:11:07 +00:00
|
|
|
|
subf r9, r9, r8
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r9, PSA.FirstPoolSegLogical(r1)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r9, kPoolOffsetFromGlobals
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r9, r9, r1
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r9, PSA.FirstPoolSeg(r1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Decide how big the segment will be
|
|
|
|
|
|
|
|
|
|
_pool_first_seg equ PSA.Base - kPoolOffsetFromGlobals
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Begin block (leave ptr to End in r23)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r8, _pool_first_seg - Block.kEndSize
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r23, r8, r9
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r8, Block.OffsetToNext(r9)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r8, Block.kBeginSig
|
|
|
|
|
stw r8, Block.Signature(r9)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Free block (leave ptr in r9)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
addi r9, r9, Block.kBeginSize
|
|
|
|
|
lisori r8, _pool_first_seg - Block.kEndSize - Block.kBeginSize
|
|
|
|
|
stw r8, Block.OffsetToNext(r9)
|
|
|
|
|
|
|
|
|
|
lisori r8, Block.kFreeSig
|
|
|
|
|
stw r8, Block.Signature(r9)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; End block
|
|
|
|
|
|
|
|
|
|
li r8, 0
|
|
|
|
|
stw r8, Block.OffsetToNext(r23)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r8, Block.kEndSig
|
|
|
|
|
stw r8, Block.Signature(r23)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Add Free block to global doubly linked list
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
addi r8, r1, PSA.FreePool
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r9, Block.FreeNext(r8)
|
|
|
|
|
stw r9, Block.FreePrev(r8)
|
|
|
|
|
stw r8, Block.FreeNext(r9)
|
|
|
|
|
stw r8, Block.FreePrev(r9)
|
|
|
|
|
|
|
|
|
|
lisori r9, Block.kPoolSig
|
|
|
|
|
stw r9, Block.Signature(r8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Return
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
blr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; The NanoKernel's malloc
|
|
|
|
|
|
|
|
|
|
; ARG size r8
|
|
|
|
|
; RET ptr r8
|
|
|
|
|
|
|
|
|
|
_poolalloc_noclr_cr_bit equ 30
|
|
|
|
|
|
|
|
|
|
PoolAllocClear
|
|
|
|
|
crclr _poolalloc_noclr_cr_bit
|
|
|
|
|
b _PoolAllocCommon
|
|
|
|
|
PoolAlloc
|
|
|
|
|
crset _poolalloc_noclr_cr_bit
|
|
|
|
|
_PoolAllocCommon
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
; Save LR and arg to EWA. Get lock.
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
mflr r17
|
|
|
|
|
mfsprg r18, 0
|
|
|
|
|
|
|
|
|
|
_Lock PSA.PoolLock, scratch1=r15, scratch2=r16
|
|
|
|
|
|
|
|
|
|
; These saves are my first real hint at the contents of that
|
|
|
|
|
; large unexplored area of the EWA. This file, then, owns
|
|
|
|
|
; part of the EWA, for its CPU-scoped globals. Because the
|
|
|
|
|
; kernel runs stackless.
|
|
|
|
|
stw r17, EWA.PoolSavedLR(r18)
|
|
|
|
|
stw r8, EWA.PoolSavedSizeArg(r18)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@recheck_for_new_block
|
|
|
|
|
|
|
|
|
|
; Sanity checks
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpwi r8, 0
|
|
|
|
|
cmpwi cr1, r8, 0xfd8
|
2018-04-15 07:05:02 +00:00
|
|
|
|
ble _PoolPanic
|
|
|
|
|
bgt cr1, @request_too_large
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Up-align to 32b boundary and snatch an extra 8b
|
|
|
|
|
; This is our minimum OffsetToNext field
|
|
|
|
|
|
|
|
|
|
addi r8, r8, 8 + 31
|
|
|
|
|
rlwinm r8, r8, 0, 0xffffffe0
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Iterate the free-block list
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
addi r14, r1, PSA.FreePool
|
|
|
|
|
lwz r15, LLL.Next(r14)
|
2018-03-23 09:22:56 +00:00
|
|
|
|
@next_block
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpw r14, r15
|
2018-03-23 09:22:56 +00:00
|
|
|
|
bne+ @try_block
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Global free-block list is empty (not great news)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Got a free page in the system free list? It's ours.
|
|
|
|
|
li r8, 0 ; return zero if there is no page at all
|
|
|
|
|
li r9, 1 ; number of pages to grab
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lwz r16, PSA.FreePageCount(r1)
|
|
|
|
|
lwz r17, PSA.UnheldFreePageCount(r1)
|
|
|
|
|
subf. r16, r9, r16
|
|
|
|
|
subf r17, r9, r17
|
2018-04-15 07:05:02 +00:00
|
|
|
|
blt _PoolReturn
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
stw r16, PSA.FreePageCount(r1)
|
|
|
|
|
stw r17, PSA.UnheldFreePageCount(r1)
|
|
|
|
|
|
|
|
|
|
; Get that page, mofo. Macros FTW.
|
|
|
|
|
lwz r8, PSA.FreeList + LLL.Next(r1)
|
|
|
|
|
RemoveFromList r8, scratch1=r17, scratch2=r18
|
|
|
|
|
|
|
|
|
|
; There was probably once a mechanism for virtual addressing of the pool!
|
|
|
|
|
li r9, 0
|
|
|
|
|
bl ExtendPool ; r8=page, r9=virt=0
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
; Now that the pool is not empty, start over.
|
|
|
|
|
mfsprg r18, 0
|
|
|
|
|
lwz r8, EWA.PoolSavedSizeArg(r18)
|
2018-03-23 09:22:56 +00:00
|
|
|
|
b @recheck_for_new_block
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Request was greater than the maximum block size
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
@request_too_large
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
li r8, 0
|
2018-03-23 09:22:56 +00:00
|
|
|
|
b _PoolReturn
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Try the free block that r15 points to
|
|
|
|
|
|
|
|
|
|
@try_block
|
|
|
|
|
@retry_newly_expanded_block
|
|
|
|
|
|
|
|
|
|
lwz r16, Block.OffsetToNext(r15)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmplw r16, r8
|
|
|
|
|
|
|
|
|
|
lis r20, 'fr'
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bgt @decide_whether_to_split
|
|
|
|
|
beq @do_not_split
|
2017-11-19 04:11:07 +00:00
|
|
|
|
ori r20, r20, 'ee'
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; This block is too small to fit our allocation, but can it be mashed together
|
|
|
|
|
; with a physically adjacent free block? This might happen a few times before
|
|
|
|
|
; we decide to give up and search for another block.
|
|
|
|
|
|
|
|
|
|
lwz r16, Block.OffsetToNext(r15)
|
|
|
|
|
add r18, r16, r15
|
|
|
|
|
lwz r19, Block.Signature(r18)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmplw cr1, r18, r15
|
|
|
|
|
cmpw r19, r20
|
2018-04-15 07:05:02 +00:00
|
|
|
|
ble cr1, _PoolPanic
|
|
|
|
|
bne @physically_adjacent_block_is_not_free
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
lwz r17, Block.OffsetToNext(r18)
|
|
|
|
|
rotlwi r19, r19, 8
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r17, r17, r16
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r17, Block.OffsetToNext(r15)
|
|
|
|
|
stw r19, Block.Signature(r18) ; scramble old signature to clarify mem dumps
|
|
|
|
|
lwz r17, Block.FreePrev(r18)
|
|
|
|
|
lwz r16, Block.FreeNext(r18)
|
|
|
|
|
stw r16, Block.FreeNext(r17)
|
|
|
|
|
stw r17, Block.FreePrev(r16)
|
|
|
|
|
|
|
|
|
|
b @retry_newly_expanded_block
|
|
|
|
|
@physically_adjacent_block_is_not_free
|
|
|
|
|
|
|
|
|
|
lwz r15, Block.FreeNext(r15)
|
|
|
|
|
b @next_block
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Success: split the block if there is >=40b left over
|
|
|
|
|
|
|
|
|
|
@decide_whether_to_split
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
subf r16, r8, r16
|
2018-03-23 09:22:56 +00:00
|
|
|
|
cmpwi r16, 40
|
2018-04-15 07:05:02 +00:00
|
|
|
|
blt @do_not_split
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Use the rightmost part of the block, leaving ptr in r15
|
|
|
|
|
; (Leaving the leftmost part saves us touching the free block list)
|
|
|
|
|
|
|
|
|
|
stw r16, Block.OffsetToNext(r15)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r15, r15, r16
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r8, Block.OffsetToNext(r15)
|
|
|
|
|
b @proceed_with_block
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Success: use the entire block, leaving ptr in r15
|
|
|
|
|
|
|
|
|
|
@do_not_split
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
lwz r14, 0x000c(r15)
|
|
|
|
|
lwz r16, LLL.Next(r15)
|
|
|
|
|
stw r16, LLL.Next(r14)
|
|
|
|
|
stw r14, 0x000c(r16)
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Sign the block and return data ptr in r8
|
|
|
|
|
|
|
|
|
|
@proceed_with_block
|
|
|
|
|
|
|
|
|
|
lisori r8, Block.kAllocSig
|
|
|
|
|
stw r8, Block.Signature(r15)
|
|
|
|
|
|
|
|
|
|
addi r8, r15, Block.Data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Optionally clear the block (quicker if we don't)
|
|
|
|
|
|
|
|
|
|
bc BO_IF, _poolalloc_noclr_cr_bit, _PoolReturn
|
|
|
|
|
lwz r16, Block.OffsetToNext(r15)
|
|
|
|
|
subi r16, r16, Block.Data
|
|
|
|
|
li r14, 0
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r16, r16, r15
|
2018-03-23 09:22:56 +00:00
|
|
|
|
addi r15, r15, 4
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
@clrloop
|
|
|
|
|
stwu r14, 4(r15)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpw r15, r16
|
2018-04-15 07:05:02 +00:00
|
|
|
|
ble @clrloop
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
b _PoolReturn
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; The NanoKernel's free
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; ARG r8 = ptr to contents of pool block
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
PoolFree
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
mflr r17
|
|
|
|
|
mfsprg r18, 0
|
|
|
|
|
|
|
|
|
|
_Lock PSA.PoolLock, scratch1=r15, scratch2=r16
|
|
|
|
|
|
|
|
|
|
stw r17, EWA.PoolSavedLR(r18)
|
2018-03-23 09:22:56 +00:00
|
|
|
|
bl _PoolAddBlockToFreeList
|
|
|
|
|
bl _PoolMergeAdjacentFreeBlocks
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Fall through...
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; PoolAlloc and PoolFree save LR on entry, then return this way
|
|
|
|
|
|
|
|
|
|
_PoolReturn
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
mfsprg r18, 0
|
|
|
|
|
|
2017-12-12 07:54:19 +00:00
|
|
|
|
_AssertAndRelease PSA.PoolLock, scratch=r15
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
lwz r17, EWA.PoolSavedLR(r18)
|
|
|
|
|
mtlr r17
|
|
|
|
|
blr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Re-label an Allocated block as Free, and add it to the global list
|
|
|
|
|
; Panics if block is not Allocated to start with!
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; ARG r8 = ptr to contents of pool block
|
|
|
|
|
; RET r15 = ptr to pool block itself (r8 - 8)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
_PoolAddBlockToFreeList
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Get the block containing the data
|
|
|
|
|
subi r15, r8, Block.Data
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Change the signature
|
|
|
|
|
_lstart r20, Block.kFreeSig
|
|
|
|
|
lhz r16, Block.Signature(r15)
|
|
|
|
|
_lfinish
|
|
|
|
|
cmplwi r16, 0x876c ; Block.kAllocSig >> 16
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bne _PoolPanic
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r20, Block.Signature(r15)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Insert into the global free block list
|
2017-11-19 04:11:07 +00:00
|
|
|
|
addi r16, r1, PSA.FreePool
|
|
|
|
|
InsertAsPrev r15, r16, scratch=r17
|
|
|
|
|
|
|
|
|
|
blr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Merge a free block with any free blocks to the right
|
|
|
|
|
; (Cannot look to the left because list is singly linked)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; ARG r15 = ptr to free block
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
_PoolMergeAdjacentFreeBlocks
|
|
|
|
|
|
|
|
|
|
@next_segment
|
|
|
|
|
_lstart r20, Block.kFreeSig
|
|
|
|
|
lwz r16, Block.OffsetToNext(r15)
|
|
|
|
|
_lfinish
|
|
|
|
|
add r18, r16, r15 ; r18 = block to the right
|
|
|
|
|
lwz r19, Block.Signature(r18) ; r19 = signature of that block
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmplw cr1, r18, r15
|
|
|
|
|
cmpw r19, r20
|
2018-04-15 07:05:02 +00:00
|
|
|
|
ble cr1, _PoolPanic ; die if block was of non-positive size!
|
|
|
|
|
bnelr ; return if block to right is not free
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
lwz r17, Block.OffsetToNext(r18)
|
|
|
|
|
rotlwi r19, r19, 8 ; scramble old signature to clarify mem dumps
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r17, r17, r16
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r17, Block.OffsetToNext(r15) ; increase the size of the main block
|
|
|
|
|
stw r19, Block.Signature(r18)
|
|
|
|
|
|
|
|
|
|
lwz r17, Block.FreePrev(r18) ; remove the absorbed block from the list of free blocks
|
|
|
|
|
lwz r16, Block.FreeNext(r18)
|
|
|
|
|
stw r16, Block.FreeNext(r17)
|
|
|
|
|
stw r17, Block.FreePrev(r16)
|
|
|
|
|
|
|
|
|
|
b @next_segment
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Create a new pool segment from a physical page
|
|
|
|
|
|
|
|
|
|
; ARG PhysPtr r8, LogiPtr r9
|
|
|
|
|
|
|
|
|
|
ExtendPool
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mflr r14
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; This segment will occupy a page
|
|
|
|
|
|
|
|
|
|
_pool_page_seg equ 0x1000
|
|
|
|
|
|
|
|
|
|
rlwinm r17, r8, 0, -(_pool_page_seg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Counter can be viewed from Apple System Profiler
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.FreePoolExtendCount(r1)
|
|
|
|
|
addi r16, r16, 1
|
|
|
|
|
stw r16, KDP.NanoKernelInfo + NKNanoKernelInfo.FreePoolExtendCount(r1)
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Bit of palaver
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
_log 'Extend free pool: phys 0x'
|
|
|
|
|
mr r8, r17
|
|
|
|
|
bl Printw
|
|
|
|
|
_log ' virt 0x'
|
|
|
|
|
mr r8, r9
|
|
|
|
|
bl Printw
|
|
|
|
|
_log ' count: '
|
|
|
|
|
mr r8, r16
|
|
|
|
|
bl Printd
|
|
|
|
|
_log '^n'
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Clear the page
|
|
|
|
|
|
|
|
|
|
li r16, _pool_page_seg
|
2017-11-19 04:11:07 +00:00
|
|
|
|
@zeroloop
|
|
|
|
|
subi r16, r16, 32
|
|
|
|
|
cmpwi r16, 0
|
|
|
|
|
dcbz r16, r17
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bgt @zeroloop
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Begin block
|
|
|
|
|
|
|
|
|
|
li r16, _pool_page_seg - Block.kEndSize
|
|
|
|
|
stw r16, Block.OffsetToNext(r17)
|
|
|
|
|
|
|
|
|
|
lisori r16, Block.kBeginSig
|
|
|
|
|
stw r16, Block.Signature(r17)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Alloc block (_PoolAddBlockToFreeList will convert to Free)
|
|
|
|
|
|
|
|
|
|
addi r15, r17, Block.kBeginSize
|
|
|
|
|
li r16, _pool_page_seg - Block.kEndSize - Block.kBeginSize
|
|
|
|
|
stw r16, Block.OffsetToNext(r15)
|
|
|
|
|
|
|
|
|
|
lisori r16, Block.kAllocSig
|
|
|
|
|
stw r16, Block.Signature(r15)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; End block
|
|
|
|
|
|
|
|
|
|
addi r15, r17, _pool_page_seg - Block.kEndSize
|
|
|
|
|
lwz r18, PSA.FirstPoolSeg(r1)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
subf r18, r15, r18
|
2018-03-23 09:22:56 +00:00
|
|
|
|
stw r18, Block.OffsetToNext(r15) ; point to next-most-recently-added segment
|
|
|
|
|
|
|
|
|
|
lisori r16, Block.kEndSig
|
|
|
|
|
stw r16, Block.Signature(r15)
|
|
|
|
|
|
|
|
|
|
lwz r16, PSA.FirstPoolSegLogical(r1) ; vestigial?
|
|
|
|
|
stw r16, Block.LogiNextSeg(r15)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Add new segment to global singly linked list
|
|
|
|
|
|
|
|
|
|
stw r9, PSA.FirstPoolSegLogical(r1)
|
|
|
|
|
stw r17, PSA.FirstPoolSeg(r1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Free the Alloc block and add it to the global doubly linked list
|
|
|
|
|
|
|
|
|
|
addi r8, r17, Block.kBeginSize + Block.Data
|
|
|
|
|
bl _PoolAddBlockToFreeList
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; This won't do anything, because there is no other free block in the segment
|
|
|
|
|
|
|
|
|
|
bl _PoolMergeAdjacentFreeBlocks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Return
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mtlr r14
|
|
|
|
|
blr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; Check the pool for corruption (dead code)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
PoolCheck
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
mflr r19
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lwz r20, PSA.FirstPoolSeg(r1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Check this segment, starting with first Allocated block
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
@next_segment
|
|
|
|
|
addi r8, r20, Block.kBeginSize
|
|
|
|
|
bl _PoolCheckBlocks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Get End block
|
|
|
|
|
|
|
|
|
|
lwz r17, Block.OffsetToNext(r20)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r17, r17, r20
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Use that to get another Begin block
|
|
|
|
|
|
|
|
|
|
lwz r18, Block.OffsetToNext(r17)
|
|
|
|
|
cmpwi r18, 0
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r20, r18, r17
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bne @next_segment
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; If there are no more Begins, we are done
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mtlr r19
|
|
|
|
|
blr
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Only called by the above function
|
|
|
|
|
; Called on data ptrs? Or on block ptrs?
|
|
|
|
|
|
|
|
|
|
; ARG ptr r8
|
|
|
|
|
|
|
|
|
|
_PoolCheckBlocks
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mflr r14
|
2018-03-23 09:22:56 +00:00
|
|
|
|
subi r16, r8, 8 ; Block.kBeginSize or Block.Data?
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
@loop
|
|
|
|
|
lwz r17, Block.Signature(r16)
|
|
|
|
|
|
|
|
|
|
lisori r18, Block.kEndSig
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpw r17, r18
|
2018-03-23 09:22:56 +00:00
|
|
|
|
li r9, 0
|
2018-04-15 07:05:02 +00:00
|
|
|
|
beq @return
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
lisori r18, Block.kAllocSig
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpw r17, r18
|
2018-04-15 07:05:02 +00:00
|
|
|
|
beq @block_is_allocated
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lisori r18, Block.kFreeSig
|
|
|
|
|
li r9, 4
|
|
|
|
|
cmpw r17, r18
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bne @block_corrupt
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; From now we assume Free
|
|
|
|
|
lwz r17, Block.FreePrev(r16)
|
|
|
|
|
cmpwi r17, 0
|
|
|
|
|
li r9, 5
|
2018-04-15 07:05:02 +00:00
|
|
|
|
beq @block_corrupt
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
lwz r17, Block.FreeNext(r16)
|
|
|
|
|
cmpwi r17, 0
|
|
|
|
|
li r9, 6
|
2018-04-15 07:05:02 +00:00
|
|
|
|
beq @block_corrupt
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
@block_is_allocated
|
|
|
|
|
;or block is free (fallthru)
|
|
|
|
|
lwz r17, Block.OffsetToNext(r16)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
add r16, r16, r17
|
2018-03-23 09:22:56 +00:00
|
|
|
|
cmpwi r17, 0
|
|
|
|
|
li r9, 7
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bgt @loop
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
; 4: neither Allocated nor Free
|
|
|
|
|
; 5: Free with bad FreePrev ptr
|
|
|
|
|
; 6: Free with bad FreeNext ptr
|
|
|
|
|
; 7: bad OffsetToNext ptr
|
|
|
|
|
|
|
|
|
|
@block_corrupt
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mr r18, r8
|
|
|
|
|
_log 'Heap segment corrupt '
|
|
|
|
|
mr r8, r9
|
|
|
|
|
bl Printd
|
|
|
|
|
_log 'at '
|
|
|
|
|
mr r8, r16
|
|
|
|
|
bl Printw
|
|
|
|
|
_log '^n'
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
; Dump some memory
|
|
|
|
|
|
|
|
|
|
subi r16, r16, 64
|
|
|
|
|
li r17, 8 ; 8 lines, 16 bytes each
|
|
|
|
|
|
|
|
|
|
@dump_next_line
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mr r8, r16
|
|
|
|
|
bl Printw
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
_log ' '
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
lwz r8, 0(r16)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
bl Printw
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lwz r8, 4(r16)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
bl Printw
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lwz r8, 8(r16)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
bl Printw
|
2018-03-23 09:22:56 +00:00
|
|
|
|
lwz r8, 12(r16)
|
2017-11-19 04:11:07 +00:00
|
|
|
|
bl Printw
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
_log ' *'
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
li r8, 16
|
|
|
|
|
subi r16, r16, 1
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mtctr r8
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
@dump_next_char
|
|
|
|
|
lbzu r8, 1(r16)
|
|
|
|
|
|
|
|
|
|
cmpwi r8, ' '
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bgt @dont_use_space
|
2018-03-23 09:22:56 +00:00
|
|
|
|
li r8, ' '
|
|
|
|
|
@dont_use_space
|
2017-11-19 04:11:07 +00:00
|
|
|
|
|
|
|
|
|
bl Printc
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bdnz @dump_next_char
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
_log '*^n'
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
subi r17, r17, 1
|
|
|
|
|
addi r16, r16, 1
|
2017-11-19 04:11:07 +00:00
|
|
|
|
cmpwi r17, 0x00
|
2018-04-15 07:05:02 +00:00
|
|
|
|
bne @dump_next_line
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mr r8, r18
|
|
|
|
|
|
2018-03-23 09:22:56 +00:00
|
|
|
|
|
|
|
|
|
@return
|
2017-11-19 04:11:07 +00:00
|
|
|
|
mtlr r14
|
|
|
|
|
blr
|