From da847c792c26ee6888c66228eb25c026baf0eab5 Mon Sep 17 00:00:00 2001 From: Mike Stephens <mstephen@gitlab.riscosopen.org> Date: Fri, 10 Nov 2000 14:41:16 +0000 Subject: [PATCH] reintroduce Ursula AMBControl, recoded with generic ARMop style, not debugged yet Version 5.35, 4.79.2.12. Tagged as 'Kernel-5_35-4_79_2_12' --- VersionASM | 16 +- VersionNum | 19 +- hdr/KernelWS | 27 +-- hdr/Options | 6 + s/AMBControl/AMB | 7 + s/AMBControl/Memory | 84 ++++---- s/AMBControl/Options | 48 ++++- s/AMBControl/Workspace | 102 ++++++--- s/AMBControl/allocate | 39 +--- s/AMBControl/deallocate | 6 +- s/AMBControl/growp | 16 +- s/AMBControl/growshrink | 18 +- s/AMBControl/main | 112 +++++++--- s/AMBControl/mapslot | 43 +++- s/AMBControl/memmap | 460 ++++++++++++++++++++++++++-------------- s/AMBControl/service | 128 +++++++++-- s/AMBControl/shrinkp | 24 ++- s/ARMops | 67 ++++++ 18 files changed, 861 insertions(+), 361 deletions(-) diff --git a/VersionASM b/VersionASM index 88c7f791..89a7571f 100644 --- a/VersionASM +++ b/VersionASM @@ -9,12 +9,16 @@ GBLS Module_ApplicationDate2 GBLS Module_ApplicationDate4 GBLS Module_HelpVersion + GBLS Module_ComponentName + GBLS Module_ComponentPath Module_MajorVersion SETS "5.35" Module_Version SETA 535 -Module_MinorVersion SETS "4.79.2.11" -Module_Date SETS "20 Oct 2000" -Module_ApplicationDate2 SETS "20-Oct-00" -Module_ApplicationDate4 SETS "20-Oct-2000" -Module_FullVersion SETS "5.35 (4.79.2.11)" -Module_HelpVersion SETS "5.35 (20 Oct 2000) 4.79.2.11" +Module_MinorVersion SETS "4.79.2.12" +Module_Date SETS "10 Nov 2000" +Module_ApplicationDate2 SETS "10-Nov-00" +Module_ApplicationDate4 SETS "10-Nov-2000" +Module_ComponentName SETS "Kernel" +Module_ComponentPath SETS "RiscOS/Sources/Kernel" +Module_FullVersion SETS "5.35 (4.79.2.12)" +Module_HelpVersion SETS "5.35 (10 Nov 2000) 4.79.2.12" END diff --git a/VersionNum b/VersionNum index f55412af..fccf4cfe 100644 --- a/VersionNum +++ b/VersionNum @@ -4,16 +4,19 @@ * */ #define Module_MajorVersion_CMHG 5.35 -#define Module_MinorVersion_CMHG 4.79.2.11 -#define Module_Date_CMHG 20 Oct 2000 +#define Module_MinorVersion_CMHG 4.79.2.12 +#define Module_Date_CMHG 10 Nov 2000 #define Module_MajorVersion "5.35" #define Module_Version 535 -#define Module_MinorVersion "4.79.2.11" -#define Module_Date "20 Oct 2000" +#define Module_MinorVersion "4.79.2.12" +#define Module_Date "10 Nov 2000" -#define Module_ApplicationDate2 "20-Oct-00" -#define Module_ApplicationDate4 "20-Oct-2000" +#define Module_ApplicationDate2 "10-Nov-00" +#define Module_ApplicationDate4 "10-Nov-2000" -#define Module_FullVersion "5.35 (4.79.2.11)" -#define Module_HelpVersion "5.35 (20 Oct 2000) (4.79.2.11)" +#define Module_ComponentName "Kernel" +#define Module_ComponentPath "RiscOS/Sources/Kernel" + +#define Module_FullVersion "5.35 (4.79.2.12)" +#define Module_HelpVersion "5.35 (10 Nov 2000) (4.79.2.12)" diff --git a/hdr/KernelWS b/hdr/KernelWS index bbff4ad6..38a00650 100644 --- a/hdr/KernelWS +++ b/hdr/KernelWS @@ -1171,18 +1171,21 @@ ProcessorArch # 1 AlignSpace -Proc_Cache_CleanInvalidateAll # 4 -Proc_Cache_CleanAll # 4 -Proc_Cache_InvalidateAll # 4 -Proc_TLB_InvalidateAll # 4 -Proc_TLB_InvalidateEntry # 4 -Proc_WriteBuffer_Drain # 4 -Proc_IMB_Full # 4 -Proc_IMB_Range # 4 -Proc_MMU_Changing # 4 -Proc_MMU_ChangingEntry # 4 -Proc_MMU_ChangingUncached # 4 -Proc_MMU_ChangingUncachedEntry # 4 +Proc_Cache_CleanInvalidateAll # 4 +Proc_Cache_CleanAll # 4 +Proc_Cache_InvalidateAll # 4 +Proc_Cache_RangeThreshold # 4 +Proc_TLB_InvalidateAll # 4 +Proc_TLB_InvalidateEntry # 4 +Proc_WriteBuffer_Drain # 4 +Proc_IMB_Full # 4 +Proc_IMB_Range # 4 +Proc_MMU_Changing # 4 +Proc_MMU_ChangingEntry # 4 +Proc_MMU_ChangingUncached # 4 +Proc_MMU_ChangingUncachedEntry # 4 +Proc_MMU_ChangingEntries # 4 +Proc_MMU_ChangingUncachedEntries # 4 ] diff --git a/hdr/Options b/hdr/Options index 80d86b60..e5d22e7d 100644 --- a/hdr/Options +++ b/hdr/Options @@ -236,6 +236,7 @@ ARM6support SETL {TRUE} ;despatch and wider SWI hashing) ; ;any ARM + ; GBLL ChocolateSysHeap ;whether to save cost of SysHeap block claim/release for common cases (eg. callback blocks) ;also reduces SysHeap stress by using fewer blocks in total GBLL ChocolateOSMod ;whether to reduce SysHeap stress in module handling @@ -244,11 +245,16 @@ ARM6support SETL {TRUE} GBLL ChocolateService ;whether to implement fast module service call distribution (uses table introduced ;into module format by Ursula API + ;possibly enabled at run time for some ARMs only + ; + GBLL ChocolateAMB ;whether to compile support for Lazy task swapping + ChocolateSysHeap SETL {TRUE} ChocolateOSMod SETL {TRUE} ChocolateSysVars SETL {TRUE} ChocolateOscli SETL {TRUE} ChocolateService SETL {TRUE} +ChocolateAMB SETL {TRUE} [ ChocolateSysHeap GBLA MaxChocolateCBBlocks ;max quick CallBack blocks available at any one time (else ordinary heap nodes used) GBLA MaxChocolateSVBlocks ;max quick Software Vector blocks available at any one time (else ordinary heap nodes used) diff --git a/s/AMBControl/AMB b/s/AMBControl/AMB index 51de20a8..c0088427 100644 --- a/s/AMBControl/AMB +++ b/s/AMBControl/AMB @@ -13,6 +13,13 @@ ; limitations under the License. ; +; Implements OS_AMBControl (takes care of application memory management for Wimp) +; +; Nov 1995 mjs development version originated as Module +; Jul 1996 mjs fully implemented in kernel for RISC OS 3.70 +; Mar 1997 mjs performance enhancements for Ursula OS +; Oct 2000 mjs Ursula code resurrected for 32-bit HALised kernel, hoorah! + GET s.AMBControl.Options GET s.AMBControl.Workspace GET s.AMBControl.main diff --git a/s/AMBControl/Memory b/s/AMBControl/Memory index 043d7318..8fc2f47e 100644 --- a/s/AMBControl/Memory +++ b/s/AMBControl/Memory @@ -14,57 +14,47 @@ ; ; > s.Memory -; lifted from Wimp source (v3.67) +; Small veneer between AMBControl's memory block requirements and OS_Heap, +; using system heap. This is changed since Ursula - old code called OS_Module +; and claimed blocks from RMA, which is an anachronism since code is in +; the kernel. -; this OS_Module equivalent looks at ptr-4 which the Heap Manager uses -; to store the real size of the block. In this way the memory use is -; more efficient (especially when extending a block) and RMA should -; fragment less often. - - -XROS_Module Entry - TEQ R0,#6 - TEQNE R0,#7 - TEQNE R0,#13 - SWINE XOS_Module - EXIT NE - TEQ R0,#6 - BEQ ros_claim - TEQ R0,#7 - BEQ ros_free -; extend - Push "R3-R5" - LDR R4,[R2,#-8] - LDR R5,[R2,#-4]! - ADD R5,R5,R3 ; R5 is proposed new size - SUB R4,R4,#4 - CMP R4,R5 - CMPGE R3,#0 - BLT %FT02 - STR R5,[R2],#4 ; enough space so just store - Pull "R3-R5" -; can never error - CLRV - EXIT -02 - SUB R3,R5,R4 - SWI XOS_Module - STRVC R5,[R2],#4 - Pull "R3-R5" - EXIT +; quantise sizes to reduce heap stress +; +AMBblockQ * 64 -ros_free - SUB R2,R2,#4 - SWI XOS_Module - EXIT +;in: r3=size +;out: r2 -> block, r0 corrupted +; +AMB_BlockClaim ROUT + Push "r1,r3,lr" + ADD r3,r3,#AMBblockQ - 1 + BIC r3,r3,#AMBblockQ - 1 + BL ClaimSysHeapNode + Pull "r1,r3,pc" + +;in: r2 -> block +;out: r0 corrupted +; +AMB_BlockFree ROUT + Push "r1,lr" + BL FreeSysHeapNode + Pull "r1,pc" -ros_claim - ADD R3,R3,#4 - SWI XOS_Module - STRVC R3,[R2],#4 ; so modptr-4 = amount asked for + 4 - SUB R3,R3,#4 ; needs to be preserved - EXIT +;in: r2 -> block, r3 = new size +;out: r2 -> new block, r0 corrupted +; +AMB_BlockResize ROUT + Push "r1,r3,lr" + ADD r3,r3,#AMBblockQ - 1 + BIC r3,r3,#AMBblockQ - 1 + LDR r1,[r2,#-4] ;pick up OS_Heap's size word (naughty!) + SUB r1,r1,#8 ;heap size will be 8 more than quantised size + SUBS r3,r3,r1 ;required size change + MOVNE r0, #HeapReason_ExtendBlock + BLNE DoSysHeapOpWithExtension + Pull "r1,r3,pc" END diff --git a/s/AMBControl/Options b/s/AMBControl/Options index 185d552b..fc4c2424 100644 --- a/s/AMBControl/Options +++ b/s/AMBControl/Options @@ -13,10 +13,12 @@ ; limitations under the License. ; +; > s.Options + AMBMagicNodeID * &4E424D41 ;"AMBN" AMBInitialMaxNodes * 256 -AMBGrowMaxNodes * 64 +AMBGrowMaxNodes * 64 ;not used now AMBControl is in kernel ;Bin pages by physical address, for quick mapping from page number to @@ -30,15 +32,49 @@ AMBPhysBinMask * &7F ApplicationStart * (32*1024) -AbsMaxAppSize * (28*1024*1024) ;28 Mb application space limit for RISC OS -;maximum logical space size cleaned by range strategy -; -AMB_ARMA_CleanRange_thresh * 256*1024 +AbsMaxAppSize * (28*1024*1024) ;28 Mb application space limit for RISC OS +AbsMaxAppPages * (AbsMaxAppSize:SHR:Log2PageSize) ;and same limit expressed in Pages + [ ChocolateAMB +AMBMIRegWords * (AbsMaxAppPages+31) :SHR: 5 ;no. of words for AMBMappedInRegister + ;convenient to set this at fixed max size + ;(only 896 bytes for 28Mb AppSpace) + ] - GBLL ValidateAMBHandles ; whether to check handles given to AppMAMBan +;whether to check handles given to AMBControl - not very useful when in kernel +; + GBLL ValidateAMBHandles ValidateAMBHandles SETL {FALSE} +;performance enhancements originally introduced for Ursula OS +; +; ChocolateAMB - if {FALSE}, disables all AMBControl crazy chocolate flavour enhancements +; +; AMB_LazyMapIn - if {TRUE}, individual pages of a swapped-in task are only mapped in when +; necessary (happens via abort mechanism). This typically makes the swapping +; cost much lower and much less sensitive to large slot size. The worst case +; swapping cost is still good (abort mechanism cost is very small). +; Probably only worth supporting this on ARMs with simple instruction restart +; after abort (originally StrongARM revT or later for Ursula) +; +; AMB_LimpidFreePool - if {TRUE}, the cache(s) can be assumed to be clear with respect to the FreePool +; when AMBControl fetches pages from it. This allows AMBControl to avoid any +; cache clean/flush for moving pages out of the FreePool. This assumption is +; valid if either: FreePool pages are uncacheable; or FreePool pages are +; never used in situ; or FreePool pages are flushed after use in situ. +; +; AMB_ChocTrace - if {TRUE}, keep trace info for some enhanced code calls and data (probably development only) + + GBLL AMB_LazyMapIn + GBLL AMB_LimpidFreePool + GBLL AMB_ChocTrace + +AMB_LazyMapIn SETL {TRUE} :LAND: ChocolateAMB +AMB_LimpidFreePool SETL {TRUE} :LAND: ChocolateAMB ;allowed because FreePool is currently marked uncacheable + ;current implementation assumes uncacheability as criterion + +AMB_ChocTrace SETL {FALSE} :LAND: ChocolateAMB ;development only + END diff --git a/s/AMBControl/Workspace b/s/AMBControl/Workspace index bbdb7b92..0d2524b2 100644 --- a/s/AMBControl/Workspace +++ b/s/AMBControl/Workspace @@ -14,36 +14,76 @@ ; ; > s.Workspace -; task node format - ^ 0 -AMBNode_id # 4 ; magic identifier -AMBNode_handle # 4 ; handle for external reference -AMBNode_prev # 4 ; -> previous node -AMBNode_next # 4 ; -> next node -AMBNode_pagetable # 0 ; data comprising page table from here on -AMBNode_Npages # 4 ; no. of pages in page list -AMBNode_startaddr # 4 ; logical address of first page (-1 means nowhere) -AMBNode_PPL # 4 ; PPL ('page protection level') for pages -AMBNode_pages # 0 ; list of pages from here on (1 word per page no.) - - -; main workspace - ^ 0,R12 -AMBNhandles # 4 ; total handles available -AMBNtasks # 4 ; No. of tasks currently allocated -AMBMappedInNode # 4 ; node ptr of mapped-in task, or 0 for none - -;ptr to node handle array (1 word per entry) -AMBNodeHandles # 4 - -;ptr to physical page bin array -AMBPhysBin # 4 -AMBPhysBinEntries # 4 - -;dummy node (0 page entries) forms anchor of circular node list -;this averts the need for any special case for add or remove node -AMBAnchorNode # (AMBNode_pages - AMBNode_id) - -AMBmaxwork * :INDEX:@ + +; +;task node format +; + ^ 0 +AMBNode_HdrStart # 0 +AMBNode_id # 4 ;magic identifier +AMBNode_handle # 4 ;handle for external reference +AMBNode_prev # 4 ;ptr to previous node +AMBNode_next # 4 ;ptr to next node +AMBNode_pagetable # 0 ;data comprising page table from here on +AMBNode_Npages # 4 ;no. of pages in page list +AMBNode_startaddr # 4 ;logical address of first page (-1 means nowhere) +AMBNode_PPL # 4 ;PPL ('page protection level') for pages +AMBNode_pages # 0 ;list of page numbers from here on (1 word per page) +AMBNode_HdrEnd # 0 +; +AMBNode_HdrSize * AMBNode_HdrEnd - AMBNode_HdrStart + + +; +;main workspace +; + ^ 0,R12 +AMBNhandles # 4 ;total handles available +AMBNtasks # 4 ;no. of tasks currently allocated +AMBMappedInNode # 4 ;node ptr of mapped-in task, or 0 for none +AMBNodeHandles # 4 ;ptr to node handle array (1 word per entry) +AMBPhysBin # 4 ;ptr to physical page bin array +AMBPhysBinEntries # 4 ;no. of entries in physical page bin array +AMBAnchorNode # AMBNode_HdrSize ;dummy node - see note (1) below +; + [ ChocolateAMB +AMBFlags # 4 ;bits defined as below +AMBNContextSwitches # 4 ;monotonic count of total no. of task map-in's (eg. for performance tracing) + [ AMB_ChocTrace +AMBNmakeunsparse # 4 ;count of no. of calls to AMB_MakeUnsparse +AMBNmemmoveshrink # 4 ;count of no. of Service_MemoryMoved shrink fixups +AMBNmemmovegrow # 4 ;count of no. of Service_MemoryMoved grow fixups + ] +AMBMappedInNpages # 4 ;no. of pages of MappedInNode really mapped in +AMBMappedInRegister # AMBMIRegWords*4 ;1 bit per page - see note (2) below + ] +; +AMBmaxwork * :INDEX:@ ;size of main workspace (assumed to be multiple of 4 bytes) + + + [ ChocolateAMB +; +;definition of bits in AMBFlags +; +AMBFlag_LazyMapIn_disable * &80000000 ;bit 31 LazyMapIn permanent disable (eg. not running on StrongARM) +AMBFlag_LazyMapIn_suspend * &40000000 ;bit 30 LazyMapIn suspend (controlled via AMB SWI) + ;bits 29..0 reserved (0) +; + ] + +;Notes: +; +; (1) AMBAnchorNode is a dummy node with 0 page entries that forms the anchor of a +; circular node list. This averts the need for any special case for adding or +; removing nodes. +; +; (2) AMBMappedInRegister is a 'bitmap' of the current page mapping status of the +; MappedInNode. This supports AMB_LazyMapIn. Bit n corresponds to the n'th page +; of the MappedInNode; if it is set, then that page is currently mapped in. The +; bits are packed 'little endian', so bit 0 is the LSB of word 0, bit 31 is +; the MSB of word 0, bit 32 is the LSB of word 1 and so on. The bits are only +; significant when AMBMappedInNpages is > 0 (and then all AMBNode_Npages bits +; for the MappedInNode are significant). + END diff --git a/s/AMBControl/allocate b/s/AMBControl/allocate index e067c63a..432bab77 100644 --- a/s/AMBControl/allocate +++ b/s/AMBControl/allocate @@ -27,6 +27,8 @@ allocate Push "R0,R3,R4,LR" +; Debug AMB,"allocate ",r0,r1 + MOV R3,#AbsMaxAppSize SUB R3,R3,#ApplicationStart MOV R3,R3,LSR #Log2PageSize ;R3 = absolute max app pages @@ -40,44 +42,16 @@ allocate CMP R4,#0 ;any handles available? BNE %FT01 - [ {TRUE} ; give up + ; give up Pull "R0,R3,R4,LR" ADR R0,err_nomorehandles B SLVK_SetV - ] - - [ {FALSE} ; oh no we don't, we're not a module now -;try to extend handles array - MOV R2,R0 - MOV R0,#ModHandReason_ExtendBlock - MOV R3,#(GrowMaxNodes:SHL:2) - SWI XOS_Module - BVS alloc_done - MOV R0,R2 - STR R0,AMBNodeHandles ;in case block has moved - LDR R3,AMBNhandles - STR R3,[R0] ;first free handle now - ADD LR,R3,#GrowMaxNodes - STR LR,AMBNhandles - ADD R4,R0,R3,LSL #2 - ADD R3,R3,#1 -;put new handles on free list -00 - STR R3,[R4],#4 - ADD R3,R3,#1 - CMP R3,LR - BNE %BT00 - MOV R3,#0 - STR R3,[R4] ;0 = end of list - LDR R4,[R0] ;now we have a useable handle - ] 01 ;get memory for node - from RMA MOV R3,#(AMBNode_pages - AMBNode_id) ;size excluding page list ADD R3,R3,R1,LSL #2 ;plus one word per page - MOV R0,#ModHandReason_Claim - BL XROS_Module + BL AMB_BlockClaim BVS alloc_done ;remember handle in node @@ -128,16 +102,17 @@ alloc_ok STR R2,AMBMappedInNode ;allocated node is also mapped in LDR R2,[R2,#AMBNode_handle] ;change address to handle + CLRV alloc_done +; Debug AMB,"<alloc ",r1,r2 STRVS R0,[SP] Pull "R0,R3,R4,LR" B SLVK_TestV ;free page table space and return 0 handle alloc_zeropages - MOV R0,#ModHandReason_Free - BL XROS_Module + BL AMB_BlockFree MOV R1,#0 MOV R2,#0 B alloc_done diff --git a/s/AMBControl/deallocate b/s/AMBControl/deallocate index ba8caaf4..2e9b47c6 100644 --- a/s/AMBControl/deallocate +++ b/s/AMBControl/deallocate @@ -27,6 +27,8 @@ deallocate Push "R0-R3,LR" +; Debug AMB,"deallocate ",r0,r2 + [ ValidateAMBHandles ;validate handle LDR R0,AMBNhandles @@ -76,8 +78,8 @@ deallocate STREQ R0,AMBMappedInNode ;free node (at R2) - MOV R0,#ModHandReason_Free - BL XROS_Module + BL AMB_BlockFree + dealloc_done STRVS R0,[SP] Pull "R0-R3,LR" diff --git a/s/AMBControl/growp b/s/AMBControl/growp index 88126db7..e3d47757 100644 --- a/s/AMBControl/growp +++ b/s/AMBControl/growp @@ -62,10 +62,21 @@ growpages ROUT ; R5 := start logical address BL AMB_FindMemMapEntries ;find page nos. + [ AMB_LazyMapIn + LDR R5,AMBFlags + TST R5,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend + ; + MOVEQ R5,#-1 ;map the pages to Nowhere initially + MOVEQ R6,#AP_Duff + LDRNE R5,[R0,#AMBNode_startaddr] + ADDNE R5,R5,R7,LSL #Log2PageSize ;R5 := first new page new address + LDRNE R6,[R0,#AMBNode_PPL] ;R6 := dest PPL flags + | LDR R5,[R0,#AMBNode_startaddr] ADD R5,R5,R7,LSL #Log2PageSize ;R5 := first new page new address LDR R6,[R0,#AMBNode_PPL] ;R6 := dest PPL flags - + ] + ; ;entry: R3 = no. of pages, R4 -> list of page entries, ; R5 = start logical address, R6 = PPL BL AMB_SetMemMapEntries ;remap @@ -81,7 +92,8 @@ growpages ROUT STR R5,[R6,#MemLimit] ;update MemLimit 02 - STRVS R0,[SP] +;;; STRVS R0,[SP] + CLRV Pull "R0-R7,PC" [ ShrinkableDAs diff --git a/s/AMBControl/growshrink b/s/AMBControl/growshrink index b28a568a..29ea8634 100644 --- a/s/AMBControl/growshrink +++ b/s/AMBControl/growshrink @@ -31,6 +31,8 @@ growshrink Push "R0,R2,R4,R5,LR" +; Debug AMB,"growshrink ",r0,r1,r2 + MOV R5,#AbsMaxAppSize SUB R5,R5,#ApplicationStart MOV R5,R5,LSR #Log2PageSize ;R5 = absolute max app pages @@ -102,13 +104,12 @@ gs_done grwshr_node Push "R0,R3,R4,LR" CMP R1,#0 - BEQ grwshrn_free ;shrunk to nothing - SUB R4,R1,R5 - MOV R3,R4,ASL #2 - MOV R4,R2 ;so we can check for moved block - MOV R0,#ModHandReason_ExtendBlock - BL XROS_Module - MOVVS R2,R4 ;in case block ptr not preserved on error + BEQ grwshrn_free ;shrunk to nothing + MOV R3,#(AMBNode_pages - AMBNode_id) ;new size excluding page list + ADD R3,R3,R1,LSL #2 ;new size + MOV R4,R2 ;so we can check for moved block + BL AMB_BlockResize + MOVVS R2,R4 ;in case block ptr not preserved on error BVS grwshrn_done ;fix-up links if block has moved CMP R4,R2 @@ -152,8 +153,7 @@ grwshrn_free MOVEQ R0,#0 STREQ R0,AMBMappedInNode - MOV R0,#ModHandReason_Free - BL XROS_Module + BL AMB_BlockFree MOVVC R2,#0 B grwshrn_done diff --git a/s/AMBControl/main b/s/AMBControl/main index ee8ca68d..af358305 100644 --- a/s/AMBControl/main +++ b/s/AMBControl/main @@ -13,28 +13,36 @@ ; limitations under the License. ; -; AMBControl - takes care of application memory management (for Wimp) - -;Nov 95 - Started by mjs +; > s.main ;;; Initialisation ; AMBControl_Init Push "R0-R4,R12,LR" +;claim main workspace LDR R3,=AMBmaxwork BL ClaimSysHeapNode -;;; BVS err_cantclaim - this should not happen +;;; BVS err_cantclaim - this should not happen ;don't store ws pointer till end of initialise - service routines must ;know when initialise is not yet complete ; MOV R12,R2 -;block for handle array +;zero-init workspace + MOV R1,#0 + LDR R3,=AMBmaxwork + ADD R3,R3,R2 +00 + STR R1,[R2],#4 + CMP R2,R3 + BLO %BT00 + +;claim block for handle array MOV R3,#(AMBInitialMaxNodes:SHL:2) BL ClaimSysHeapNode -;;; BVS err_cantclaim +;;; BVS err_cantclaim STR R2,AMBNodeHandles ;put all handles on free list (entry 0 is used as hdr of free list) @@ -49,7 +57,7 @@ AMBControl_Init MOV R0,#0 ; = end of list STR R0,[R2] -;block for PhysBin array +;claim block for PhysBin array LDR R3,=MaxCamEntry LDR R3,[R3] ADD R3,R3,#1 ;no. of RAM pages extant @@ -57,7 +65,7 @@ AMBControl_Init STR R3,AMBPhysBinEntries MOV R3,R3,LSL #2 ;1 word per entry BL ClaimSysHeapNode -;;; BVS err_cantclaim +;;; BVS err_cantclaim STR R2,AMBPhysBin ;init PhysBin @@ -77,22 +85,21 @@ AMBControl_Init SUBS R4,R4,#1 BNE %BT03 -; init anchor node stuff etc. - MOV R0,#0 - STR R0,AMBNtasks - STR R0,AMBMappedInNode +;init any other workspace that shouldn't init as 0 ADR R1,AMBAnchorNode - MOV R3,R1 - STR R0,[R1],#4 ; node id = 0 for ank node (not a real node!) - STR R0,[R1],#4 ; handle = 0 - STR R3,[R1],#4 ; prev (starts -> ank node) - STR R3,[R1],#4 ; next (starts -> ank node) - STR R0,[R1],#4 ; Npages - STR R0,[R1],#4 ; startaddr - STR R0,[R1],#4 ; PPL - + STR R1,[R1,#AMBNode_prev] ;anchor prev initially -> anchor (empty list) + STR R1,[R1,#AMBNode_next] ;anchor next initially -> anchor (empty list) + [ AMB_LazyMapIn + ; currently always disable, need to sort out when abort fix up is supported + ; and for which ARMs + ; + ! 0, "AMBControl currently always disables LazyMapIn (needs abort handler hooks)" + ; + MOV R1,#AMBFlag_LazyMapIn_disable + STR R1,AMBFlags + ] MOV R0,#AMBControl_ws - STR R12,[R0] ;now initialisation is complete + STR R12,[R0] ;now initialisation is complete Pull "R0-R4,R12,PC" @@ -119,7 +126,11 @@ reasons0 B growshrink ;2 B mapslot ;3 B readinfo ;4 + [ AMB_LazyMapIn + B laziness ;5 + | B reserved ;5 + ] B reserved ;6 B reserved ;7 B mjs_info ;8 - system reason code, dumps info to buffer @@ -128,6 +139,58 @@ reasons1 B SLVK_SetV + [ AMB_LazyMapIn +; +;entry: R0=5 (reason),R1=1 for lazy on, 0 for lazy off, -1 to read lazy only +;exit: R1=new lazy value, after any restrictions of platform applied +; +;action: if reading only, if lazy disabled, or if new state = current, do nothing +; if state is changing, map out any current node, change state, map in any current node +; +laziness ROUT + Push "R2-R3,LR" + CMP R1,#-1 + BEQ %FT20 + LDR R2,AMBFlags ;R2 := current flags + TST R2,#AMBFlag_LazyMapIn_disable ;disable is permanent + BNE %FT20 + CMP R1,#0 + MOV R1,R2 + ORREQ R1,R1,#AMBFlag_LazyMapIn_suspend + BICNE R1,R1,#AMBFlag_LazyMapIn_suspend ;R1 := new flags + EOR R3,R1,R2 + TST R3,#AMBFlag_LazyMapIn_suspend ;is suspend status changing? + BEQ %FT20 + LDR R3,AMBMappedInNode + CMP R3,#0 + BEQ %FT10 + Push "R0-R3" + MOV R0,#3 + MOV R1,#-1 + LDR R2,[R3,#AMBNode_handle] + SWI XOS_AMBControl ;map out current node + Pull "R0-R3" +10 + STR R1,AMBFlags + CMP R3,#0 + BEQ %FT20 + Push "R0-R3" + MOV R0,#3 + MOV R1,#0 + LDR R2,[R3,#AMBNode_handle] + SWI XOS_AMBControl ;map in current node + Pull "R0-R3" +20 + LDR R1,AMBFlags + TST R1,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend + MOVEQ R1,#1 + MOVNE R1,#0 + Pull "R2-R3,LR" + B SLVK +; + ] ;AMB_LazyMapIn + + ;entry: R0=8 (reason),R1 -> buffer (say 4k for up to 255 tasks) ;exit: buffer filled: ; 0 Ntasks @@ -171,11 +234,6 @@ reserved ;;; errors (sod internationalisation) -;;;err_cantclaim -;;; DCD 0 -;;; DCB "AMBControl failed to claim workspace",0 -;;; ALIGN - err_badreason DCD 0 DCB "bad AMBControl reason code",0 diff --git a/s/AMBControl/mapslot b/s/AMBControl/mapslot index 7e816894..509b6743 100644 --- a/s/AMBControl/mapslot +++ b/s/AMBControl/mapslot @@ -23,8 +23,14 @@ ; R2 = handle ; R3,R4 used if bit 8 set - see mapsome ; +; Note that if bit 8 is clear, the use is restricted to mapping in or out of +; whole slots only. Hence if bit 8 is clear, behaviour is undefined unless +; R1 is one of: 0, &8000 or -1. +; mapslot +; Debug AMB,"mapslot",r0,r1,r2,r3,r4 + TST R0,#&100 ;if bit 8 set, then mapsome BNE mapsome @@ -71,16 +77,48 @@ mapslot BEQ ms_done ;else do map only if not already mapped in, and asked to map in ms_domap - CMP R5,#-1 + CMP R5,#-1 ;EQ if it is a map out LDREQ R6,=DuffEntry MOVNE R6,#ApplicationStart STR R6,[R1,#AMBNode_startaddr] MOVEQ R6,#AP_Duff MOVNE R6,#0 STR R6,[R1,#AMBNode_PPL] + + [ AMB_LazyMapIn + LDRNE R2,AMBNContextSwitches + ADDNE R2,R2,#1 + STRNE R2,AMBNContextSwitches + LDR R2,AMBFlags + TST R2,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend + BNE ms_cantbelazy + ; + ; - if map out, do sparse map out of whole page list then zero AMBMappedInNpages + ; - if map in, just zero AMBMappedInNpages (last map out will have cleared AMBMappedInRegister) + ; + MOV R2,R5 + CMP R2,#-1 + LDREQ R3,AMBMappedInNpages + ADREQ R5,AMBMappedInRegister + LDREQ R6,[R1,#AMBNode_Npages] + ;entry: R3 = no. pages mapped in, R4 -> list of page entries, + ; R5 -> bitmap of pages mapped in, R6=total no. of pages in page list + BLEQ AMB_SetMemMapEntries_SparseMapOut + MOV R3,#0 + STR R3,AMBMappedInNpages + MOV R5,R2 + B ms_mapdone +ms_cantbelazy ;entry: R3 = no. of pages, R4 -> list of page entries, ; R5 := start logical address, R6 = PPL BL AMB_SetMemMapEntries +ms_mapdone + | + ;entry: R3 = no. of pages, R4 -> list of page entries, + ; R5 := start logical address, R6 = PPL + BL AMB_SetMemMapEntries + ] + ;update AppSpace kernel stuff LDR R2,[R1,#AMBNode_Npages] LDR R3,=AppSpaceDANode @@ -96,7 +134,8 @@ ms_domap STR R3,AMBMappedInNode ms_done - STRVS R0,[SP] +;;; STRVS R0,[SP] + CLRV Pull "R0-R6,LR" B SLVK_TestV diff --git a/s/AMBControl/memmap b/s/AMBControl/memmap index 862e1461..40d1a4cb 100644 --- a/s/AMBControl/memmap +++ b/s/AMBControl/memmap @@ -15,25 +15,117 @@ ; > s.memmap ; low level memory mapping - -; ************************************************************************************** ; - -;convert page number in $reg to L2PT entry (physical address+protection bits), +; ---------------------------------------------------------------------------------- +; +;convert page number in $pnum to L2PT entry (physical address+protection bits), ;using PhysBin table for speed ; -;entry: lr -> PhysBin table, r11 = protection bits -;exit: r12 corrupted +;entry: $ptable -> PhysBin table, $pbits = protection bits +;exit: $temp corrupted ; MACRO - PageNumToL2PT $reg - BIC r12,$reg,#(3:SHL:(AMBPhysBinShift-2)) ;word alignment for PhysBin lookup - LDR r12,[lr,r12,LSR #(AMBPhysBinShift-2)] ;start physical address of bin - AND $reg,$reg,#AMBPhysBinMask ;no. pages into bin - ADD $reg,r12,$reg,LSL #Log2PageSize ;physical address of page - ORR $reg,$reg,r11 ;munge in protection bits + PageNumToL2PT $pnum,$ptable,$pbits,$temp + BIC $temp,$pnum,#(3:SHL:(AMBPhysBinShift-2)) ;word alignment for PhysBin lookup + LDR $temp,[$ptable,$temp,LSR #(AMBPhysBinShift-2)] ;start physical address of bin + AND $pnum,$pnum,#AMBPhysBinMask ;no. pages into bin + ADD $pnum,$temp,$pnum,LSL #Log2PageSize ;physical address of page + ORR $pnum,$pnum,$pbits ;munge in protection bits MEND + + [ AMB_LazyMapIn + +; ---------------------------------------------------------------------------------- +; +;AMB_LazyFixUp +; +; *Only* for ARMs where the abort handler can restart instructions +; +; Routine to be used in abort handlers (in abort32 mode), that checks to see if abort +; is expected, and fixes things up if so, ready to restart instruction. +; +; Fix up consists of mapping in affected page, and updating AMBMappedInRegister. This +; may seem like a lot of work, but remember that the L2PT and CAM updates for each page are +; needed anyway in non-lazy scheme, so there is really only a housekeeping overhead. +; +; There is no cache clean/flush consideration here, since the map is a map in from Nowhere. +; TLB flush consideration is left to main abort handler code - in fact there may not +; be a TLB flush consideration at all, if ARM TLB can be assumed not to cache an +; entry which is a translation fault, as seems rational. +; +; entry: r0 = aborting address (data address for data abort, instruction address +; for prefetch abort), r1-r7 trashable, no stack +; exit: r0 = non-zero if abort was expected and fixed up, zero if not +; +AMB_LazyFixUp ROUT + ; not hooked in yet! + ! 0, "AMB_LazyFixUp needs hooking into abort handlers" + MOV r7,r12 + MOV r12,#AMBControl_ws + LDR r12,[r12] + CMP r12,#0 + BEQ %FT20 + SUBS r0,r0,#ApplicationStart + BMI %FT20 + MOV r0,r0,LSR #Log2PageSize ;address now in terms of pages from ApplicationStart + LDR r1,AMBMappedInNode + CMP r1,#0 + BEQ %FT20 + LDR r2,[r1,#AMBNode_Npages] + CMP r2,r0 + BLS %FT20 +; +;need not check MappedInRegister first, since if abort has happened in range of current +;AppSpace, then the page can be assumed to be mapped out +; + ADD r1,r1,#AMBNode_pages + ADD r1,r1,r0,LSL #2 ;r1 -> page involved, in node page list + LDR r2,AMBPhysBin + ! 0, "AMB_LazyFixup a symbol for L2PT protection bits would be handy" + MOV r3,#&FF0 + ORR r3,r3,#&E ;&FFE = L2PT protection bits for ordinary page + LDR r4,[r1] + MOV r6,r4 + PageNumToL2PT r4,r2,r3,r5 +; +;here, r6 = page number of page involved, r4 = new L2PT entry value to map in page +; + LDR r2,AMBMappedInNpages ;for convenience, update bitmap etc. here... + ADD r2,r2,#1 + STR r2,AMBMappedInNpages + ADR r2,AMBMappedInRegister + ADD r2,r2,r0,LSR #5-2 ;r2 -> bitmap word affected + BIC r2,r2,#3 + AND r3,r0,#31 + MOV r5,#1 + MOV r5,r5,LSL r3 ;mask for bit affected in bitmap word + LDR r3,[r2] + ORR r3,r3,r5 + STR r3,[r2] + + ADD r0,r0,#ApplicationStart:SHR:Log2PageSize ;address now in terms of pages from 0 + MOV r5,#L2PT + STR r4,[r5,r0,LSL #2] ;update L2PT + + MOV r5,#0 + LDR r5,[r5,#CamEntriesPointer] + ADD r5,r5,r6,LSL #3 ;r5 -> CAM entry affected + MOV r0,r0,LSL #Log2PageSize ;address is now ordinary again, and must be non-zero + MOV r1,#0 ;0 = AP for ordinary page + STMIA r5,{r0,r1} ;update CAM entry + MOV r12,r7 + MOV pc,lr ;r0 is non-zero +20 + MOV r0,#0 + MOV r12,r7 + MOV pc,lr + + ] ;AMB_LazyMapIn + + +; ---------------------------------------------------------------------------------- +; ;AMB_movepagesin_L2PT ; ;updates L2PT for new logical page positions, does not update CAM @@ -54,16 +146,16 @@ AMB_movepagesin_L2PT ROUT CMP r8,#8 BLT %FT20 10 - LDMIA r10!,{r0-r7} ;next 8 page numbers - PageNumToL2PT r0 - PageNumToL2PT r1 - PageNumToL2PT r2 - PageNumToL2PT r3 - PageNumToL2PT r4 - PageNumToL2PT r5 - PageNumToL2PT r6 - PageNumToL2PT r7 - STMIA r9!,{r0-r7} ;write 8 L2PT entries + LDMIA r10!,{r0-r7} ;next 8 page numbers + PageNumToL2PT r0,lr,r11,r12 + PageNumToL2PT r1,lr,r11,r12 + PageNumToL2PT r2,lr,r11,r12 + PageNumToL2PT r3,lr,r11,r12 + PageNumToL2PT r4,lr,r11,r12 + PageNumToL2PT r5,lr,r11,r12 + PageNumToL2PT r6,lr,r11,r12 + PageNumToL2PT r7,lr,r11,r12 + STMIA r9!,{r0-r7} ;write 8 L2PT entries SUB r8,r8,#8 CMP r8,#8 BGE %BT10 @@ -72,17 +164,15 @@ AMB_movepagesin_L2PT ROUT BEQ %FT35 30 LDR r0,[r10],#4 - PageNumToL2PT r0 + PageNumToL2PT r0,lr,r11,r12 STR r0,[r9],#4 SUBS r8,r8,#1 BNE %BT30 35 - ARM_read_ID r0 - AND r0,r0,#&F000 - CMP r0,#&A000 - ARMA_drain_WB EQ ;because L2PT area for AppSpace will be bufferable Pull "r0-r10,r12,pc" +; ---------------------------------------------------------------------------------- +; ;update CAM entry for page number in $reg ; ;entry: r11 -> CAM, r9 = logical addr of page, lr = PPL of page @@ -94,6 +184,8 @@ AMB_movepagesin_L2PT ROUT STMIA $reg,{r9,lr} ;store logical addr,PPL MEND +; ---------------------------------------------------------------------------------- +; ;AMB_movepagesin_CAM ; ;updates CAM, does not update L2PT @@ -147,7 +239,8 @@ AMB_movepagesin_CAM ROUT BNE %BT30 Pull "r0-r11,pc" - +; ---------------------------------------------------------------------------------- +; ;AMB_movepagesout_CAM ; ;updates CAM, does not update L2PT @@ -190,7 +283,8 @@ AMB_movepagesout_CAM ROUT BNE %BT30 Pull "r0-r11,pc" - +; ---------------------------------------------------------------------------------- +; ;AMB_movepagesout_L2PT ; ;updates L2PT for old logical page positions, does not update CAM @@ -229,40 +323,10 @@ AMB_movepagesout_L2PT ROUT SUBS r8,r8,#1 BNE %BT30 35 - ARM_read_ID r0 - AND r0,r0,#&F000 - CMP r0,#&A000 - ARMA_drain_WB EQ ;because L2PT area for AppSpace will be bufferable Pull "r0-r8,pc" - [ ARM810support - ;Previously supported ARMs all tolerate cache (clean and) flush _after_ - ;remapping - ARMs 6,7 because there is no clean, StrongARM because the cache - ;writebacks use physical address. - ;ARM810 does not support clean of writeback cache after remapping, since - ;writebacks use virtual address. Rather than completely restructure code, - ;this routine is called before remapping where necessary, and cleans/flushes - ;if it finds we are running on ARM 810. - ; - ;corrupts r3 - ; -AMB_cachecleanflush_ifARM810 - ARM_read_ID r3 - AND r3,r3,#&F000 - CMP r3,#&8000 - MOVNE pc,lr ;not ARM8 - [ ARM810cleanflushbroken - Push "lr" - ARM8_cleanflush_IDC r3,lr - Pull "pc" - | - ARM8_cleanflush_IDC r3 - MOV pc,lr - ] - - ] ;ARM810support - -;************************************************************************** +; ---------------------------------------------------------------------------------- +; ; AMB_SetMemMapEntries: ; ; entry: @@ -271,9 +335,8 @@ AMB_cachecleanflush_ifARM810 ; R5 = start logical address of mapping (-1 means 'out of the way') ; R6 = PPL ('page protection level') for mapping ; -; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - AMB_SetMemMapEntries ROUT + Push "r0-r4,r7-r11,lr" MOVS r8,r3 @@ -298,8 +361,13 @@ AMB_SetMemMapEntries ROUT LDR r2,[r10] ;page number of 1st page MOV r7,#0 LDR r7,[r7,#CamEntriesPointer] ;r7 -> CAM - ADD r1,r7,r2,LSL #3 + ADD r1,r7,r2,LSL #3 ;r1 -> CAM entry for 1st page + [ AMB_LimpidFreePool + LDR r4,[r1] ;fetch old logical addr. of 1st page from CAM + LDR r3,[r1,#4] ;fetch old PPL of 1st page from CAM + | LDR r4,[r1] ;fetch old logical addr. of 1st page from CAM + ] CMP r5,#-1 BEQ AMB_smme_mapout @@ -309,135 +377,199 @@ AMB_SetMemMapEntries ROUT BEQ AMB_smme_mapin ;map from somewhere to somewhere (should be App Space <-> Free Pool) -;could be an optimise here if source is FreePool and we know that FreePool -;has not been used - ie. no need to clean/flush cache(s) - not done yet (requires -;sorting of Wimp_ClaimFreeMemory) - [ ARM810support - BL AMB_cachecleanflush_ifARM810 +; + [ AMB_LimpidFreePool + ;can avoid cache clean/flush for moving pages out from FreePool, since FreePool pages are uncacheable + ; + TST r3, #DynAreaFlags_NotCacheable ;test PPL of 1st page for not cacheable bit set + BEQ AMB_smme_mapnotlimpid ;if clear, must do full map somewhere with cache clean/flush + ; + ;this should be map FreePool -> App Space then + ; + MOV r0,r4 ;address of 1st page + MOV r1,r8 ;number of pages + MOV r3,#0 + ARMop MMU_ChangingUncachedEntries,,,r3 ;no cache worries, hoorah + MOV r3,r5 + BL AMB_movepagesout_L2PT ;unmap 'em from where they are + BL AMB_movepagesin_L2PT ;map 'em to where they now be + BL AMB_movepagesin_CAM ;keep the bloomin' soft CAM up to date + Pull "r0-r4,r7-r11, pc" +AMB_smme_mapnotlimpid ] +; + MOV r0,r4 ;address of 1st page + MOV r1,r8 ;number of pages + MOV r3,#0 + ARMop MMU_ChangingEntries,,,r3 ; MOV r3,r5 BL AMB_movepagesout_L2PT BL AMB_movepagesin_L2PT BL AMB_movepagesin_CAM - B AMB_smme_cachecleanflush ;needed because of the map out from source + Pull "r0-r4,r7-r11, pc" -;all pages sourced from same old logical page 'nowhere' +;all pages sourced from same old logical page Nowhere, ie. pages currently mapped out, no cache worries +; AMB_smme_mapin + MOV r0,r4 ;address of 1st page + MOV r1,r8 ;number of pages + MOV r3,#0 + ARMop MMU_ChangingUncachedEntries,,,r3 ;TLB coherency, possibly not needed (TLBs shouldn't cache 0 entries) MOV r3,r5 BL AMB_movepagesin_L2PT BL AMB_movepagesin_CAM -;don't need to flush cache at end of mapin (already coherent, since -;nothing mapped in before), but do need to flush TLB (eg. TLB will cache -;access denial for app space after mapout) - B AMB_smme_TLBflush + Pull "r0-r4,r7-r11, pc" -;all pages destined for same new logical page 'nowhere' +;all pages destined for same new logical page Nowhere, ie. mapping them out +; AMB_smme_mapout - [ ARM810support - BL AMB_cachecleanflush_ifARM810 - ] + MOV r0,r4 ;address of 1st page + MOV r1,r8 ;number of pages + MOV r3,#0 + ARMop MMU_ChangingEntries,,,r3 ; LDR r3,=DuffEntry BL AMB_movepagesout_L2PT BL AMB_movepagesout_CAM -;(clean and) flush cache(s) appropriately, then flush TLB(s) -AMB_smme_cachecleanflush - ARM_read_ID r0 - AND r0,r0,#&F000 - [ ARM810support - CMP r0,#&8000 ;cache clean/flush done before remapping if ARM810 - ARM8_flush_TLB EQ - Pull "r0-r4,r7-r11, pc",EQ - ] - CMP r0,#&A000 - BEQ AMB_smme_cachecleanflush_strongarm - - MOV r11, #0 - ARMop MMU_Changing,,,r11 +AMB_smme_exit Pull "r0-r4,r7-r11, pc" -AMB_smme_cachecleanflush_strongarm -;we have a StrongARM then + + [ AMB_LazyMapIn + +; ---------------------------------------------------------------------------------- ; -;here, r4 = old logical addr. of 1st page, r8 = no. of pages +; AMB_SetMemMapEntries_SparseMapOut: ; -;StrongARM lets us clean data cache (DC) after remapping, because it writes back by -;physical address. ; - MOV r0,r4 ;r0 := start address for clean/flush - ADD r1,r0,r8,LSL #Log2PageSize ;r1 := end address for clean/flush (exclusive) +; entry: +; R3 = no. of pages currently mapped in (0=none) +; R4 -> list of page entries (1 word per entry, giving page no.) +; R5 -> bitmap of pages mapped in (1 bit per page in whole page list) +; R6 = total no. of pages in slot +; +AMB_SetMemMapEntries_SparseMapOut ROUT -;Cleaning a sufficiently small space by range will be quicker, because of the fixed -;memory reading cost for a full DC clean. A sufficiently large space will be better handled -;by full clean, because of the huge number of clean/flush line instructions for the range -;case. We use a threshold to switch between the two schemes. The value of the threshold -;depends on memory speed, core speed etc. but is not particularly critical. + CMP r3,#0 + MOVEQ pc,lr + Push "r0-r11,lr" - SUB r2,r1,r0 - CMP r2,#AMB_ARMA_CleanRange_thresh - BLO AMB_smme_StrongARM_flushrange + MOV r10,r4 ;ptr to page list + MOV r7,#0 + LDR r7,[r7,#CamEntriesPointer] ;r7 -> CAM + LDR lr,=L2PT ;lr -> L2PT + MOV r9,#AP_Duff ;permissions for DuffEntry + LDR r1,=DuffEntry ;means Nowhere, in CAM + MOV r4,#ApplicationStart ;log. address of first page + MOV r2,#0 ;r2 is zero during sparse map out + + ;if the number of pages mapped in is small enough, we'll do cache/TLB coherency on + ;just those pages, else global (performance decision, threshold probably not critical) + + ARMop Cache_RangeThreshold,,,r2 ;returns threshold (bytes) in r0 + CMP r3,r0,LSR #Log2PageSize + MOVLO r6,#0 ;r6 := 0 if we are to do coherency as we go + BLO %FT10 ;let's do it + + Push "lr" ;global coherency + ARMop MMU_Changing,,,r2 + Pull "lr" + B %FT10 + +;skip next 32 pages then continue +06 + ADD r10,r10,#32*4 + ADD r4,r4,#32*PageSize + +;find the sparsely mapped pages, map them out, doing coherency as we go if enabled +10 + MOV r8,#1 ;initial bitmap mask for new bitmap word + LDR r11,[r5],#4 ;next word of bitmap + CMP r11,#0 ;if next 32 bits of bitmap clear, skip + BEQ %BT06 ;skip loop must terminate if r3 > 0 +12 + TST r11,r8 ;page is currently mapped in if bit set + BEQ %FT16 + TEQ r6, #0 + BNE %FT14 ;check for coherency as we go + Push "lr" + MOV r0,r4 ;address of page + ARMop MMU_ChangingEntry,,,r2 + Pull "lr" +14 + LDR r0,[r10] ;page no. + ADD r0,r7,r0,LSL #3 ;r0 -> CAM entry for page + STMIA r0,{r1,r9} ;CAM entry for page set to DuffEntry,AP_Duff + STR r2,[lr,r4,LSR #(Log2PageSize-2)] ;L2PT entry for page set to 0 (means translation fault) + SUBS r3,r3,#1 + STREQ r2,[r5,#-4] ;make sure we clear last word of bitmap, and... + BEQ %FT20 ;done +16 + ADD r10,r10,#4 ;next page no. + ADD r4,r4,#PageSize ;next logical address + MOVS r8,r8,LSL #1 ;if 32 bits processed... + BNE %BT12 + STR r2,[r5,#-4] ;zero word of bitmap we've just traversed (r2 is 0) + B %BT10 - MOV r2,#ARMA_Cleaner_flipflop - LDR r1,[r2] - EOR r1,r1,#16*1024 - STR r1,[r2] - ARMA_clean_DC r1,r2,r3 ;effectively, fully clean/flush wrt non-interrupt stuff - ARMA_drain_WB - ARMA_flush_IC WithoutNOPs ;do *not* flush DC - may be interrupt stuff in it - MOV r0,r0 ;NOPs to ensure 4 instructions after IC flush before return - MOV r0,r0 - ARMA_flush_TLBs - Pull "r0-r4,r7-r11, pc" +20 + Pull "r0-r11,pc" -AMB_smme_StrongARM_flushrange - - [ SAcleanflushbroken ; ARMA_cleanflush_DCentry instruction seems to be ineffective. -01 - ARMA_clean_DCentry r0 - ARMA_flush_DCentry r0 - ADD r0,r0,#32 - ARMA_clean_DCentry r0 - ARMA_flush_DCentry r0 - ADD r0,r0,#32 - ARMA_clean_DCentry r0 - ARMA_flush_DCentry r0 - ADD r0,r0,#32 - ARMA_clean_DCentry r0 - ARMA_flush_DCentry r0 - ADD r0,r0,#32 - CMP r0,r1 - BLO %BT01 ;loop to clean DC over logical range - | -01 - ARMA_cleanflush_DCentry r0 - ADD r0,r0,#32 - ARMA_cleanflush_DCentry r0 - ADD r0,r0,#32 - ARMA_cleanflush_DCentry r0 - ADD r0,r0,#32 - ARMA_cleanflush_DCentry r0 - ADD r0,r0,#32 - CMP r0,r1 - BLO %BT01 ;loop to clean DC over logical range - ] - ARMA_drain_WB - ARMA_flush_IC WithoutNOPs - MOV r0,r0 ;NOPs to ensure 4 instructions after IC flush before return - MOV r0,r0 - ARMA_flush_TLBs - Pull "r0-r4,r7-r11, pc" +; ---------------------------------------------------------------------------------- +; +; AMB_MakeUnsparse +; +; entry: r0 = size of area (at top of current slot) to ensure is not sparsely mapped +; +; action: walk over space involved, to force abort handler fix up to map in any +; pages not already there +; +AMB_MakeUnsparse ROUT + Push "r0-r2,r12,lr" +; Debug AMB,"AMB_MakeUnsparse r0",r0 + ADD r0,r0,#PageSize + SUB r0,r0,#1 + MOVS r0,r0,LSR #Log2PageSize + BEQ %FT20 + MOV r12,#AMBControl_ws + LDR r12,[r12] + CMP r12,#0 + BEQ %FT20 + LDR r1,AMBMappedInNode + CMP r1,#0 + BEQ %FT20 + LDR r2,AMBFlags + TST r2,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend + BNE %FT20 + [ AMB_ChocTrace + LDR r2,AMBNmakeunsparse + ADD r2,r2,#1 + STR r2,AMBNmakeunsparse + ] + LDR r2,[r1,#AMBNode_Npages] +; Debug AMB,"AMB_MakeUnsparse pages Npages ",r0,r2 + CMP r0,r2 + MOVHI r0,r2 + SUB lr,r2,r0 + MOV lr,lr,LSL #Log2PageSize + ADD lr,lr,#ApplicationStart +; Debug AMB,"AMB_MakeUnsparse MappedInNode addr pages ",r1,lr,r0 +10 + LDR r2,[lr] ;tends to wash data cache a bit, but this should be called rarely + ADD lr,lr,#PageSize + SUBS r0,r0,#1 + BNE %BT10 +20 + Pull "r0-r2,r12,pc" -AMB_smme_TLBflush - MOV r11,#0 - ARMop TLB_InvalidateAll,,,r11 -AMB_smme_exit - Pull "r0-r4,r7-r11, pc" + ] ;AMB_LazyMapIn -; ************************************************************************ +; ---------------------------------------------------------------------------------- +; ; AMB_FindMemMapEntries ; ; finds page numbers for pages currently at given logical start address, @@ -452,8 +584,6 @@ AMB_smme_exit ; exit: ; buffer at R4 filled in with page numbers ; -; ************************************************************************ - AMB_FindMemMapEntries ROUT Push "r0-r11,lr" @@ -497,6 +627,8 @@ AMB_FindMemMapEntries ROUT BNE %BT30 Pull "r0-r11,pc" +; ---------------------------------------------------------------------------------- +; ;AMB_r11topagenum ;entry: ; r0,r1,r2 = lowest addr,highest addr +1,first page no. diff --git a/s/AMBControl/service b/s/AMBControl/service index bac767a3..d5118c08 100644 --- a/s/AMBControl/service +++ b/s/AMBControl/service @@ -21,22 +21,23 @@ ; ; if there is a mapped-in node then recheck which and how many pages it owns ; -; I believe it should only be necessary to +; it is only necessary to: ; 1) reset node's idea of Npages to agree with no. of pages in app space -; 2) find the page numbers for new pages, if Npages has increased -; ie. I believe it is not necessary to recheck page numbers for whole node +; 2) if Npages has increased, find the page numbers for new pages [and update +; the mapped in list, if LazyMapIn] +; ie. page numbers of existing pages are not messed with ; -AMBsrv_memorymoved +AMBsrv_memorymoved ROUT Push "R3-R6,R12,LR" MOV R12,#AMBControl_ws LDR R12,[R12] CMP R12,#0 - Pull "R3-R6,R12,PC",EQ ;AMBControl not initialised yet! + Pull "R3-R6,R12,PC",EQ,^ ;AMBControl not initialised yet! LDR R4,AMBMappedInNode CMP R4,#0 - Pull "R3-R6,R12,PC",EQ ;done if nothing mapped in + Pull "R3-R6,R12,PC",EQ,^ ;done if nothing mapped in LDR R3,[R4,#AMBNode_Npages] @@ -47,7 +48,12 @@ AMBsrv_memorymoved CMP R6,R3 STRNE R6,[R4,#AMBNode_Npages] ;update Npages - Pull "R3-R6,R12,PC",LE ;done if Npages same, or shrink + [ AMB_LazyMapIn + Pull "R3-R6,R12,PC",EQ,^ ;done if Npages same + BLT %FT22 ;shrink + | + Pull "R3-R6,R12,PC",LE,^ ;done if Npages same, or shrink + ] MOV R5,#ApplicationStart ADD R5,R5,R3,LSL #Log2PageSize ;first logical address to find @@ -55,7 +61,105 @@ AMBsrv_memorymoved ADD R4,R4,R3,LSL #2 ;first page number word to use SUB R3,R6,R3 ;no. of pages to find (grow number) BL AMB_FindMemMapEntries - Pull "R3-R6,R12,PC" + + [ AMB_LazyMapIn + ;if Npages has grown, update AMBMappedInNpages and set bits in bitmap for + ;new pages, since these will be mapped in. + ; +; Debug AMB,"AMBsrv +Npages ",R3 + [ AMB_ChocTrace + LDR R5,AMBNmemmovegrow + ADD R5,R5,#1 + STR R5,AMBNmemmovegrow + ] + LDR R5,AMBFlags + TST R5,#AMBFlag_LazyMapIn_disable :OR AMBFlag_LazyMapIn_suspend + BNE %FT21 + LDR R5,AMBMappedInNpages + ADD R5,R5,R3 + STR R5,AMBMappedInNpages + LDR R4,AMBMappedInNode + LDR R5,[R4,#AMBNode_Npages] + SUB R5,R5,R3 + ADR R6,AMBMappedInRegister + ADD R6,R6,R5,LSR #5-2 ;first word of bitmap affected + BIC R6,R6,#3 + AND R5,R5,#31 ;first bit of word + MOV R4,#1 + MOV R5,R4,LSL R5 ;bitmap mask + LDR R4,[R6],#4 +10 + ORR R4,R4,R5 + SUBS R3,R3,#1 + STREQ R4,[R6,#-4] + BEQ %FT20 + MOVS R5,R5,LSL #1 + BNE %BT10 + STR R4,[R6,#-4] + MOV R4,#-1 +12 + CMP R3,#32 + BLT %FT14 + STR R4,[R6],#4 + SUBS R3,R3,#32 + BEQ %FT20 + B %BT12 +14 + MOV R5,#1 + LDR R4,[R6],#4 + B %BT10 +20 +21 + Pull "R3-R6,R12,PC",,^ + +22 + SUB R3,R3,R6 ;no. of pages removed from app space (known unsparse before removal) +; Debug AMB,"AMBsrv -Npages ",R3 + [ AMB_ChocTrace + LDR R5,AMBNmemmoveshrink + ADD R5,R5,#1 + STR R5,AMBNmemmoveshrink + ] + LDR R5,AMBFlags + TST R5,#AMBFlag_LazyMapIn_disable :OR AMBFlag_LazyMapIn_suspend + BNE %FT41 + LDR R5,AMBMappedInNpages + SUB R5,R5,R3 + STR R5,AMBMappedInNpages + LDR R4,AMBMappedInNode + LDR R5,[R4,#AMBNode_Npages] + ADR R6,AMBMappedInRegister + ADD R6,R6,R5,LSR #5-2 ;first word of bitmap affected + BIC R6,R6,#3 + AND R5,R5,#31 ;first bit of word + MOV R4,#1 + MOV R5,R4,LSL R5 ;bitmap mask + LDR R4,[R6],#4 +30 + BIC R4,R4,R5 + SUBS R3,R3,#1 + STREQ R4,[R6,#-4] + BEQ %FT40 + MOVS R5,R5,LSL #1 + BNE %BT30 + STR R4,[R6,#-4] + MOV R4,#0 +32 + CMP R3,#32 + BLT %FT34 + STR R4,[R6],#4 + SUBS R3,R3,#32 + BEQ %FT40 + B %BT32 +34 + MOV R5,#1 + LDR R4,[R6],#4 + B %BT30 +40 +41 + ] ;AMB_LazyMapIn + + Pull "R3-R6,R12,PC",,^ ;Service_PagesSafe @@ -65,17 +169,17 @@ AMBsrv_memorymoved ; ; action: fix-up page numbers in page lists of nodes as necessary ; -AMBsrv_pagessafe +AMBsrv_pagessafe ROUT Push "R0-R1,R5-R10,R12,LR" MOV R12,#AMBControl_ws LDR R12,[R12] CMP R12,#0 - Pull "R0-R1,R5-R10,R12,PC",EQ ;AMBControl not initialised yet! + Pull "R0-R1,R5-R10,R12,PC",EQ,^ ;AMBControl not initialised yet! LDR R0,AMBNtasks CMP R0,#0 - Pull "R0-R1,R5-R10,R12,PC",EQ ;no nodes to check + Pull "R0-R1,R5-R10,R12,PC",EQ,^ ;no nodes to check ;speed-up - list of pages tends to span a narrow range of page numbers, so ; use min,max limits to skip search @@ -136,7 +240,7 @@ AMBsrv_pagessafe LDR R0,[R0,#AMBNode_next] CMP R0,R1 ;done if back at anchor node BNE %BT01 - Pull "R0-R1,R5-R10,R12,PC" + Pull "R0-R1,R5-R10,R12,PC",,^ END diff --git a/s/AMBControl/shrinkp b/s/AMBControl/shrinkp index 52e97179..2c965c75 100644 --- a/s/AMBControl/shrinkp +++ b/s/AMBControl/shrinkp @@ -38,6 +38,27 @@ shrinkpages MOVEQ R3,#1 ;flag this is the mapped-in node MOVNE R3,#0 ;flag is not + [ AMB_LazyMapIn + ;first make sure the current mapping of mapped in node is simple, + ;so that main mapping can cope - easiest thing is to do a sparse map out + ; + BNE %FT02 + Push "R3,R6" + LDR R3,AMBFlags + TST R3,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend + BNE %FT01 + LDR R3,AMBMappedInNpages + ADD R4,R5,#AMBNode_pages + LDR R6,[R5,#AMBNode_Npages] + ADR R5,AMBMappedInRegister + BL AMB_SetMemMapEntries_SparseMapOut + MOV R3,#0 + STR R3,AMBMappedInNpages +01 + Pull "R3,R6" +02 + ] + TST R3,#1 ;check flag MOVEQ R1,#0 ;source is not App space LDRNE R1,=AppSpaceDANode ;source is App space @@ -73,7 +94,8 @@ shrinkpages STRNE R0,[R5,#MemLimit] ;update MemLimit 02 - STRVS R0,[SP] +;;; STRVS R0,[SP] + CLRV Pull "R0-R7,PC" diff --git a/s/ARMops b/s/ARMops index 666e9683..fc697cce 100644 --- a/s/ARMops +++ b/s/ARMops @@ -187,6 +187,13 @@ Analyse_ARMv3 STR a2, [v6, #Proc_MMU_ChangingEntry] STR a3, [v6, #Proc_MMU_ChangingUncached] STR a4, [v6, #Proc_MMU_ChangingUncachedEntry] + + ADR a1, MMU_ChangingEntries_ARMv3 + ADR a2, MMU_ChangingUncachedEntries_ARMv3 + ADR a3, Cache_RangeThreshold_ARMv3 + STR a1, [v6, #Proc_MMU_ChangingEntries] + STR a2, [v6, #Proc_MMU_ChangingUncachedEntries] + STR a3, [v6, #Proc_Cache_RangeThreshold] B %FT90 Analyse_WriteThroughUnified @@ -215,6 +222,13 @@ Analyse_WriteThroughUnified STR a2, [v6, #Proc_MMU_ChangingEntry] STR a3, [v6, #Proc_MMU_ChangingUncached] STR a4, [v6, #Proc_MMU_ChangingUncachedEntry] + + ADR a1, MMU_ChangingEntries_Writethrough + ADR a2, MMU_ChangingUncachedEntries + ADR a3, Cache_RangeThreshold_Writethrough + STR a1, [v6, #Proc_MMU_ChangingEntries] + STR a2, [v6, #Proc_MMU_ChangingUncachedEntries] + STR a3, [v6, #Proc_Cache_RangeThreshold] B %FT90 90 @@ -371,10 +385,37 @@ MMU_ChangingEntry_ARMv3 MCR p15, 0, a1, c6, c0 ; invalidate TLB entry MOV pc, lr +MMU_ChangingEntries_ARMv3 ROUT + Push "a2" + MCR p15, 0, a1, c7, c0 ; invalidate cache +10 + MCR p15, 0, a1, c6, c0 ; invalidate TLB entry + SUBS a2, a2, #1 ; next page + ADD a1, a1, #PageSize + BNE %BT10 + Pull "a2" + MOV pc, lr + MMU_ChangingUncachedEntry_ARMv3 MCR p15, 0, a1, c6, c0 ; invalidate TLB entry MOV pc, lr +MMU_ChangingUncachedEntries_ARMv3 ROUT + Push "a2" +10 + MCR p15, 0, a1, c6, c0 ; invalidate TLB entry + SUBS a2, a2, #1 ; next page + ADD a1, a1, #PageSize + BNE %BT10 + Pull "a2" + MOV pc, lr + +Cache_RangeThreshold_ARMv3 + ! 0, "arbitrary Cache_RangeThreshold_ARMv3" + MOV a1, #16*PageSize + MOV pc, lr + + Cache_InvalidateUnified MOV a1, #0 MCR p15, 0, a1, c7, c7 @@ -422,10 +463,36 @@ MMU_ChangingEntry_Writethrough Pull "a4" MOV pc, lr +MMU_ChangingEntries_Writethrough ROUT + Push "a2,a4" + MOV a4, #0 + MCR p15, 0, a4, c7, c7 ; invalidate cache +10 + MCR p15, 0, a1, c8, c7, 1 ; invalidate TLB entry + SUBS a2, a2, #1 ; next page + ADD a1, a1, #PageSize + BNE %BT10 + Pull "a2,a4" + MOV pc, lr + MMU_ChangingUncachedEntry MCR p15, 0, a1, c8, c7, 1 ; invalidate TLB entry MOV pc, lr +MMU_ChangingUncachedEntries ROUT + Push "a2" +10 + MCR p15, 0, a1, c8, c7, 1 ; invalidate TLB entry + SUBS a2, a2, #1 ; next page + ADD a1, a1, #PageSize + BNE %BT10 + Pull "a2" + MOV pc, lr + +Cache_RangeThreshold_Writethrough + ! 0, "arbitrary Cache_RangeThreshold_Writethrough" + MOV a1, #16*PageSize + MOV pc, lr ; IMPORT Write0_Translated -- GitLab