Commit 360c9fc5 authored by Jeffrey Lee's avatar Jeffrey Lee Committed by ROOL
Browse files

Make PCI_RAMAlloc more robust

Detail:
* Use the new OS_Memory 23 memory reservation system to stop other DAs
claiming exclusive use of the physical memory we want to use for the PCI
heap
* Switch to using the new OS_Heap 8 instead of OS_Heap 7, so that memory
alignment can be handled in terms of physical address insead of logical
address (avoiding the need to ensure the DA is both logically and
physically aligned)
* Make sure the DA max size matches the amount of memory we found, so
that if we can't get the full 32MB as desired, we don't run the risk of
growing the DA into a non physically contiguous chunk of RAM

Admin:
Tested on BB-xM
parent 900f50cb
......@@ -31,5 +31,6 @@
MakeInternatErrorBlock NDallas
MakeInternatErrorBlock CDATBufferOverflow,,"BufOFlo"
MakeErrorBlock ModuleBadSWI
MakeErrorBlock ChDynamNotAllMoved
END
......@@ -13,32 +13,33 @@
; limitations under the License.
;
RAMAlloc
Push "r1-r4,lr"
Push "r1-r5,lr"
LDR lr, mempool_base_log
TEQ lr, #0
BLEQ InitDA
Pull "r1-r4,pc",VS
Pull "r1-r5,pc",VS
[ DebugMemory
DREG r0, "Requested size ",cc
DREG r1, ", alignment ",cc
DREG r2, ", boundary limitation "
]
LDRB r3, osheap7_supported
LDRB r3, osheap8_supported
CMP r3, #0
BEQ NoOSHeap7
BEQ NoOSHeap8
MOV r4, r2
MOV r3, r0
MOV r2, r1
MOV r0, #HeapReason_GetAligned
MOV r0, #HeapReason_GetSkewAligned
LDR r1, mempool_base_log
LDR r5, mempool_base_phys
SWI XOS_Heap
BVC GotAlloced
LDR r14, [r0]
TEQ r14, #ErrorNumber_HeapFail_Alloc
Pull "r1-r4,pc",NE
Pull "r1-r5,pc",NE
; Grow heap
LDR r0, [r1, #8] ; heap base offset
ADD r0, r0, r1 ; heap base ptr
ADD r0, r0, r5 ; converted to physical address
; Add some breathing room to ensure a free block plus used block header will fit
ADD r0, r0, #12
; Round up heap base ptr to required alignment
......@@ -60,19 +61,27 @@ RAMAlloc
ADD r0, r0, r4
BIC r0, r0, r4
BoundaryOK
ADD r0, r0, r3
LDR r2, [r1, #12] ; heap end offset
SUB r0, r0, r1 ; New base offset
ADD r0, r0, r3 ; required physical end addr of heap
SUB r0, r0, r5 ; required heap size
LDR r2, [r1, #12] ; current heap end offset
ADD r4, r4, #1
SUB r1, r0, r2 ; Grow amount
LDR r0, mempool_da_number
SWI XOS_ChangeDynamicArea
; Try again
MOVVC r0, #HeapReason_GetAligned
MOVVC r0, #HeapReason_GetSkewAligned
LDRVC r1, mempool_base_log
LDRVC r2, [sp]
SWIVC XOS_Heap
Pull "r1-r4,pc",VS
[ DebugMemory
BVC %FT90
LDR r1,[r0],#4
DREG r1,"Error ",cc
DSTRING r0
SUB r0,r0,#4
90
]
Pull "r1-r5,pc",VS
GotAlloced
[ DebugMemory
......@@ -88,9 +97,15 @@ GotAlloced
DREG r1, ", physical address = "
]
ADD sp, sp, #4
Pull "r2-r4,pc"
Pull "r2-r5,pc"
NoOSHeap7
NoOSHeap8
; Check requested alignment against the alignment of the memory we
; reserved - anything larger than the memory alignment can't be dealt
; with by this fallback implementation
LDR r3, mempool_alignment
MOVS lr, r1, LSR r3
BNE BadAlign
CMP r2, r1
MOVLO r2, r1 ; cheaty cheaty
LDR r1, mempool_base_log
......@@ -100,10 +115,10 @@ NoOSHeap7
ADDHI r3, r0, r4
MOV r0, #HeapReason_Get
SWI XOS_Heap
BVC GotAllocedNoOSHeap7
BVC GotAllocedNoOSHeap8
LDR r14, [r0]
TEQ r14, #ErrorNumber_HeapFail_Alloc
Pull "r1-r4,pc",NE
Pull "r1-r5,pc",NE
; Grow heap
LDR r0, [r1, #8] ; heap base offset
LDR r1, [r1, #12] ; heap end offset
......@@ -117,19 +132,21 @@ NoOSHeap7
MOVVC r0, #HeapReason_Get
LDRVC r1, mempool_base_log
SWIVC XOS_Heap
Pull "r1-r4,pc",VS
Pull "r1-r5,pc",VS
GotAllocedNoOSHeap7
GotAllocedNoOSHeap8
[ DebugMemory
DREG r2, "Allocated block at ",cc
DREG r3, ", size = "
]
ADD r0, r2, #4
CMP r4, #4
SUBHI lr, r2, r1 ; align relative to heap start
SUBHI r3, r4, #1
ADDHI r0, r2, r3
ADDHI r0, lr, r3
BICHI r0, r0, r3
ADDHI r0, r0, r1
STR r2, [r0, #-4]
LDR r3, mempool_base_phys
SUB lr, r0, r1
......@@ -139,13 +156,19 @@ GotAllocedNoOSHeap7
DREG r1, ", physical address = "
]
ADD sp, sp, #4
Pull "r2-r4,pc"
Pull "r2-r5,pc"
BadAlign
; Mimic error that's generated if the heap isn't big enough
Pull "r1-r5,lr"
ADRL r0, ErrorBlock_ChDynamNotAllMoved
B copy_error_zero
RAMFree
Push "r1,r2,lr"
; If OS_Heap 7 is supported, all pointers are to heap blocks
; If OS_Heap 8 is supported, all pointers are to heap blocks
; Else the word before the pointer points to the heap block
LDRB r2, osheap7_supported
LDRB r2, osheap8_supported
CMP r2, #0
LDREQ r2, [r0, #-4]
MOVNE r2, r0
......@@ -171,42 +194,76 @@ InitDA
MOVVC r6, #0
MOVVC r7, #0
SWIVC XMessageTrans_Lookup
MOVVC r0, #0
STRVCB r0, [r2, r3]
MOVVC r8, r2
MOVVC r0, #DAReason_Create
MOVVC r1, #-1
STRVC r1, mempool_base_ppn
MOVVC r2, #0
MOVVC r3, #-1
MOVVC r4, #2_00100010 ; SVC only, B, ~C, draggable
ORRVC r4, r4, #&100 ; requires specific physical pages
MOVVC r5, #32*1024*1024
ADRVC r6, DynAreaHandler
MOVVC r7, wp
SWIVC XOS_DynamicArea
BVS %FT19
MOV r0, #0
STRB r0, [r2, r3]
MOV r8, r2
MOV r1, #32*1024*1024 ; Try for 32M, 4M aligned
MOV r2, #22
02 LDR r0, =OSMemReason_RecommendPage+256 ; Request DMAable memory
SWI XOS_Memory
BVC %FT30
MOV r1, r1, LSR #1 ; If we can't get it, halve both
SUB r2, r2, #1 ; until down to 32K, 4K aligned
TST r1, #16*1024 ; preserve V flag in loop test
BEQ %BT02
19
STRVS r0, [sp]
Pull "r0-r8,pc",VS
30
[ DebugMemory
DREG r3, "PPN suggested ",,Integer
]
STR r1, mempool_max_size
STR r2, mempool_alignment
STR r3, mempool_base_ppn
MOV r5, r1
; See if we can reserve the physical pages, to ensure they're available
; when we need them
MOV r0, #OSMemReason_ReservePages
MOV r1, r3
MOV r2, r5, LSR #12
SWI XOS_Memory
MOVVS r0, #0
MOVVC r0, #1
STRB r0, osmemory23_supported
; Get physical addr of memory
MOV r0, #(2_100001:SHL:8) + OSMemReason_Convert
ADR r1, mempool_base_ppn
MOV r2, #1
SWI XOS_Memory
BVS %FT90
[ DebugMemory
LDR r0, mempool_base_phys
DREG r0, "Physical address "
]
MOV r0, #DAReason_Create
MOV r1, #-1
MOV r2, #4096
MOV r3, #-1
LDR r4, =2+DynAreaFlags_NotCacheable+DynAreaFlags_NeedsSpecificPages ; SVC only, B, ~C, draggable, requires specific physical pages
ADR r6, DynAreaHandler
MOV r7, wp
SWI XOS_DynamicArea
BVS %FT90
[ DebugMemory
BVS %FT01
DREG r1, "Dynamic area ",,Integer
DREG r3, "Logical address "
01
]
STRVS r0, [sp]
Pull "r0-r8,pc",VS
20 STR r1, mempool_da_number
STR r1, mempool_da_number
STR r3, mempool_base_log
STR r3, mempool_free
; Grow by one page so we can init the heap
; (can't do the initial grow during DA create since the pre-grow handler needs to know the logical base)
SWI XOS_ReadMemMapInfo
MOVVC r1, r0
LDRVC r0, mempool_da_number
SWIVC XOS_ChangeDynamicArea
MOVVC r0, #HeapReason_Init
MOVVC r3, r1
LDRVC r1, mempool_base_log
SWIVC XOS_Heap
; Init the heap
MOV r0, #HeapReason_Init
MOV r1, r3
MOV r3, r2
SWI XOS_Heap
Pull "r0-r8,pc",VC
90
; error case
STR r0,[sp]
BL KillDA
......@@ -214,7 +271,18 @@ InitDA
Pull "r0-r8,pc"
KillDA
Push "r0-r1,lr"
Push "r0-r2,lr"
; Release the pages we reserved
LDRB r0, osmemory23_supported
CMP r0, #0
MOVNE r0, #0
STRNEB r0, osmemory23_supported
LDRNE r0, =OSMemReason_ReservePages+256
LDRNE r1, mempool_base_ppn
LDRNE r2, mempool_max_size
MOVNE r2, r2, LSR #12
SWINE XOS_Memory
; Kill the DA
MOV r0, #DAReason_Remove
LDR r1, mempool_da_number
CMP r1, #0
......@@ -228,7 +296,7 @@ KillDA
STR r1, mempool_da_number
STR r1, mempool_base_log
STRVS r0, [sp]
Pull "r0-r1,pc"
Pull "r0-r2,pc"
Token_DAName
= "DAName", 0
......@@ -255,53 +323,12 @@ UnknownHandlerError
; R4 = current size (bytes)
; R5 = page size
;
; exit with V clear, all preserved
; exit with V clear, R0=0 or DAHandler_RESV
PreGrow Entry "r0-r3"
PreGrow Entry "r1-r3"
LDR r3, mempool_base_ppn
CMP r3, #-1
BNE %FT05
MOV r1, #32*1024*1024 ; Try for 32M, 4M aligned
MOV r2, #22
02 MOV r0, #OSMemReason_RecommendPage
SWI XOS_Memory
BVC %FT03
MOV r1, r1, LSR #1 ; If we can't get it, halve both
SUB r2, r2, #1 ; until down to 32K, 4K aligned
TST r1, #16*1024 ; preserve V flag in loop test
BEQ %BT02
B %FT99
03
[ DebugMemory
DREG r3, "PPN suggested ",,Integer
]
; Skip the first few pages of the region, to ensure physical alignment and logical alignment match
; (all our allocation functions work by aligning based around logical addresses, when really what the client wants is physically aligned memory)
MOV r0, #1
MOV r2, r0, LSL r2
SUB r2, r2, #1
LDR r0, mempool_base_log
AND r0, r0, r2
ADD r3, r3, r0, LSR #12
[ DebugMemory
DREG r3, "PPN aligned ",,Integer
]
STR r3, mempool_base_ppn
MOV r0, #(2_100001:SHL:8) + OSMemReason_Convert
ADR r1, mempool_base_ppn
MOV r2, #1
SWI XOS_Memory
BVS %FT99
[ DebugMemory
LDR r0, mempool_base_phys
DREG r0, "Physical address "
]
LDMFD sp, {r0-r2} ; recover input parameters
05 MOV lr, #0
MOV lr, #0
[ DebugMemory
DREG r4, "Current size ",cc
DREG r5, ", page size "
......@@ -319,7 +346,9 @@ PreGrow Entry "r0-r3"
ADDNE r3, r3, #1
BNE %BT20
99 STRVS r0, [sp]
LDRB r0, osmemory23_supported
CMP r0, #0
LDRNE r0, =DAHandler_RESV ; Allow use of the pages we reserved
EXIT
PostGrow
......
......@@ -69,8 +69,10 @@ ModuleFlags
Word mempool_base_log
Word mempool_base_phys
Word mempool_base_pci
Word mempool_free
Byte osheap7_supported
Word mempool_alignment
Word mempool_max_size
Byte osheap8_supported
Byte osmemory23_supported
Byte pcibus_supported
AlignSpace
Byte name_buffer, 128
......@@ -121,17 +123,17 @@ InitModule
STRPL r0, [r12, r3]
BPL %BT10
; Check if OS_Heap 7 (get area aligned) is supported
; Check if OS_Heap 8 (get area aligned relative to R5) is supported
; We'll do a dummy call with a bad heap block and see what error we get
; back (Assumes bad reason codes will always be checked first!)
MOV r0, #HeapReason_GetAligned
MOV r0, #HeapReason_GetSkewAligned
MOV r1, r12 ; Valid address but not a heap
SWI XOS_Heap
LDRVS r0, [r0]
TEQVS r0, #ErrorNumber_HeapBadReason ; EQ if unsupported
TEQVC r1, r1 ; EQ if no error returned (definitely a bad sign)
MOVNE r0, #1
STRNEB r0, osheap7_supported
STRNEB r0, osheap8_supported
BL SetUpHAL
; If we get an error back there is no PCI. But do not give up,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment