Commit 1f84ad9f authored by Jeffrey Lee's avatar Jeffrey Lee Committed by ROOL
Browse files

Allow reservation of memory pages

This change adds a new OS_Memory reason code, 23, for reserving memory
without actually assigning it to a dynamic area. Other dynamic areas can
still use the memory, but only the code that reserved it will be allowed
to claim exclusive use over it (i.e. PageFlags_Unavailable).

This is useful for systems such as the PCI heap, where physically
contiguous memory is required, but the memory isn't needed all of the
time. By reserving the pages, it allows other regular DAs to make use of
the memory when the PCI heap is small. But when the PCI heap needs to
grow, it guarantees that (if there's enough free memory in the system)
the previously reserved pages can be allocated to the PCI heap.

Notes:

* Reservations are handled on an honour system; there's no checking that
the program that reserved the memory is the one attempting to map it in.

* For regular NeedsSpecificPages DAs, reserved pages can only be used if
the special "RESV" R0 return value is used.

* For PMP DAs, reserved pages can only be made Unavailable if the entry
in the page block also specifies the Reserved page flag. The actual
state of the Reserved flag can't be modified via PMP DA ops, the flag is
only used to indicate the caller's permission/intent to make the page
Unavailable.

* If a PMP DA tries to make a Reserved page Unavailable without
specifying the Reserved flag, the kernel will try to swap it out for a
replacement page taken from the free pool (preserving the contents and
generating Service_PagesUnsafe / Service_PagesSafe, as if another DA
had claimed the page)

Version 6.28. Tagged as 'Kernel-6_28'
parent a52c5049
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
GBLS Module_ApplicationDate GBLS Module_ApplicationDate
GBLS Module_HelpVersion GBLS Module_HelpVersion
GBLS Module_ComponentName GBLS Module_ComponentName
Module_MajorVersion SETS "6.27" Module_MajorVersion SETS "6.28"
Module_Version SETA 627 Module_Version SETA 628
Module_MinorVersion SETS "" Module_MinorVersion SETS ""
Module_Date SETS "19 Nov 2019" Module_Date SETS "19 Nov 2019"
Module_ApplicationDate SETS "19-Nov-19" Module_ApplicationDate SETS "19-Nov-19"
Module_ComponentName SETS "Kernel" Module_ComponentName SETS "Kernel"
Module_FullVersion SETS "6.27" Module_FullVersion SETS "6.28"
Module_HelpVersion SETS "6.27 (19 Nov 2019)" Module_HelpVersion SETS "6.28 (19 Nov 2019)"
END END
/* (6.27) /* (6.28)
* *
* This file is automatically maintained by srccommit, do not edit manually. * This file is automatically maintained by srccommit, do not edit manually.
* *
*/ */
#define Module_MajorVersion_CMHG 6.27 #define Module_MajorVersion_CMHG 6.28
#define Module_MinorVersion_CMHG #define Module_MinorVersion_CMHG
#define Module_Date_CMHG 19 Nov 2019 #define Module_Date_CMHG 19 Nov 2019
#define Module_MajorVersion "6.27" #define Module_MajorVersion "6.28"
#define Module_Version 627 #define Module_Version 628
#define Module_MinorVersion "" #define Module_MinorVersion ""
#define Module_Date "19 Nov 2019" #define Module_Date "19 Nov 2019"
...@@ -16,6 +16,6 @@ ...@@ -16,6 +16,6 @@
#define Module_ComponentName "Kernel" #define Module_ComponentName "Kernel"
#define Module_FullVersion "6.27" #define Module_FullVersion "6.28"
#define Module_HelpVersion "6.27 (19 Nov 2019)" #define Module_HelpVersion "6.28 (19 Nov 2019)"
#define Module_LibraryVersionInfo "6:27" #define Module_LibraryVersionInfo "6:28"
...@@ -83,7 +83,8 @@ CP_CB_AlternativeDCache * 4 ; Use XScale/SA11x0 mini-data ca ...@@ -83,7 +83,8 @@ CP_CB_AlternativeDCache * 4 ; Use XScale/SA11x0 mini-data ca
; ;
; N.B. not all public flags are writable. ; N.B. not all public flags are writable.
; ;
PageFlags_Unavailable * 1 :SHL: 15 ; physical page has been claimed by someone for exclusive use (can't be requested by PreGrow handler or PMP PhysOp page list) PageFlags_Reserved * 1 :SHL: 7 ; physical page has been reserved for future use. It can still be allocated to arbitrary DAs, but only the program that reserved it can claim it for exclusive use (PageFlags_Unavailable)
PageFlags_Unavailable * 1 :SHL: 15 ; physical page has been claimed by someone for exclusive use (can't be requested by PreGrow handler or PMP PhysOp page list)
; Dynamic area handler reason codes ; Dynamic area handler reason codes
...@@ -96,6 +97,8 @@ DAHandler_TestShrink * 4 ; Shrinkable DAs: Find abount can shrink ...@@ -96,6 +97,8 @@ DAHandler_TestShrink * 4 ; Shrinkable DAs: Find abount can shrink
DAHandler_Abort * 5 ; ROL abortable DAs DAHandler_Abort * 5 ; ROL abortable DAs
DAHandler_ResizePMP * 6 ; PMP DAs: Called on OS_ChangeDynamicArea DAHandler_ResizePMP * 6 ; PMP DAs: Called on OS_ChangeDynamicArea
DAHandler_RESV * &56534552 ; "RESV" magic value for use by PreGrow handlers
; OS_Memory reason codes ; OS_Memory reason codes
OSMemReason_Convert * 0 ; Convert PA <-> LA <-> PN, alter cacheability OSMemReason_Convert * 0 ; Convert PA <-> LA <-> PN, alter cacheability
...@@ -114,6 +117,7 @@ OSMemReason_DMAPrep * 19 ; Convert PA <-> LA, perform cache maint ...@@ -114,6 +117,7 @@ OSMemReason_DMAPrep * 19 ; Convert PA <-> LA, perform cache maint
OSMemReason_Compatibility * 20 ; Get/set compatibility settings OSMemReason_Compatibility * 20 ; Get/set compatibility settings
OSMemReason_MapIO64Permanent * 21 ; Map in IO area from 64-bit space OSMemReason_MapIO64Permanent * 21 ; Map in IO area from 64-bit space
OSMemReason_AccessPhysAddr64 * 22 ; Temporarily map in 64-bit phys addr OSMemReason_AccessPhysAddr64 * 22 ; Temporarily map in 64-bit phys addr
OSMemReason_ReservePages * 23 ; Reserve (or un-reserve) pages
OSMemReason_CheckMemoryAccess * 24 ; Return attributes/permissions for a logical address range OSMemReason_CheckMemoryAccess * 24 ; Return attributes/permissions for a logical address range
; OS_Memory 17/18 permission flags ; OS_Memory 17/18 permission flags
......
...@@ -512,6 +512,9 @@ AMB_LazyFixUp ROUT ...@@ -512,6 +512,9 @@ AMB_LazyFixUp ROUT
LDR r5,[r5,#CamEntriesPointer] LDR r5,[r5,#CamEntriesPointer]
ADD r5,r5,r3,LSL #CAM_EntrySizeLog2 ;r5 -> CAM entry affected ADD r5,r5,r3,LSL #CAM_EntrySizeLog2 ;r5 -> CAM entry affected
MOVS r0,r0,LSL #Log2PageSize ;address is now ordinary again, and must be non-zero MOVS r0,r0,LSL #Log2PageSize ;address is now ordinary again, and must be non-zero
LDR r12,[r5,#CAM_PageFlags]
AND r12,r12,#StickyPageFlags
ORR r1,r1,r12
ASSERT CAM_LogAddr=0 ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4 ASSERT CAM_PageFlags=4
STMIA r5,{r0,r1} ;update CAM entry STMIA r5,{r0,r1} ;update CAM entry
...@@ -674,11 +677,19 @@ AMB_movepagesin_L2PT ROUT ...@@ -674,11 +677,19 @@ AMB_movepagesin_L2PT ROUT
;exit: $reg = addr of CAM entry ;exit: $reg = addr of CAM entry
; ;
MACRO MACRO
UpdateCAM $reg UpdateCAM $reg,$temp
ADD $reg,r11,$reg,LSL #CAM_EntrySizeLog2 ;r0 -> CAM entry for 1st page ADD $reg,r11,$reg,LSL #CAM_EntrySizeLog2 ;r0 -> CAM entry for 1st page
LDR $temp,[$reg,#CAM_PageFlags]
AND $temp,$temp,#StickyPageFlags
ORR $temp,$temp,lr
[ $temp > r9
ASSERT CAM_LogAddr=0 ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4 ASSERT CAM_PageFlags=4
STMIA $reg,{r9,lr} ;store logical addr,PPL STMIA $reg,{r9,$temp} ;store logical addr,PPL
|
STR r9,[$reg,#CAM_LogAddr]
STR $temp,[$reg,#CAM_PageFlags]
]
MEND MEND
; ---------------------------------------------------------------------------------- ; ----------------------------------------------------------------------------------
...@@ -694,10 +705,10 @@ AMB_movepagesin_L2PT ROUT ...@@ -694,10 +705,10 @@ AMB_movepagesin_L2PT ROUT
; r10 -> page list ; r10 -> page list
; ;
AMB_movepagesin_CAM ROUT AMB_movepagesin_CAM ROUT
Entry "r0-r11" Entry "r0-r12"
MOV lr,r9 BIC lr,r9,#StickyPageFlags
MOV r9,r3 MOV r9,r3
LDR r11,=ZeroPage LDR r11,=ZeroPage
LDR r11,[r11,#CamEntriesPointer] ;r11 -> CAM LDR r11,[r11,#CamEntriesPointer] ;r11 -> CAM
...@@ -706,21 +717,21 @@ AMB_movepagesin_CAM ROUT ...@@ -706,21 +717,21 @@ AMB_movepagesin_CAM ROUT
BLT %FT20 BLT %FT20
10 10
LDMIA r10!,{r0-r7} ;next 8 page numbers LDMIA r10!,{r0-r7} ;next 8 page numbers
UpdateCAM r0 UpdateCAM r0,r12
ADD r9,r9,#PageSize ;next logical addr ADD r9,r9,#PageSize ;next logical addr
UpdateCAM r1 UpdateCAM r1,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r2 UpdateCAM r2,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r3 UpdateCAM r3,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r4 UpdateCAM r4,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r5 UpdateCAM r5,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r6 UpdateCAM r6,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
UpdateCAM r7 UpdateCAM r7,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
SUB r8,r8,#8 SUB r8,r8,#8
CMP r8,#8 CMP r8,#8
...@@ -730,7 +741,7 @@ AMB_movepagesin_CAM ROUT ...@@ -730,7 +741,7 @@ AMB_movepagesin_CAM ROUT
EXIT EQ EXIT EQ
30 30
LDR r0,[r10],#4 LDR r0,[r10],#4
UpdateCAM r0 UpdateCAM r0,r12
ADD r9,r9,#PageSize ADD r9,r9,#PageSize
SUBS r8,r8,#1 SUBS r8,r8,#1
BNE %BT30 BNE %BT30
...@@ -748,9 +759,9 @@ AMB_movepagesin_CAM ROUT ...@@ -748,9 +759,9 @@ AMB_movepagesin_CAM ROUT
; r10 -> page list ; r10 -> page list
; ;
AMB_movepagesout_CAM ROUT AMB_movepagesout_CAM ROUT
Entry "r0-r11" Entry "r0-r12"
MOV lr,r9 BIC lr,r9,#StickyPageFlags
LDR r9,=DuffEntry LDR r9,=DuffEntry
LDR r11,=ZeroPage LDR r11,=ZeroPage
LDR r11,[r11,#CamEntriesPointer] ;r11 -> CAM LDR r11,[r11,#CamEntriesPointer] ;r11 -> CAM
...@@ -759,14 +770,14 @@ AMB_movepagesout_CAM ROUT ...@@ -759,14 +770,14 @@ AMB_movepagesout_CAM ROUT
BLT %FT20 BLT %FT20
10 10
LDMIA r10!,{r0-r7} ;next 8 page numbers LDMIA r10!,{r0-r7} ;next 8 page numbers
UpdateCAM r0 UpdateCAM r0,r12
UpdateCAM r1 UpdateCAM r1,r12
UpdateCAM r2 UpdateCAM r2,r12
UpdateCAM r3 UpdateCAM r3,r12
UpdateCAM r4 UpdateCAM r4,r12
UpdateCAM r5 UpdateCAM r5,r12
UpdateCAM r6 UpdateCAM r6,r12
UpdateCAM r7 UpdateCAM r7,r12
SUB r8,r8,#8 SUB r8,r8,#8
CMP r8,#8 CMP r8,#8
BGE %BT10 BGE %BT10
...@@ -775,7 +786,7 @@ AMB_movepagesout_CAM ROUT ...@@ -775,7 +786,7 @@ AMB_movepagesout_CAM ROUT
EXIT EQ EXIT EQ
30 30
LDR r0,[r10],#4 LDR r0,[r10],#4
UpdateCAM r0 UpdateCAM r0,r12
SUBS r8,r8,#1 SUBS r8,r8,#1
BNE %BT30 BNE %BT30
EXIT EXIT
......
...@@ -71,9 +71,13 @@ BangCamUpdate ROUT ...@@ -71,9 +71,13 @@ BangCamUpdate ROUT
ASSERT CAM_LogAddr=0 ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4 ASSERT CAM_PageFlags=4
LDMIA r1, {r0, r6} ; r0 = current logaddress, r6 = current PPL LDMIA r1, {r0, r6} ; r0 = current logaddress, r6 = current PPL
Push "r0, r6" ; save old logical address, PPL
BIC r4, r11, #PageFlags_Unsafe BIC r4, r11, #PageFlags_Unsafe
BIC r4, r4, #StickyPageFlags
AND r6, r6, #StickyPageFlags
ORR r4, r4, r6
STMIA r1, {r3, r4} ; store new address, PPL STMIA r1, {r3, r4} ; store new address, PPL
Push "r0, r6" ; save old logical address, PPL
LDR r1, =ZeroPage+PhysRamTable ; go through phys RAM table LDR r1, =ZeroPage+PhysRamTable ; go through phys RAM table
MOV r6, r2 ; make copy of r2 (since that must be preserved) MOV r6, r2 ; make copy of r2 (since that must be preserved)
10 10
......
...@@ -591,9 +591,10 @@ SetMemMapEntries_Code ROUT ...@@ -591,9 +591,10 @@ SetMemMapEntries_Code ROUT
MOVHS r11, #AreaFlags_Duff MOVHS r11, #AreaFlags_Duff
; Ensure PMP membership flag is retained - just in case caller doesn't ; Ensure PMP membership flag is retained - just in case caller doesn't
; know what he's doing ; know what he's doing
LDR r6, =StickyPageFlags+DynAreaFlags_PMP
LDR r0, [r9, r2, LSL #CAM_EntrySizeLog2] LDR r0, [r9, r2, LSL #CAM_EntrySizeLog2]
AND r0, r0, #DynAreaFlags_PMP AND r0, r0, r6
BIC r11, r11, #DynAreaFlags_PMP BIC r11, r11, r6
ORR r11, r11, r0 ORR r11, r11, r0
BL BangCamUpdate BL BangCamUpdate
B %BT01 B %BT01
...@@ -640,6 +641,15 @@ DynAreaFlags_PMPLogOpAccessMask * (DynAreaFlags_AccessMask :OR: PageFlags_Unavai ...@@ -640,6 +641,15 @@ DynAreaFlags_PMPLogOpAccessMask * (DynAreaFlags_AccessMask :OR: PageFlags_Unavai
; PMP PhysOp can specify these flags ; PMP PhysOp can specify these flags
DynAreaFlags_PMPPhysOpAccessMask * PageFlags_Unavailable DynAreaFlags_PMPPhysOpAccessMask * PageFlags_Unavailable
; Sticky page flags - they're preserved over most operations, including changes
; in ownership
StickyPageFlags * PageFlags_Reserved
; Ensure user can't specify any sticky flags for the main calls
; If this changes, lots of code will need checking/updating!
ASSERT (DynAreaFlags_AccessMask :AND: StickyPageFlags) = 0
ASSERT (DynAreaFlags_PMPLogOpAccessMask :AND: StickyPageFlags) = 0
ASSERT (DynAreaFlags_PMPPhysOpAccessMask :AND: StickyPageFlags) = 0
DynamicAreaSWI Entry DynamicAreaSWI Entry
BL DynAreaSub BL DynAreaSub
...@@ -2337,7 +2347,11 @@ DynArea_Locate Entry "r2-r5" ...@@ -2337,7 +2347,11 @@ DynArea_Locate Entry "r2-r5"
; phys page index -1 to release ; phys page index -1 to release
; phys page index -2 to let kernel pick page ; phys page index -2 to let kernel pick page
; otherwise page number to use ; otherwise page number to use
; page flags are defined by DynAreaFlags_PMPPhysOpAccessMask ;
; page flags are defined by DynAreaFlags_PMPPhysOpAccessMask, and
; PageFlags_Reserved to allow claiming of pages previously reserved
; via OS_Memory 23
;
; r3 = number of entries ; r3 = number of entries
; ;
; out: r0-r1 preserved (error if not all of region successfully updated) ; out: r0-r1 preserved (error if not all of region successfully updated)
...@@ -2373,7 +2387,7 @@ DynArea_PMP_PhysOp ROUT ...@@ -2373,7 +2387,7 @@ DynArea_PMP_PhysOp ROUT
LDR r0, [r7, #FreePoolDANode+DANode_PMPSize] LDR r0, [r7, #FreePoolDANode+DANode_PMPSize]
LDR r7, [r7, #CamEntriesPointer] LDR r7, [r7, #CamEntriesPointer]
CMP r0, r3 CMP r0, r3
BHS %FT45 BHS %FT30
; Free pool may be too small - scan the page list and the PMP to work out exactly how many pages are required ; Free pool may be too small - scan the page list and the PMP to work out exactly how many pages are required
; If there aren't enough, try growing the free pool (shrink app space, shrink shrinkables, etc.) ; If there aren't enough, try growing the free pool (shrink app space, shrink shrinkables, etc.)
MOV r12, #0 MOV r12, #0
...@@ -2421,7 +2435,7 @@ DynArea_PMP_PhysOp ROUT ...@@ -2421,7 +2435,7 @@ DynArea_PMP_PhysOp ROUT
FRAMLDR r2 FRAMLDR r2
FRAMLDR r3 FRAMLDR r3
45 30
LDR r12, [r10, #DANode_PMPSize] LDR r12, [r10, #DANode_PMPSize]
; Usage in main loop: ; Usage in main loop:
; r2 -> input page list ; r2 -> input page list
...@@ -2436,7 +2450,7 @@ DynArea_PMP_PhysOp ROUT ...@@ -2436,7 +2450,7 @@ DynArea_PMP_PhysOp ROUT
; r11 = MaxCamEntry ; r11 = MaxCamEntry
; r12 = current PMPSize ; r12 = current PMPSize
; r0, r1 temp ; r0, r1 temp
50 40
SUBS r3, r3, #1 SUBS r3, r3, #1
BLO %FT80 BLO %FT80
LDMIA r2!, {r4-r6} LDMIA r2!, {r4-r6}
...@@ -2447,25 +2461,49 @@ DynArea_PMP_PhysOp ROUT ...@@ -2447,25 +2461,49 @@ DynArea_PMP_PhysOp ROUT
CMP r5, #-3 CMP r5, #-3
CMPLS r11, r5 CMPLS r11, r5
BLS %FT93 BLS %FT93
42
AND r6, r6, #DynAreaFlags_PMPPhysOpAccessMask AND r6, r6, #DynAreaFlags_PMPPhysOpAccessMask
; Look up the page that's currently in the PMP ; Look up the page that's currently in the PMP
LDR r0, [r8, r4, LSL #2] LDR r0, [r8, r4, LSL #2]
TEQ r0, r5 TEQ r0, r5
BNE %FT52 BNE %FT50
CMP r0, #-1
BEQ %BT40
45
; Page is there - check/update flags ; Page is there - check/update flags
ADD r0, r7, r0, LSL #CAM_EntrySizeLog2 ADD r0, r7, r0, LSL #CAM_EntrySizeLog2
LDR r1, [r0, #CAM_PageFlags] LDR r1, [r0, #CAM_PageFlags]
BIC lr, r1, #DynAreaFlags_PMPPhysOpAccessMask BIC lr, r1, #DynAreaFlags_PMPPhysOpAccessMask
ORR lr, lr, r6 ORR lr, lr, r6
TEQ r1, lr TEQ r1, lr
STRNE lr, [r0, #CAM_PageFlags] BEQ %BT40
B %BT50 ; Only allow Reserved pages to become Unavailable if we're given the magic password
52 TST r6, #PageFlags_Unavailable ; Unavailable requested?
TSTNE r1, #PageFlags_Reserved ; And currently Reserved?
BEQ %FT49
TST r1, #PageFlags_Unavailable ; Was it already Unavailable?
LDREQ r6, [r2, #-4]
TSTEQ r6, #PageFlags_Reserved ; Or was Reserved specified in the page list?
BNE %FT49 ; Then we're fine
; Attempting to claim a Reserved page without the proper permission.
; If we're allowed to kernel-pick a page, swap in a replacement. Else
; raise an error.
CMP r5, #-2
BNE %FT96
LDR r0, [r8, r4, LSL #2]
BL GetNonReservedPage
BVS %FT96
; Success, retry this page modification
B %BT42
49
STR lr, [r0, #CAM_PageFlags]
B %BT40
50
; Do we need to release the existing page? ; Do we need to release the existing page?
CMP r0, #-1 CMP r0, #-1
BEQ %FT55 BEQ %FT55
CMP r5, #-2 CMP r5, #-2
BEQ %BT50 ; Page is currently there, and we want a kernel picked page -> no action required BEQ %BT45 ; Page is currently there, and we want a kernel picked page
; A page is currently there, but we either want to release it or to swap in a different page. Start by releasing the existing page. ; A page is currently there, but we either want to release it or to swap in a different page. Start by releasing the existing page.
; TODO - if we're swapping with another page we'll probably want to preserve the contents (have a flag to control behaviour) ; TODO - if we're swapping with another page we'll probably want to preserve the contents (have a flag to control behaviour)
; Check page isn't mapped in ; Check page isn't mapped in
...@@ -2488,6 +2526,9 @@ DynArea_PMP_PhysOp ROUT ...@@ -2488,6 +2526,9 @@ DynArea_PMP_PhysOp ROUT
LDR r3, [r4, #DANode_Flags] LDR r3, [r4, #DANode_Flags]
LDR lr, =DynAreaFlags_AccessMask LDR lr, =DynAreaFlags_AccessMask
AND r3, r3, lr AND r3, r3, lr
LDR lr, [r2, #CAM_PageFlags]
AND lr, lr, #StickyPageFlags
ORR r3, r3, lr
ASSERT CAM_PageFlags=4 ASSERT CAM_PageFlags=4
ASSERT CAM_PMP=8 ASSERT CAM_PMP=8
ASSERT CAM_PMPIndex=12 ASSERT CAM_PMPIndex=12
...@@ -2502,36 +2543,63 @@ DynArea_PMP_PhysOp ROUT ...@@ -2502,36 +2543,63 @@ DynArea_PMP_PhysOp ROUT
55 55
; Map in new page if required ; Map in new page if required
CMP r5, #-2 CMP r5, #-2
BHI %BT50 ; i.e. -1 BHI %BT40 ; i.e. -1
BLO %FT60 BLO %FT60 ; specific page
[ PMPDebug [ PMPDebug
DebugTX "Kernel-picking page" DebugTX "Kernel-picking page"
] ]
; Kernel-picked page required. Pick the last page from the free pool. ; Kernel-picked page required. Find a suitable page in the free pool.
LDR r0, =ZeroPage+FreePoolDANode LDR r0, =ZeroPage+FreePoolDANode
LDR r1, [r0, #DANode_PMP] LDR r1, [r0, #DANode_PMP]
LDR r5, [r0, #DANode_PMPSize] LDR lr, [r0, #DANode_PMPSize]
SUBS r5, r5, #1 Push "r4,r8"
BLO %FT95 ; Shouldn't happen 56
STR r5, [r0, #DANode_PMPSize] SUBS lr, lr, #1
LDR r5, [r1, r5, LSL #2]! Pull "r4,r8",LO
BLO %FT95
LDR r5, [r1, lr, LSL #2]
TST r6, #PageFlags_Unavailable
BEQ %FT57
; Caller is requesting exclusive use of the page, so avoid picking a
; reserved page.
; Note: For this case, we don't allow the caller to specify
; PageFlags_Reserved to allow use of reserved pages, because we have no
; way of knowing whether a particular page was reserved by them or by
; someone else.
ADD r4, r7, r5, LSL #CAM_EntrySizeLog2
LDR r4, [r4, #CAM_PageFlags]
TST r4, #PageFlags_Reserved
BNE %BT56
57
LDR r4, [r0, #DANode_PMPSize]
SUB r4, r4, #1
STR r4, [r0, #DANode_PMPSize]
CMP r4, lr
LDRNE r8, [r1, r4, LSL #2] ; Within the PMP, shuffle last free pool page down to replace the page we're taking
STRNE r8, [r1, lr, LSL #2]
ADDNE r8, r7, r8, LSL #CAM_EntrySizeLog2
STRNE lr, [r8, #CAM_PMPIndex] ; And update the CAM
MOV r0, #-1 MOV r0, #-1
STR r0, [r1] STR r0, [r1, r4, LSL #2]
; Add to our PMP Pull "r4,r8"
; Add page r5 to our PMP
59 59
STR r5, [r8, r4, LSL #2] STR r5, [r8, r4, LSL #2]
ADD r5, r7, r5, LSL #CAM_EntrySizeLog2 ADD r5, r7, r5, LSL #CAM_EntrySizeLog2
LDR r0, [r10, #DANode_Flags] ; Use default DA flags, modified by flags given in page list LDR r0, [r10, #DANode_Flags] ; Use default DA flags, modified by flags given in page list
LDR r1, =DynAreaFlags_AccessMask :AND: :NOT: DynAreaFlags_PMPPhysOpAccessMask LDR r1, =DynAreaFlags_AccessMask :AND: :NOT: DynAreaFlags_PMPPhysOpAccessMask
MOV lr, r4
AND r0, r0, r1 AND r0, r0, r1
ORR r0, r0, r6 ORR r0, r0, r6
LDR lr, [r5, #CAM_PageFlags]
AND lr, lr, #StickyPageFlags
ORR r0, r0, lr
MOV lr, r4
ASSERT CAM_PageFlags=4 ASSERT CAM_PageFlags=4
ASSERT CAM_PMP=8 ASSERT CAM_PMP=8
ASSERT CAM_PMPIndex=12 ASSERT CAM_PMPIndex=12
STMIB r5, {r0,r10,lr} STMIB r5, {r0,r10,lr}
ADD r12, r12, #1 ADD r12, r12, #1
B %BT50 B %BT40
60 60
; Check that the requested page isn't locked ; Check that the requested page isn't locked
ADD r0, r7, r5, LSL #CAM_EntrySizeLog2 ADD r0, r7, r5, LSL #CAM_EntrySizeLog2
...@@ -2545,6 +2613,14 @@ DynArea_PMP_PhysOp ROUT ...@@ -2545,6 +2613,14 @@ DynArea_PMP_PhysOp ROUT
] ]
TST r1, #PageFlags_Unavailable TST r1, #PageFlags_Unavailable
BNE %FT95 BNE %FT95
; Only allow Reserved pages to become Unavailable if we're given the magic password
TST r6, #PageFlags_Unavailable ; Unavailable requested?
TSTNE r1, #PageFlags_Reserved ; And currently Reserved?
BEQ %FT605
LDR lr, [r2, #-4]
TST lr, #PageFlags_Reserved
BEQ %FT96
605
; Construct a dummy DANode on the stack so we can use a Batcall to map ; Construct a dummy DANode on the stack so we can use a Batcall to map
; in the page ; in the page
SUB sp, sp, #DANode_NodeSize SUB sp, sp, #DANode_NodeSize
...@@ -2582,7 +2658,7 @@ DynArea_PMP_PhysOp ROUT ...@@ -2582,7 +2658,7 @@ DynArea_PMP_PhysOp ROUT
] ]
; Replace handler routine with our own ; Replace handler routine with our own
STR r5, [sp, #DANode_Workspace] ; Required page number is handler param STR r5, [sp, #DANode_Workspace] ; Required page number is handler param
ADR r0, PMPGrowHandler ADR r0, PMPGrowHandlerReserved ; If we're dealing with a reserved page, we must specify "RESV", otherwise OS_ChangeDynamicArea won't let us move it
STR r0, [sp, #DANode_Handler] STR r0, [sp, #DANode_Handler]
; Make the call ; Make the call
Push "r2" Push "r2"
...@@ -2655,6 +2731,13 @@ DynArea_PMP_PhysOp ROUT ...@@ -2655,6 +2731,13 @@ DynArea_PMP_PhysOp ROUT
ADRL r0, ErrorBlock_ChDynamNotAllMoved ADRL r0, ErrorBlock_ChDynamNotAllMoved
B %FT98 B %FT98
96
[ PMPDebug
DebugTX "-> physop can't use page"
]
ADRL r0, ErrorBlock_CantGetPhysMem
B %FT98
98 98
[ International [ International
BL TranslateError BL TranslateError
...@@ -2708,12 +2791,132 @@ PMPMemoryMoved ROUT ...@@ -2708,12 +2791,132 @@ PMPMemoryMoved ROUT
] ]
EXITS EXITS
PMPGrowHandlerReserved ROUT
TEQ r0, #DAHandler_PreGrow
LDREQ r0, =DAHandler_RESV
STREQ r12, [r1]
MOV pc, lr