Commit 54872d8c authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Add initial support for "physical memory pools"

Detail:
  This set of changes adds support for "physical memory pools" (aka PMPs), a new type of dynamic area which allow physical pages to be claimed/allocated without mapping them in to the logical address space. PMPs have full control over which physical pages they use (similar to DAs which request specific physical pages), and also have full control over the logical mapping of their pages (which pages go where, and per-page access/cacheability control).
  Currently the OS makes use of two PMPs: one for the free pool (which now has a logical size of zero - freeing up gigabytes of logical space), and one for the RAM disc (logical size of 1MB, allowing for a physical size limited only by the amount of free memory)
  Implementing these changes has required a number of other changes to be made:
  * The CAM has been expanded from 8 bytes per entry to 16 bytes per entry, in order to allow each RAM page to store information about its PMP association
  * The system heap has been expanded to 32MB in size (from just under 4MB), in order to allow it to be used to store PMP page lists (1 word needed per page, but PMP pages may not always have physical pages assigned to them - so to allow multiple large PMPs to exist we need more than just 1 word per RAM page)
  * The &FA000000-&FBFFFFFF area of fixed kernel workspace has been shuffled around to accomodate the larger CAM, and the system heap is now located just above the RMA.
  * SoftResets code stripped out (unlikely we'll ever want to fix and re-enable it)
  * A couple of FastCDA options are now permanently on
  * Internal page flags shuffled around a bit. PageFlags_Unavailable now publicly exposed so that PMP clients can lock/unlock pages at will.
  * When OS_ChangeDynamicArea is asked to grow or shrink the free pool, it now implicitly converts it into a shrink or grow of application space (which is what would happen anyway). This simplifies the implementation; during a grow, pages (or replacement pages) are always sourced from the free pool, and during a shrink pages are always sent to the free pool.
  File changes:
  - hdr/KernelWS - Extend DANode structure. Describe CAM format. Adjust kernel workspace.
  - hdr/OSRSI6, s/Middle - Add new item to expose the CAM format
  - hdr/Options - Remove SoftResets switch. Add some PMP switches.
  - s/ARM600, s/VMSAv6 - Updated for new CAM format. Note that although the CAM stores PMP information, BangCamUpdate currently doesn't deal with updating that data - it's the caller's responsibility to do so where appropriate.
  - s/ChangeDyn - Lots of changes to implement PMP support, and to cope with the new CAM format.
  - s/HAL - Updated to cope with new CAM format, and lack of logical mapping of free pool.
  - s/MemInfo - Updated to cope with new CAM format. OS_Memory 0 updated to cope with converting PPN to PA for pages which are mapped out. OS_Memory 24 updated to decode the access permissions on a per-page basis for PMPs, and fixed its HWM usage for sparse DAs.
  - s/NewReset - Soft reset code and unused AddCamEntries function removed. Updated to cope with new CAM format, PMP free pool, PMP RAMFS
  - s/AMBControl/allocate - Update comment (RMA hasn't been used for AMBControl nodes for a long time)
  - s/AMBControl/growp, s/AMBControl/memmap, s/AMBControl/shrinkp - Update for new CAM format + PMP free pool
  - s/vdu/vdudriver - Strip out soft reset code.
Admin:
  Tested on Pandaboard
  This is just a first iteration of the PMP feature, with any luck future changes will improve functionality. This means APIs are subject to change as well.


Version 5.35, 4.79.2.284. Tagged as 'Kernel-5_35-4_79_2_284'
parent da41d3a5
......@@ -13,11 +13,11 @@
GBLS Module_ComponentPath
Module_MajorVersion SETS "5.35"
Module_Version SETA 535
Module_MinorVersion SETS "4.79.2.283"
Module_Date SETS "20 Aug 2015"
Module_ApplicationDate SETS "20-Aug-15"
Module_MinorVersion SETS "4.79.2.284"
Module_Date SETS "31 Aug 2015"
Module_ApplicationDate SETS "31-Aug-15"
Module_ComponentName SETS "Kernel"
Module_ComponentPath SETS "castle/RiscOS/Sources/Kernel"
Module_FullVersion SETS "5.35 (4.79.2.283)"
Module_HelpVersion SETS "5.35 (20 Aug 2015) 4.79.2.283"
Module_FullVersion SETS "5.35 (4.79.2.284)"
Module_HelpVersion SETS "5.35 (31 Aug 2015) 4.79.2.284"
END
......@@ -5,19 +5,19 @@
*
*/
#define Module_MajorVersion_CMHG 5.35
#define Module_MinorVersion_CMHG 4.79.2.283
#define Module_Date_CMHG 20 Aug 2015
#define Module_MinorVersion_CMHG 4.79.2.284
#define Module_Date_CMHG 31 Aug 2015
#define Module_MajorVersion "5.35"
#define Module_Version 535
#define Module_MinorVersion "4.79.2.283"
#define Module_Date "20 Aug 2015"
#define Module_MinorVersion "4.79.2.284"
#define Module_Date "31 Aug 2015"
#define Module_ApplicationDate "20-Aug-15"
#define Module_ApplicationDate "31-Aug-15"
#define Module_ComponentName "Kernel"
#define Module_ComponentPath "castle/RiscOS/Sources/Kernel"
#define Module_FullVersion "5.35 (4.79.2.283)"
#define Module_HelpVersion "5.35 (20 Aug 2015) 4.79.2.283"
#define Module_FullVersion "5.35 (4.79.2.284)"
#define Module_HelpVersion "5.35 (31 Aug 2015) 4.79.2.284"
#define Module_LibraryVersionInfo "5:35"
......@@ -218,16 +218,28 @@ DANode_Link # 4 ; points to next node (in address order)
DANode_Number # 4 ; number of this area
DANode_Base # 4 ; base address of area (points in middle of doubly-mapped areas)
DANode_Flags # 4 ; various flags
DANode_Size # 4 ; current size of area (not counting holes, if Sparse area)
DANode_MaxSize # 4 ; maximum size of area
DANode_Size # 4 ; current logical size of area (not counting holes, if Sparse/PMP area)
DANode_MaxSize # 4 ; maximum logical size of area
DANode_Workspace # 4 ; workspace pointer when calling handlers
DANode_Handler # 4 ; pointer to handler routine for area
DANode_Title # 4 ; pointer to area title
DANode_SubLink # 4 ; next node in any disjoint sublist (currently used for Shrinkables only)
DANode_SparseHWM # 4 ; high water mark, if Sparse area (highest base+size claimed for area)
DANode_SortLink # 4 ; next node in alphabetically sorted list
DANode_PMP # 4 ; pointer to physical memory pool - zero if not PMP or has been resized to zero
DANode_PMPSize # 4 ; number of pages currently in phys pool
DANode_PMPMaxSize # 4 ; size of phys memory pool, in pages
DANode_NodeSize # 0
; CAM entry format
^ 0
CAM_LogAddr # 4 ; Logical address page is assigned to (lower address if doubly mapped, Nowhere/DuffEntry if not mapped)
CAM_PageFlags # 4 ; DynAreaFlags_* and PageFlags_*
CAM_PMP # 4 ; Pointer to PMP (DANode ptr) if DynAreaFlags_PMP. 0 if not.
CAM_PMPIndex # 4 ; Index of page in PMP page list. Invalid if not in PMP.
CAM_EntrySize # 0
CAM_EntrySizeLog2 * 4
; The addresses below are only temporary; eventually most of them will be allocated at run time (we hope!)
......@@ -252,7 +264,10 @@ DCacheCleanSize * 256*1024 ;should be multiple of 64k
AplWorkMaxSize * &20000000 ; 512M - temporary (need to decide this at boot time)
RMAAddress * AplWorkMaxSize ; temporary - run time allocate?
RMAMaxSize * &10000000 ; 256M
FreePoolAddress * RMAAddress + RMAMaxSize
SysHeapChunkAddress * RMAAddress + RMAMaxSize
SysHeapAddress * SysHeapChunkAddress
SysHeapMaxSize * 32:SHL:20
FreePoolAddress * 0
IOLimit * &BA000000 ; initial lower limit on room for IO space (DA creation may move limit up)
IO * &FA000000 ; works downwards
......@@ -262,20 +277,17 @@ IRQStackAddress * &FA100000
SVCStackAddress * &FA200000
ABTStackAddress * &FA300000
UNDStackAddress * &FA400000
PhysicalAccess * &FAE00000
DCacheCleanAddress * &FAF00000 ; eg. for StrongARM, 256k of space, up to FAF40000
KbuffsBaseAddress * &FAF40000 ; kernel buffers for long command lines, size KbuffsMaxSize
HALWorkspaceNCNB * &FAFE8000 ; 32K of uncacheable HAL workspace (if requested)
PhysicalAccess * &FA500000
DCacheCleanAddress * &FA600000 ; eg. for StrongARM, 256k of space, up to FAF40000
KbuffsBaseAddress * &FA640000 ; kernel buffers for long command lines, size KbuffsMaxSize
HALWorkspaceNCNB * &FA6E8000 ; 32K of uncacheable HAL workspace (if requested)
L2PT * &FA800000
L1PT * &FAC00000
CursorChunkAddress * &FAFF0000
DuffEntry * &FAFF8000 ; No page ever mapped in here (L2PT entry always 0), also, all non mapped pages
Nowhere * DuffEntry ; use this as their CAM entry. There is only one 'Nowhere' (synonym).
L2PT * &FB000000
L1PT * &FB400000
SysHeapChunkAddress * &FB404000
SysHeapAddress * SysHeapChunkAddress
SysHeapMaxSize * &FB800000 - SysHeapAddress
CAM * &FB800000
CAMspace * 8*1024*1024 ; enough for 4GB of RAM
CAM * &FB000000
CAMspace * CAM_EntrySize*1024*1024 ; 1M entries = enough for 4GB of RAM
IRQSTK * IRQStackAddress + IRQStackSize
ABTSTK * ABTStackAddress + ABTStackSize
......
......@@ -86,5 +86,6 @@ OSRSI6_ECFYOffset * 83
OSRSI6_ECFShift * 84
OSRSI6_VecPtrTab * 85
OSRSI6_NVECTORS * 86
OSRSI6_CAMFormat * 87 ; 0 = 8 bytes per entry, 1 = 16 bytes per entry
END
......@@ -120,9 +120,6 @@ MouseBufferManager SETL {TRUE}
GBLL IrqsInClaimRelease ; Whether OS_Claim/Release restore IRQ's before releasing heap node
IrqsInClaimRelease SETL {TRUE}
GBLL SoftResets ; If false, always force a hard reset
SoftResets SETL {FALSE}
GBLL AlwaysClearRAM ; If true, clear RAM on every break/reset
AlwaysClearRAM SETL {TRUE}
......@@ -313,8 +310,21 @@ FirstUnpluggableModule SETA 8 ; Podule, FileSwitch, ResourceFS
; TerritoryManager, UK. Moot now the keyboard and mouse aren't
; in the kernel - unplug those and you're stuffed.
GBLL PMPDebug
PMPDebug SETL {FALSE} ; Physical memory pool debugging
GBLL PMPParanoid
PMPParanoid SETL {FALSE} ; Validate PMPs after most ops
GBLL PMPRAMFS
PMPRAMFS SETL {TRUE} ; Whether RAMFS DA is a PMP (requires compatible RAMFS module)
[ PMPRAMFS
PMPRAMFS_Size * 256 ; Number of logical pages (physical size is unlimited)
|
GBLA MaxRAMFS_Size
MaxRAMFS_Size SETA 128 ; Max size available for RAM Disc
]
[ DebugForcedReset
Reset_CannotResetFlag * 1
......
......@@ -48,7 +48,7 @@ allocate
B SLVK_SetV
01
;get memory for node - from RMA
;get memory for node - from system heap
MOV R3,#(AMBNode_pages - AMBNode_id) ;size excluding page list
ADD R3,R3,R1,LSL #2 ;plus one word per page
BL AMB_BlockClaim
......
......@@ -39,28 +39,36 @@ growpages ROUT
LDR R7,[R0,#AMBNode_Npages] ;R7 := current no. of pages
SUB R3,R6,R7 ;no. of pages required from FreePool
LDR R4,[R1,#DANode_Size]
MOV R4,R4,LSR #Log2PageSize ;no. of pages in FreePool
LDR R4,[R1,#DANode_PMPSize] ;no. of pages in FreePool
CMP R3,R4
[ ShrinkableDAs
BLGT growp_TryToShrinkShrinkables
BLHI growp_TryToShrinkShrinkables
]
MOVGT R3,R4 ;R3 := no. of pages we will move
MOVHI R3,R4 ;R3 := no. of pages we will move
CMP R3,#0
BEQ %FT02 ;done if can't move any pages
BEQ %FT90 ;done if can't move any pages
ADD R4,R3,R7
STR R4,[R0,#AMBNode_Npages] ;new no. of pages
ADD R4,R0,#AMBNode_pages
ADD R4,R4,R7,LSL #2 ;R4 -> 1st page table entry for grow
LDR R5,[R1,#DANode_Base]
LDR LR,[R1,#DANode_Size]
ADD R5,R5,LR ;current end of FreePool
SUB R5,R5,R3,LSL #Log2PageSize ;R5 := first required page address
;entry: R3 = no. of pages, R4 -> buffer for page entries,
; R5 := start logical address
BL AMB_FindMemMapEntries ;find page nos.
LDR R5,[R1,#DANode_PMP]
LDR LR,[R1,#DANode_PMPSize]
ADD R5,R5,LR,LSL #2 ;current end of FreePool
SUB R5,R5,R3,LSL #2 ;R5 := first required page in PMP
;R3 = no. of pages, R4 -> buffer for page entries,
;R5 := start page in PMP
MOV R2,R3
MOV R6,#-1
10
LDR LR,[R5]
SUBS R2,R2,#1
STR LR,[R4],#4
STR R6,[R5],#4
BNE %BT10
SUB R4,R4,R3,LSL #2
LDR R2,=ZeroPage+AppSpaceDANode ;R2 := dest for pages
[ AMB_LazyMapIn
LDR R5,AMBFlags
......@@ -81,9 +89,9 @@ growpages ROUT
; R5 = start logical address, R6 = PPL
BL AMB_SetMemMapEntries ;remap
LDR R5,[R1,#DANode_Size]
SUB R5,R5,R3,LSL #Log2PageSize
STR R5,[R1,#DANode_Size] ;new FreePool size
LDR R5,[R1,#DANode_PMPSize]
SUB R5,R5,R3
STR R5,[R1,#DANode_PMPSize] ;new FreePool size
LDR R5,[R2,#DANode_Size]
ADD R5,R5,R3,LSL #Log2PageSize
......@@ -91,7 +99,7 @@ growpages ROUT
LDR R6,=ZeroPage
STR R5,[R6,#MemLimit] ;update MemLimit
02
90
;;; STRVS R0,[SP]
CLRV
Pull "R0-R7,PC"
......@@ -110,36 +118,16 @@ growpages ROUT
; condition code GT is true if still less than required (ie. R3 > R4 on exit)
;
growp_TryToShrinkShrinkables ROUT
Push "R0-R2,R11,R12,LR"
MOV R11,R1 ; -> FreePool DANode
MOV R1,R3,LSL #Log2PageSize ;amount we need in FreePool
MOV R2,R4,LSL #Log2PageSize ;amount we have in FreePool
LDR R10,=ZeroPage+DAList
ASSERT DANode_Link = 0 ;because DAList has only link
10
LDR R10,[R10,#DANode_Link] ;and load next
CMP R10,#1 ;any more nodes?
BCC %FT99
LDR LR,[R10,#DANode_Flags] ;check area is shrinkable
TST LR,#DynAreaFlags_Shrinkable
BEQ %BT10 ;if not, try next area
SUBS R1,R1,R2 ;amount we still need
LDR LR,[R10,#DANode_Size] ;available size of this area
CMP LR,R1
MOVCC R1,LR ;min(amount we need, size of this area)
RSB R1,R1,#0 ;make negative - it's a shrink
LDR R0,[R10,#DANode_Number]
SWI XOS_ChangeDynamicArea ;should not be currently threaded during AMBControl
MOV R1,R3,LSL #Log2PageSize ;original amount we need again
LDR R2,[R11,#DANode_Size] ;get new size of FreePool
CMP R2,R1
BCC %BT10 ;if still too small, loop
99
MOV R4,R2,LSR #Log2PageSize ;no. of pages now in FreePool
CMP R3,R4
Pull "R0-R2,R11,R12,PC"
Entry "R1-R2,R11,R12"
MOV R11,R1
MOV R12,#0 ; dest node irrelevant
MOV R1,R3
MOV R2,R4
CLC
BL TryToShrinkShrinkables
MOV R4,R2
CMP R3,R2
EXIT
] ;ShrinkableDAs
......
......@@ -124,14 +124,16 @@ AMB_LazyFixUp ROUT
;here, r6 = page number of page involved, r4 = new L2PT entry value to map in page
;
ADD r0,r0,#ApplicationStart:SHR:Log2PageSize ;address now in terms of pages from 0
MOV r5,#L2PT
LDR r5,=L2PT
STR r4,[r5,r0,LSL #2] ;update L2PT
;
LDR r5,=ZeroPage
LDR r5,[r5,#CamEntriesPointer]
ADD r5,r5,r6,LSL #3 ;r5 -> CAM entry affected
ADD r5,r5,r6,LSL #CAM_EntrySizeLog2 ;r5 -> CAM entry affected
MOVS r0,r0,LSL #Log2PageSize ;address is now ordinary again, and must be non-zero
MOV r1,#0 ;0 = AP for ordinary page
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
STMIA r5,{r0,r1} ;update CAM entry
MOV r12,r7
MOV pc,lr ;r0 is non-zero, NE status
......@@ -215,7 +217,8 @@ AMB_MakeHonestPN ROUT
CMP r0,r1
BHI %FT90 ;invalid page number
LDR r1,[r14,#CamEntriesPointer]
LDR r1,[r1,r0,LSL #3] ;logical address from CAM
ASSERT CAM_LogAddr = 0
LDR r1,[r1,r0,LSL #CAM_EntrySizeLog2] ;logical address from CAM
LDR r14,=Nowhere
TEQ r1,r14
BNE %FT90 ;only a page at Nowhere might be dishonest
......@@ -303,7 +306,9 @@ AMB_movepagesin_L2PT ROUT
;
MACRO
UpdateCAM $reg
ADD $reg,r11,$reg,LSL #3 ;r0 -> CAM entry for 1st page
ADD $reg,r11,$reg,LSL #CAM_EntrySizeLog2 ;r0 -> CAM entry for 1st page
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
STMIA $reg,{r9,lr} ;store logical addr,PPL
MEND
......@@ -480,6 +485,7 @@ AMB_SetMemMapEntries ROUT
MOVEQ r9,#AP_Duff ;PPL for mapped out pages
MOVNE r9,r6 ;PPL for mapped in pages
01
;get L2PT protection etc. bits, appropriate to PPL in R9, into R11
ADRL r1,PPLTrans
AND lr,r9,#3
......@@ -510,12 +516,12 @@ AMB_SetMemMapEntries ROUT
LDR r2,[r10] ;page number of 1st page
LDR r7,[r7,#CamEntriesPointer] ;r7 -> CAM
ADD r1,r7,r2,LSL #3 ;r1 -> CAM entry for 1st page
ADD r1,r7,r2,LSL #CAM_EntrySizeLog2 ;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,#CAM_LogAddr] ;fetch old logical addr. of 1st page from CAM
LDR r3,[r1,#CAM_PageFlags] ;fetch old PPL of 1st page from CAM
|
LDR r4,[r1] ;fetch old logical addr. of 1st page from CAM
LDR r4,[r1,#CAM_LogAddr] ;fetch old logical addr. of 1st page from CAM
]
CMP r5,#-1
......@@ -568,17 +574,38 @@ AMB_smme_mapin
;all pages destined for same new logical page Nowhere, ie. mapping them out
;
AMB_smme_mapout
LDR r3,=DuffEntry
CMP r4,r3
BEQ %FT50 ;pages already mapped out - just update CAM for new ownership
MOV r0,r4 ;address of 1st page
MOV r1,r8 ;number of pages
LDR r3,=ZeroPage
ARMop MMU_ChangingEntries,,,r3 ;
LDR r3,=DuffEntry
BL AMB_movepagesout_L2PT
50
BL AMB_movepagesout_CAM
AMB_smme_exit
Pull "r0-r4,r7-r11, pc"
; ----------------------------------------------------------------------------------
;
; AMB_SetMemMapEntries_MyPPL:
;
; As above, but uses provided PPL when mapping out instead of forcing to AP_Duff
;
; entry:
; R3 = no. of pages
; R4 -> list of page entries (1 word per entry, giving page no.)
; R5 = start logical address of mapping (-1 means 'out of the way')
; R6 = PPL ('page protection level') for mapping
;
AMB_SetMemMapEntries_MyPPL
Push "r0-r4,r7-r11,lr"
MOVS r8,r3
MOV r9,r6
BNE %BT01
B AMB_smme_exit
[ AMB_LazyMapIn
......@@ -639,7 +666,9 @@ AMB_SetMemMapEntries_SparseMapOut ROUT
ARMop MMU_ChangingEntry,,,r2
14
LDR r0,[r10] ;page no.
ADD r0,r7,r0,LSL #3 ;r0 -> CAM entry for page
ADD r0,r7,r0,LSL #CAM_EntrySizeLog2 ;r0 -> CAM entry for page
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
STMIA r0,{r1,r9} ;CAM entry for page set to DuffEntry,AP_Duff
LDR lr,=L2PT ;lr -> L2PT
MOV r2, #0
......
......@@ -71,19 +71,32 @@ shrinkpages
ADD R4,R0,#AMBNode_pages
ADD R4,R4,R6,LSL #2 ;R4 -> 1st page table entry for shrink
LDR R5,[R2,#DANode_Base]
LDR R6,[R2,#DANode_Size]
ADD R5,R5,R6 ;R5 -> current end of FreePool
LDR R6,[R2,#DANode_Flags]
AND R6,R6,#&7F ;R6 = dest PPL flags
LDR LR,=DynAreaFlags_AccessMask
MOV R5,#-1 ;map pages out
AND R6,R6,LR ;R6 = dest PPL flags
;entry: R3 = no. of pages, R4 -> list of page entries,
; R5 = start logical address, R6 = PPL
BL AMB_SetMemMapEntries ;remap
LDR R0,[R2,#DANode_Size]
ADD R0,R0,R3,LSL #Log2PageSize
STR R0,[R2,#DANode_Size]
BL AMB_SetMemMapEntries_MyPPL ;remap
LDR R5,[R2,#DANode_PMP]
LDR R6,[R2,#DANode_PMPSize]
LDR R7,=ZeroPage
LDR R7,[R7,#CamEntriesPointer]
ADD R7,R7,#CAM_PMP
MOV R0,R3
10
LDR LR,[R4],#4
SUBS R0,R0,#1
STR LR,[R5,R6,LSL #2] ;add to free pool PMP
ADD LR,R7,LR,LSL #CAM_EntrySizeLog2
ASSERT CAM_PMPIndex=CAM_PMP+4
STMIA LR,{R2,R6} ;update PMP reference in CAM
ADD R6,R6,#1
BNE %BT10
STR R6,[R2,#DANode_PMPSize]
;update Application Space kernel values, if required
CMP R1,#0
......
......@@ -152,7 +152,9 @@ BangCamUpdate ROUT
LDR r1, =ZeroPage
LDR r1, [r1, #CamEntriesPointer]
ADD r1, r1, r2, LSL #3 ; point at cam entry (logaddr, PPL)
ADD r1, r1, r2, LSL #CAM_EntrySizeLog2 ; point at cam entry (logaddr, PPL)
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
LDMIA r1, {r0, r6} ; r0 = current logaddress, r6 = current PPL
BIC r4, r11, #PageFlags_Unsafe
STMIA r1, {r3, r4} ; store new address, PPL
......
This diff is collapsed.
......@@ -587,8 +587,8 @@ RISCOS_Start
MOV lr, a2, LSR #12
SUB lr, lr, #1
STR lr, [v1, #MaxCamEntry]
MOV lr, a2, LSR #12-3+12
CMP a2, lr, LSL #12-3+12
MOV lr, a2, LSR #12-CAM_EntrySizeLog2+12
CMP a2, lr, LSL #12-CAM_EntrySizeLog2+12
ADDNE lr, lr, #1
MOV lr, lr, LSL #12
STR lr, [v1, #SoftCamMapSize]
......@@ -1283,29 +1283,22 @@ MMUon_nol1ptoverlap
]
[ MinorL2PThack
; Allocate backing L2PT for the free pool
MOV a1, #FreePoolAddress
LDR a2, [v8, #RAMLIMIT]
; Need to round this up to 4M boundary, as AllocateL2PT only does
; individual (1M) sections, rather than 4 at a time, corresponding
; to a L2PT page. The following space is available for dynamic areas,
; and ChangeDyn.s will get upset if it sees only some out of a set of 4
; section entries pointing to the L2PT page.
ASSERT FreePoolAddress :MOD: (4*1024*1024) = 0
ADD a2, a2, #4*1024*1024
SUB a2, a2, #1
MOV a2, a2, LSR #22
MOV a2, a2, LSL #22
ORR a3, v5, #AP_None * L2X_APMult
BL AllocateL2PT
; And for application space
; Allocate backing L2PT for application space
; Note that ranges must be 4M aligned, as AllocateL2PT only does individual
; (1M) sections, rather than 4 at a time, corresponding to a L2PT page. The
; following space is available for dynamic areas, and ChangeDyn.s will get
; upset if it sees only some out of a set of 4 section entries pointing to the
; L2PT page.
MOV a1, #0
MOV a2, #AplWorkMaxSize ; Not quite right, but the whole thing's wrong anyway
ASSERT AplWorkMaxSize :MOD: (4*1024*1024) = 0
ORR a3, v4, #AP_Full * L2X_APMult
BL AllocateL2PT
; And for the system heap. Sigh
LDR a1, =SysHeapAddress
LDR a2, =SysHeapMaxSize
ASSERT SysHeapAddress :MOD: (4*1024*1024) = 0
ASSERT SysHeapMaxSize :MOD: (4*1024*1024) = 0
ORR a3, v4, #AP_Full * L2X_APMult
BL AllocateL2PT
]
......@@ -1438,6 +1431,7 @@ HAL_InvalidateCache_ARMvF
] ; MEMM_Type = "VMSAv6"
CountPageTablePages ROUT
Entry
LDR a1, =ZeroPage
LDR a2, =CAM
LDR a3, [a1, #MaxCamEntry]
......@@ -1445,17 +1439,17 @@ CountPageTablePages ROUT
MOV a1, #0
]
ADD a3, a3, #1
ADD a4, a2, a3, LSL #3
10 LDR ip, [a4, #-8]!
ADD a4, a2, a3, LSL #CAM_EntrySizeLog2
ASSERT (L2PT :AND: &3FFFFF) = 0
MOV ip, ip, LSR #22
TEQ ip, #L2PT :SHR: 22
LDR lr, =L2PT :SHR: 22
10 LDR ip, [a4, #CAM_LogAddr-CAM_EntrySize]!
TEQ lr, ip, LSR #22
ADDEQ a1, a1, #4096
TEQ a4, a2
BNE %BT10
LDR a2, =ZeroPage
STR a1, [a2, #L2PTUsed]
MOV pc, lr
EXIT
; int PhysAddrToPageNo(void *addr)
;
......@@ -1492,11 +1486,18 @@ ConstructCAMfromPageTables
LDR ip, [a1, #MMU_PCBTrans]
LDR v1, =CAM ; v1 -> CAM (for whole routine)
ADD a2, a2, #1
ADD a2, v1, a2, LSL #3
ADD a2, v1, a2, LSL #CAM_EntrySizeLog2
LDR a3, =DuffEntry ; Clear the whole CAM, from
MOV a4, #AP_Duff ; the top down.
10 STMDB a2!, {a3, a4}
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
ASSERT CAM_PMP=8
ASSERT CAM_PMPIndex=12
ASSERT CAM_EntrySize=16
MOV v2, #0
MOV v3, #-1
10 STMDB a2!, {a3, a4, v2, v3}
CMP a2, v1
BHI %BT10
......@@ -1555,7 +1556,7 @@ ConstructCAMfromPageTables
CMP a1, #-1
BEQ %FT80
ADD a2, v1, a1, LSL #3 ; a2 -> CAM entry
ADD a2, v1, a1, LSL #CAM_EntrySizeLog2 ; a2 -> CAM entry
[ MEMM_Type = "VMSAv6"
AND a1, v5, #L2_AP ; a1 = access permission
......@@ -1586,6 +1587,8 @@ ConstructCAMfromPageTables
AND a1, lr, #2_11100
ORR v6, v6, a1, LSL #10 ; extract P bits
ORR v6, v6, #PageFlags_Unavailable ; ???? pages from scratch to cam only?
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
STMIA a2, {v2, v6} ; store logical address, PPL
|
AND a1, v5, #&30 ; a1 = access permission
......@@ -1613,6 +1616,8 @@ ConstructCAMfromPageTables
AND a1, lr, #2_11100
ORR v6, v6, a1, LSL #10 ; extract P bits
ORR v6, v6, #PageFlags_Unavailable ; ???? pages from scratch to cam only?
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
STMIA a2, {v2, v6} ; store logical address, PPL
]
......
......@@ -158,9 +158,12 @@ MemoryConvert ROUT
TST r0, #physical,wanted ; If PA not wanted
BEQ %FT20 ; then skip.
TST r0, #logical,given ; If LA not given (rotate clears C) then
BLEQ ppn_to_logical ; get it from PN (PA wanted (not given) & LA not given => PN given).
BLCC logical_to_physical ; Get PA from LA.
TST r0, #logical,given ; If LA given (rotate clears C) then
ADR lr, %FT15
BNE logical_to_physical ; Get PA from LA
BL ppn_to_logical ; Else get LA from PN (PA wanted (not given) & LA not given => PN given).
BLCC ppn_to_physical ; And get PA from PN (more accurate than getting PA from LA - page may be mapped out)
15
BCS %FT80
TST r0, #logical,wanted
STRNE r4, [r1, #-8] ; Store back LA if wanted.
......@@ -195,7 +198,9 @@ MemoryConvert ROUT
CMP r7, r3 ; Make sure page number is valid (might not have done any conversion).
BCC %FT80
ADD r3, r6, r3, LSL #3 ; Point to CAM entry for this page.
ADD r3, r6, r3, LSL #CAM_EntrySizeLog2 ; Point to CAM entry for this page.
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
LDMIA r3, {r4,r5} ; Get logical address and PPL.
AND lr, r5, #PageFlags_TempUncacheableBits
......@@ -213,7 +218,7 @@ MemoryConvert ROUT
SUB r5, r5, #1:SHL:TempUncacheableShift
TST r5, #PageFlags_TempUncacheableBits ; EQ => we have to change L2.
60
STR r5, [r3, #4] ; Write back new PPL.
STR r5, [r3, #CAM_PageFlags] ; Write back new PPL.
BNE %BT10 ; Do next entry if we don't have to change L2.
MOV r4, r4, LSR #12
......@@ -333,7 +338,8 @@ ppn_to_logical
ORRCCS pc, lr, #C_bit ; Invalid so return C set.
]
LDR r4, [r6, r3, LSL #3] ; If valid then lookup logical address.
ASSERT CAM_LogAddr=0
LDR r4, [r6, r3, LSL #CAM_EntrySizeLog2] ; If valid then lookup logical address.
TST r0, #physical,given ; If physical address was given then
LDRNE r9, =&FFF
ANDNE r9, r5, r9 ; mask off page offset
......@@ -430,6 +436,34 @@ physical_to_ppn ROUT
CLC
MOV pc, lr
;----------------------------------------------------------------------------------------
; ppn_to_physical
;
; In: r3 = page number
;
; Out: r9 corrupted
; CC => r5 = physical address
; CS => invalid page number, r5 corrupted
;
; Convert physical page number to physical address.
;
ppn_to_physical ROUT
Push "r3,lr"
LDR r9, =ZeroPage+PhysRamTable
10
LDMIA r9!, {r5,lr} ; Get start address and size of next block.
MOVS lr, lr, LSR #12
BEQ %FT20
CMP r3, lr
SUBHS r3, r3, lr
BHS %BT10
ADD r5, r5, r3, LSL #12
Pull "r3,pc"
20
SEC
Pull "r3,pc"
;----------------------------------------------------------------------------------------
; Symbols used in MemoryPhysSize and MemoryReadPhys
......@@ -505,7 +539,7 @@ MemoryReadPhys ROUT
MOV r4, #32 ; How much more we have to shift r3 before storing it.
LDR r6, =ZeroPage+CamEntriesPointer
LDR r7, [r6]
ADD r7, r7, #4 ; Point to PPL entries.
ADD r7, r7, #CAM_PageFlags ; Point to PPL entries.
LDR r8, [r6, #MaxCamEntry-CamEntriesPointer]
MOV r5, #0 ; last block address processed + 1
Push "r5"
......@@ -557,7 +591,7 @@ MemoryReadPhys ROUT
CMP r2, r9 ; If not reached start of block then page is not present.
ORRCC r3, r3, #(NotPresent :OR: NotAvailable) :SHL: 28
BCC %FT30
LDR lr, [r7, r5, LSL #3] ; Page is there so get PPL and determine if it's available or not.
LDR lr, [r7, r5, LSL #CAM_EntrySizeLog2] ; Page is there so get PPL and determine if it's available or not.
TST lr, #PageFlags_Unavailable
ORREQ r3, r3, #DRAM_Pattern :SHL: 28
ORRNE r3, r3, #(DRAM_Pattern :OR: NotAvailable) :SHL: 28
......@@ -921,7 +955,7 @@ RecommendPage ROUT
MOV r3,#0 ;page number, starts at 0
LDR r5,=ZeroPage+CamEntriesPointer
LDR r5,[r5]
ADD r5,r5,#4 ; [r5,<page no.>,LSL #3] addresses flags word in CAM
ADD r5,r5,#CAM_PageFlags ; [r5,<page no.>,LSL #3] addresses flags word in CAM
LDMIA r0!,{r7,r8} ;address,size of video chunk (skip this one)
;
RP_nextchunk
......@@ -948,7 +982,7 @@ RP_nextchunk
RP_nextpage
CMP r9,r1
BLO RP_nextchunk
LDR r6,[r5,r7,LSL #3] ;page flags from CAM
LDR r6,[r5,r7,LSL #CAM_EntrySizeLog2] ;page flags from CAM
;must not be marked Unavailable or Required
TST r6,#PageFlags_Unavailable :OR: PageFlags_Required
BEQ RP_checkotherpages
......@@ -963,7 +997,7 @@ RP_checkotherpages
ADD r10,r7,r1,LSR #12
SUB r10,r10,#1 ;last page required
RP_checkotherpagesloop
LDR r6,[r5,r10,LSL #3] ;page flags from CAM
LDR r6,[r5,r10,LSL #CAM_EntrySizeLog2] ;page flags from CAM
TST r6,#PageFlags_Unavailable :OR: PageFlags_Required
BNE RP_nextpagecontinue
SUB r10,r10,#1
......@@ -1309,6 +1343,7 @@ CMA_Partially_Phys * 1<<12
CMA_Partially_Abort * 1<<13
CMA_CheckL2PT * 1<<31 ; Pseudo flag used internally for checking sparse areas
CMA_DecodeAP * 1<<30 ; Used with CheckL2PT to indicate AP flags should be decoded from L2PT
; AP_ equivalents
CMA_ROM * CMA_Partially_UserR+CMA_Partially_PrivR
......@@ -1332,7 +1367,7 @@ CheckMemoryAccess ROUT
; * application space
; * dynamic areas
; * IO memory
; * special areas (stacks, ROM, HAL workspace, system heap, etc.)
; * special areas (stacks, ROM, HAL workspace, etc.)
; All ranges are checked in increasing address order, so the
; completeness flags are returned correctly if we happen to cross from
; one range into another
......@@ -1383,8 +1418,11 @@ CheckMemoryAccess ROUT
; Look through the quick lookup table until we find a valid DANode ptr
LDR r6, [r10, #DynArea_ws]
MOV r3, r1
TEQ r6, #0 ; We can get called during ROM init, before the workspace is allocated (pesky OS_Heap validating its pointers)
ADD r6, r6, #(:INDEX:DynArea_AddrLookup) :AND: &00FF
LDREQ r9, [r10, #DAList] ; So just start at the first DA
ADD r6, r6, #(:INDEX:DynArea_AddrLookup) :AND: &FF00
BEQ %FT22
21
AND r8, r3, #DynArea_AddrLookupMask
LDR r9, [r6, r8, LSR #30-DynArea_AddrLookupBits]
......@@ -1400,8 +1438,8 @@ CheckMemoryAccess ROUT
B %FT30
22
; Now that we've found a DA to start from, walk through and process all
; the entries until we hit the system heap (or any other DAs above
; IOAllocLimit)
; the entries until we hit the end of the list, or any DAs above
; IOAllocLimit
LDR r3, [r9, #DANode_Base]
LDR r6, [r9, #DANode_Flags]
CMP r3, r7
......@@ -1414,18 +1452,20 @@ CheckMemoryAccess ROUT
CMP lr, #2
MOVEQ r5, #CMA_None
MOVGT r5, #CMA_ROM
TST r6, #DynAreaFlags_SparseMap
TST r6, #DynAreaFlags_PMP
ORRNE r5, r5, #CMA_DecodeAP
TSTEQ r6, #DynAreaFlags_SparseMap
LDREQ lr, [r9, #DANode_Size]
LDRNE lr, [r9, #DANode_SparseHWM] ; Use HWM as bounds when checking sparse areas
LDRNE r4, [r9, #DANode_SparseHWM] ; Use HWM as bounds when checking sparse/PMP areas
ORRNE r5, r5, #CMA_CheckL2PT ; ... and request L2PT check
TST r6, #DynAreaFlags_DoublyMapped
ADD r4, r3, lr
ADDEQ r4, r3, lr
TST r6, #DynAreaFlags_DoublyMapped ; Currently impossible for Sparse/PMP areas - so use of lr safe
SUBNE r3, r3, lr
BL CMA_AddRange2
LDR r9, [r9, #DANode_Link]
TEQ r9, #0
BNE %BT22
; Hit the end of the list. This shouldn't happen with the current heap setup!
; Hit the end of the list
30
; IO memory
CMP r1, #IO
......@@ -1521,12 +1561,7 @@ CheckMemoryAccess ROUT
MOV r5, #CMA_None
BL CMA_AddRange
70
ASSERT CursorChunkAddress > HALWorkspaceNCNB
LDR r3, =CursorChunkAddress
MOV r4, #32*1024
MOV r5, #CMA_Read
BL CMA_AddRange
ASSERT L2PT > CursorChunkAddress
ASSERT L2PT > HALWorkspaceNCNB
LDR r3, =L2PT
MOV r5, #CMA_None
MOV r4, #4*1024*1024
......@@ -1537,14 +1572,12 @@ CheckMemoryAccess ROUT
MOV r4, #16*1024
MOV r5, #CMA_None
BL CMA_AddRange
; Note that system heap needs to be checked manually due to being
; outside main DA address range
ASSERT SysHeapChunkAddress > L1PT
LDR r3, =SysHeapChunkAddress
LDR r4, [r10, #SysHeapDANode + DANode_Size]
MOV r5, #CMA_Full
ASSERT CursorChunkAddress > L1PT
LDR r3, =CursorChunkAddress
MOV r4, #32*1024
MOV r5, #CMA_Read
BL CMA_AddRange
ASSERT CAM > SysHeapChunkAddress
ASSERT CAM > CursorChunkAddress
LDR r3, =CAM
LDR r4, [r10, #SoftCamMapSize]
MOV r5, #CMA_None
......@@ -1624,8 +1657,10 @@ CMA_AddRange2 ; r3 = start, r4 = end (excl.)
BICHS r2, r2, lr
MOVLO r2, r4
; r2 is now page aligned min(r2+1,r4)
BIC r4, r1, lr
LDR r8, =L2PT
TST r5, #CMA_DecodeAP
BIC r4, r1, lr
BNE %FT35
MOV r10, #0
30
BL logical_to_physical
......@@ -1643,4 +1678,35 @@ CMA_AddRange2 ; r3 = start, r4 = end (excl.)
BNE %BT04 ; Partially/entirely mapped
B %BT05 ; Completely unmapped
35
; Check L2PT, with AP decoding on a per-page basis
40
LDR r10, =&0F0F0F0F
BL logical_to_physical
BICCS r0, r0, r10 ; Not fully mapped, clear completion flags
BCS %FT45
; Get the L2PT entry and decode the flags
LDR r9, [r8, r4, LSR #10]
[ MEMM_Type = "VMSAv6"
AND r9, r9, #L2_AP
|
AND r9, r9, #L2X_AP
]
MOV r5, #CMA_ROM
CMP r9, #AP_None*L2X_APMult
MOVEQ r5, #CMA_None
CMP r9, #AP_Read*L2X_APMult
MOVEQ r5, #CMA_Read
CMP r9, #AP_Full*L2X_APMult
MOVEQ r5, #CMA_Full
ORR r10, r5, r10
ORR r0, r0, r5 ; Set new partial flags
AND r0, r0, r10, ROR #4 ; Discard completion flags which aren't for this range
45
ADD r4, r4, #4096
CMP r4, r2
BNE %BT40
Pull "r2,r4,r5,r8,r9,r10,lr"
B %BT05
END
......@@ -1894,6 +1894,7 @@ osri6_table
DCD ZeroPage+VduDriverWorkSpace+ECFShift ;84
DCD ZeroPage+VecPtrTab ;85
DCD NVECTORS ;86
DCD 1 ;87 CAM format: 0 = 8 bytes/entry, 1 = 16 bytes/entry
osri6_maxvalue * (.-4-osri6_table) :SHR: 2
......
This diff is collapsed.
......@@ -75,7 +75,9 @@ BangCamUpdate ROUT
LDR r1, =ZeroPage
LDR r1, [r1, #CamEntriesPointer]
ADD r1, r1, r2, LSL #3 ; point at cam entry (logaddr, PPL)
ADD r1, r1, r2, LSL #CAM_EntrySizeLog2 ; point at cam entry (logaddr, PPL)
ASSERT CAM_LogAddr=0
ASSERT CAM_PageFlags=4
LDMIA r1, {r0, r6} ; r0 = current logaddress, r6 = current PPL
BIC r4, r11, #PageFlags_Unsafe
STMIA r1, {r3, r4} ; store new address, PPL
......
......@@ -386,20 +386,8 @@ InitialiseMode ROUT
30
[ SoftResets
MOV r0, #&FD ; read last reset type
MOV r1, #0
MOV r2, #&FF
SWI XOS_Byte
CMP r1, #SoftReset
LDREQ r0, =ZeroPage+VduDriverWorkSpace+ModeNo
LDREQ r0, [r0] ; use previous mode if a soft reset
MOVNE r0, #1 ; otherwise read configured mode
SWINE XOS_ReadSysInfo
|
MOV r0, #1 ; no need to check for soft reset,
SWI XOS_ReadSysInfo ; always use configured value
]
MOV r1, r0
MOV r0, #ScreenModeReason_SelectMode
......
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