ChangeDyn 276 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
        TTL   => ChangeDyn

17 18
        ; OS_ChangeDynamicArea optimisations:

Jeffrey Lee's avatar
Jeffrey Lee committed
19 20
        GBLL  FastCDA_Bulk ; Do all cache/TLB maintenance in bulk instead of on a per-page basis
FastCDA_Bulk SETL {TRUE}
21 22 23 24

        GBLL  FastCDA_FIQs ; Don't thrash ClaimFIQ/ReleaseFIQ in DoTheGrowPagesSpecified
FastCDA_FIQs SETL {TRUE}

Jeffrey Lee's avatar
Jeffrey Lee committed
25
        GBLL  FastCDA_Unnecessary ; Avoid unnecessary cache cleaning in DoTheGrowPagesSpecified
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
FastCDA_Unnecessary SETL {TRUE}

        ; DoTheGrowPagesSpecified profiling code
        ; Written to use Cortex-A8 cycle count performance counter - will need modifying for other CPUs!

        GBLL  FastCDA_Prof
FastCDA_Prof SETL {FALSE}

      [ FastCDA_Prof
        ; Squeeze profiling workspace into "free space after envstring"
                                 ^ ExtendedROMFooter+4
        ! 0, "FastCDA_Prof workspace at ":CC::STR:@
FastCDA_Prof_DoTheGrowInit           # 4
FastCDA_Prof_MarkRequired            # 4
FastCDA_Prof_PagesUnsafe             # 4
Jeffrey Lee's avatar
Jeffrey Lee committed
41
FastCDA_Prof_DoublyRemoveCacheability # 4
42 43 44 45 46 47 48 49 50 51 52 53
FastCDA_Prof_DoublyMovePages         # 4
FastCDA_Prof_FindSpare               # 4
FastCDA_Prof_ClaimFIQ                # 4
FastCDA_Prof_AccessPhysical          # 4
FastCDA_Prof_CopyPage                # 4
FastCDA_Prof_ReleasePhysical         # 4
FastCDA_Prof_MoveReplacement         # 4
FastCDA_Prof_MoveNeeded              # 4
FastCDA_Prof_ReleaseFIQ              # 4
FastCDA_Prof_PagesSafe               # 4
FastCDA_Prof_CallPreGrow             # 4
FastCDA_Prof_CallPostGrow            # 4
Jeffrey Lee's avatar
Jeffrey Lee committed
54 55
FastCDA_Prof_MMUChangingCached       # 4 ; MMU_ChangingUncached followed by Cache_CleanInvalidateaAll
FastCDA_Prof_MMUChangingUncached     # 4 ; MMU_ChangingUncached followed by nothing
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
FastCDA_Prof_ChangingEntry           # 4
        ASSERT @ <= &500
      ]

        MACRO
        FastCDA_ProfInit $temp
      [ FastCDA_Prof
        MVN     $temp,#0
        MCR     p15,0,$temp,c9,c12,2
        MOV     $temp,#1<<31
        MCR     p15,0,$temp,c9,c12,1
        MOV     $temp,#7
        MCR     p15,0,$temp,c9,c12,0
      ]
        MEND

        MACRO
        FastCDA_ProfStart $var,$temp,$temp2,$temp3,$cc
      [ FastCDA_Prof
        LDR$cc  $temp,=ZeroPage+FastCDA_Prof_$var
        LDR$cc  $temp2,[$temp]
        MRC$cc  p15,0,$temp3,c9,c13,0
        SUB$cc  $temp2,$temp2,$temp3
        STR$cc  $temp2,[$temp]
      ]
        MEND

        MACRO
        FastCDA_ProfEnd $var,$temp,$temp2,$temp3,$cc
      [ FastCDA_Prof
        MRC$cc  p15,0,$temp3,c9,c13,0
        LDR$cc  $temp,=ZeroPage+FastCDA_Prof_$var
        LDR$cc  $temp2,[$temp]
        ADD$cc  $temp2,$temp2,$temp3
        STR$cc  $temp2,[$temp]
      ]
        MEND

Neil Turton's avatar
Neil Turton committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
;******************************************************************************
; ChangeDynamic SWI
; In  : R0 =  0 => System Heap,
;             1 => RMA
;             2 => Screen
;             3 => Sprite area
;             4 => Font cache
;             5 => RAM disc
;             6 => Free pool
;       R1 = no of bytes to change by
;
; Out : V set if CAO in AplWork or couldn't move all the bytes requested.
;       R1 set to bytes moved.
;******************************************************************************

AP_AppSpace     *       0                                       ; user r/w, CB
AP_SysHeap      *       0                                       ; user r/w, CB
AP_RMA          *       0                                       ; user r/w, CB
AP_Screen       *       0 :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_DoublyMapped :OR: DynAreaFlags_NeedsSpecificPages
AP_Sprites      *       0                                       ; user r/w, CB
AP_FontArea     *       2                                       ; user none, CB
115 116
AP_RAMDisc      *       2 :OR: DynAreaFlags_NotCacheable        ; user none, ~CB (poor performance for current StrongARMs)
AP_RAMDisc_SA   *       2                                       ; user none,
Neil Turton's avatar
Neil Turton committed
117
AP_Duff         *       2 :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_NotBufferable ; user none, ~C~B
118
AP_FreePool     *       2 :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_NotBufferable :OR: DynAreaFlags_PMP
Neil Turton's avatar
Neil Turton committed
119
AP_CursorChunk  *       1 :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_NotBufferable :OR: PageFlags_Unavailable
120

Neil Turton's avatar
Neil Turton committed
121 122 123 124
AP_L2PT         *       2 :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_NotBufferable ; user none, ~C~B
AP_L1PT         *       AP_L2PT :OR: PageFlags_Unavailable
AP_UndStackSoftCam *    PageFlags_Unavailable

125 126 127
  [ DA_Batman
ChangeDyn_Batcall    * -3               ; special DA number to select Batman usage of OS_ChangeDynamicArea
  ]
Neil Turton's avatar
Neil Turton committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
ChangeDyn_FreeAndApl * -2               ; special reason code for when we're sucking out of free pool and apl space
ChangeDyn_AplSpace   * -1
ChangeDyn_SysHeap    * 0
ChangeDyn_RMA        * 1
ChangeDyn_Screen     * 2
ChangeDyn_SpriteArea * 3
ChangeDyn_FontArea   * 4
ChangeDyn_RamFS      * 5
ChangeDyn_FreePool   * 6
ChangeDyn_MaxArea    * 6

; Area handler reason codes

DAHandler_PreGrow       *       0
DAHandler_PostGrow      *       1
DAHandler_PreShrink     *       2
DAHandler_PostShrink    *       3
145 146
 [ ShrinkableDAs
DAHandler_TestShrink    *       4       ; new reason added to find amount area could shrink by
Neil Turton's avatar
Neil Turton committed
147
 ]
148 149
DAHandler_Abort         *       5       ; ROL abortable DAs
DAHandler_ResizePMP     *       6       ; Called on OS_ChangeDynamicArea
Neil Turton's avatar
Neil Turton committed
150 151 152

; Number of entries in page block on stack

153
NumPageBlockEntries *   63
Neil Turton's avatar
Neil Turton committed
154 155 156
PageBlockSize   *       NumPageBlockEntries * 12
PageBlockChunk  *       NumPageBlockEntries * 4096

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
;
; mjs - performance enhancements (from Ursula, merged into HALised kernel June 2001)
; Workspace for acceleration of operations on a DA, by reducing need to traverse DA list.
;
; - accelerates allocating non-quick DA numbers to O(n) instead of laughable O(n*n), where n is no. of DAs
; - accelerates enumeration to O(n) instead of laughable O(n*n)
; - allocation of a quick handle (DA number) is O(1)
; - access of a DA node from a quick handle is O(1)
; - access of a DA node from a non-quick handle is O(1), if it repeats the most recent non-quick handle access (else O(n))
;
; - creation of a DA still has some O(n) work (requires search for address space), but is now rather quicker
; - removal of a DA is still O(n) (requires traversal of list in order to get previous node)
; - other uses of a DA with a quick handle (eg. get info, change size) avoid any O(n) work
;
; - all system handles will be quick.
; - non-system handles will be quick, except for very large numbers of DAs, or silly modules like the Wimp who insist on
;   their own silly DA number (the latter can still benefit from LastTreacleHandle - see below)
;
; Limitations:
; - does not allow anyone to choose their own DA number that clashes with the quick handle set - should not
;   be a problem since choosing own number reserved for Acorn use
; - does not allow anyone to renumber a DA with a quick handle - again, reserved for system use
; - DA names will be truncated to a maximum of 31 characters (or as defined below)
;
                                  GBLL DynArea_QuickHandles
DynArea_QuickHandles              SETL {TRUE}
;
      ;various bad things happen if DynArea_QuickHandles is FALSE (eg. some new API disappears)
      ;should remove FALSE build option to simplify source code next time kernel is updated (kept for reference/testing now)
      ASSERT DynArea_QuickHandles

                                  GBLL DynArea_NullNamePtrMeansHexString
DynArea_NullNamePtrMeansHexString SETL {TRUE} :LAND: DynArea_QuickHandles
;
  [ DynArea_QuickHandles
DynArea_MaxNameLength     * 31                      ;maximum length of DA name, excluding terminator (multiple of 4, -1)
DynArea_NumQHandles       * 256                     ;maximum no. of non-system quick handles available simultaneously
194 195 196
DynArea_AddrLookupBits    * 8                       ;LUT covers entire 4G logical space, so 4G>>8 = 16M granularity
DynArea_AddrLookupSize    * 1<<(32-DynArea_AddrLookupBits) ; Address space covered by each entry
DynArea_AddrLookupMask    * &FFFFFFFF-(DynArea_AddrLookupSize-1)
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
;
                          ^  0,R11
DynArea_TreacleGuess      # 4                       ;guess for next non-quick handle to allocate, if needed, is TreacleGuess+1
DynArea_CreatingHandle    # 4                       ;handle proposed but not yet committed, during DynArea_Create, or -1 if none
DynArea_CreatingPtr       # 4                       ;ptr to proposed DANode during DynArea_Create (invalid if CreatingHandle = -1)
DynArea_LastTreacleHandle # 4                       ;last non-quick handle accessed by a client (usually the Wimp), or -1 if none
DynArea_LastTreaclePtr    # 4                       ;ptr to DANode for last non-quick handle accessed (invalid if LastTreacleHandle = -1)
DynArea_LastEnumHandle    # 4                       ;last handle enumerated, or -1 if none
DynArea_LastEnumPtr       # 4                       ;ptr to DANode for last handle enumerated (invalid if LastEnumHandle = -1)
DynArea_ShrinkableSubList # 4                       ;sub list of dynamic areas that are Shrinkable (0 if none)
DynArea_OD6Signature      # 4                       ;signature of changes to non-system DAs since last call to OS_DynamicArea 6
                                                    ;bit  0 = 1 if any DAs have been created
                                                    ;bit  1 = 1 if any DAs have been removed
                                                    ;bit  2 = 1 if any DAs have been resized (excluding grow or shrink at creation or removal)
                                                    ;bit  3 = 1 if any DAs have been renumbered
                                                    ;bits 4-30   reserved (0)
                                                    ;bit 31 = 1 if next resize is not to update signature (used during create, remove)
DynArea_OD6PrevSignature  # 4                       ;previous signature, used to distinguish single from multiple changes
DynArea_OD6Handle         # 4                       ;handle of last DA that affected signature
DynArea_OD8Clamp1         # 4                       ;clamp value on area max size for OS_DynamicArea 0 with R5 = -1
                                                    ;(default -1, set by R1 of OS_DynamicArea 8)
DynArea_OD8Clamp2         # 4                       ;clamp value on area max size for OS_DynamicArea 0 with R5 > 0 (not Sparse)
                                                    ;(default -1, set by R2 of OS_DynamicArea 8)
DynArea_OD8Clamp3         # 4                       ;clamp value on area max size for OS_DynamicArea 0 for a Sparse area
                                                    ;(default 4G-4k, set by R3 of OS_DynamicArea 8)
DynArea_SortedList        # 4                       ;alphabetically sorted list of non-system areas, or 0 if none
DynArea_SysQHandleArray   # 4*(ChangeDyn_MaxArea+1) ;for system areas 0..MaxArea, word = ptr to DANode, or 0 if not created yet
DynArea_FreeQHandles      # 4                       ;index of first free quick handle, starting at 1 (or 0 for none)
DynArea_QHandleArray      # 4*DynArea_NumQHandles   ;1 word per quick handle
                                                    ; - if free, word = index of next free quick handle (or 0 if none)
                                                    ; - if used, word = ptr to DANode (must be > DynArea_NumQHandles)
228
DynArea_AddrLookup        # 4<<DynArea_AddrLookupBits ; Lookup table for fast logaddr -> dynarea lookup
229 230 231 232 233 234 235 236
;
DynArea_ws_size           *  :INDEX:@               ;must be multiple of 4
;
            ASSERT DynArea_QHandleArray = DynArea_FreeQHandles +4
  ]
;


Kevin Bracey's avatar
Kevin Bracey committed
237
;        InsertDebugRoutines
Neil Turton's avatar
Neil Turton committed
238 239 240 241

; Exit from ChangeDynamicArea with error Not all moved

failure_IRQgoingClearSemaphore
Jeffrey Lee's avatar
Jeffrey Lee committed
242 243
        LDR     r0, =ZeroPage
      [ ZeroPage = 0
Neil Turton's avatar
Neil Turton committed
244
        STR     r0, [r0, #CDASemaphore]
Jeffrey Lee's avatar
Jeffrey Lee committed
245 246 247 248
      |
        MOV     r10, #0
        STR     r10, [r0, #CDASemaphore]
      ]
Neil Turton's avatar
Neil Turton committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
failure_IRQgoing
        ADR     r0, ErrorBlock_ChDynamNotAllMoved
ChangeDynamic_Error
        MOV     r10, #0
        STR     r0, [stack]
        LDR     lr, [stack, #4*10]
        ORR     lr, lr, #V_bit
        STR     lr, [stack, #4*10]
CDS_PostServiceWithRestore
      [ International
        LDR     r0, [stack]
        BL      TranslateError
        STR     r0, [stack]
      ]

; and drop thru to ...

CDS_PostService
        MOV     r1, #Service_MemoryMoved
        MOV     r0, r10                 ; amount moved
        MOVS    r2, r11                 ; which way was transfer?
        BMI     %FT47                   ; [definitely a grow]
        CMP     r11, #ChangeDyn_FreePool
        BNE     %FT48                   ; [definitely a shrink]
        CMP     r12, #ChangeDyn_AplSpace
        BEQ     %FT48                   ; [a shrink]
47
        RSB     r0, r0, #0             ; APLwork or free was source
        MOV     r2, r12                ; r2 = area indicator
48
        BL      Issue_Service

        MOV     r1, r10                ; amount moved

        Pull    "r0, r2-r9, r10, lr"
        ExitSWIHandler

        MakeErrorBlock ChDynamNotAllMoved

288

Neil Turton's avatar
Neil Turton committed
289 290
; in:   r0 = logical address where page is now

291
GetPageFlagsForR0IntoR6 Entry "R0-R2, R4-R5, R7"
Neil Turton's avatar
Neil Turton committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
;
; code from MoveCAMatR0toR3
;
        LDR     r5, =L2PT
        ADD     r4, r5, r0, LSR #10             ; r4 -> L2PT for log addr r0
        MOV     r2, r4, LSR #12
        LDR     r2, [r5, r2, LSL #2]            ; r2 = L2PT entry for r4
        TST     r2, #3                          ; if no page there
        BEQ     %FT90                           ; then cam corrupt

        LDR     r4, [r4]                        ; r4 = L2PT entry for r0
        TST     r4, #3                          ; check entry is valid too
        BEQ     %FT91
        MOV     r4, r4, LSR #12                 ; r4 = phys addr >> 12

Jeffrey Lee's avatar
Jeffrey Lee committed
307
        LDR     r2, =ZeroPage
Neil Turton's avatar
Neil Turton committed
308
        LDR     r6, [r2, #MaxCamEntry]
Jeffrey Lee's avatar
Jeffrey Lee committed
309 310 311 312
        ADD     r5, r2, #PhysRamTable
      [ ZeroPage <> 0
        MOV     r2, #0
      ]
Neil Turton's avatar
Neil Turton committed
313 314 315 316 317 318 319 320 321 322 323 324 325
10
        CMP     r2, r6                          ; if page we've got to is > max
        BHI     %FT92                           ; then corrupt
        LDMIA   r5!, {r7, lr}                   ; get phys.addr, size
        SUB     r7, r4, r7, LSR #12             ; number of pages into this bank
        CMP     r7, lr, LSR #12                 ; if too many
        ADDCS   r2, r2, lr, LSR #12             ; then advance physical page no.
        BCS     %BT10                           ; and loop

        ADD     r2, r2, r7                      ; add on number of pages within bank
;
; code from BangCamUpdate
;
Jeffrey Lee's avatar
Jeffrey Lee committed
326
        LDR     r1, =ZeroPage
Neil Turton's avatar
Neil Turton committed
327
        LDR     r1, [r1, #CamEntriesPointer]
328 329 330
        ADD     r1, r1, r2, LSL #CAM_EntrySizeLog2 ; point at cam entry (logaddr, PPL)
        ASSERT  CAM_LogAddr=0
        ASSERT  CAM_PageFlags=4
Neil Turton's avatar
Neil Turton committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
        LDMIA   r1, {r0, r6}                    ; r0 = current logaddress, r6 = current PPL
        EXIT

90
        ADR     lr, NoL2ForPageBeingRemovedError ; NB don't corrupt r0 yet - we need that in block as evidence
95
        STR     lr, [sp]                        ; update returned r0
        BL      StoreDebugRegs
        PullEnv                                 ; seriously broken memory
        SETV
        MOV     pc, lr

91
        ADR     lr, PageBeingRemovedNotPresentError
        B       %BT95

92
        ADR     lr, PhysicalAddressNotFoundError
        B       %BT95


; MoveCAMatR0toR3
; in:   r0 = old logaddr
;       r3 = new logaddr
355
;       r9 = offset from 1st to 2nd copy of doubly mapped area (either source or dest, but not both)
Neil Turton's avatar
Neil Turton committed
356 357 358 359 360 361
;       r11 = page protection level
;
; out:  r2 = physical page number of page moved, unless there was a serious error
;       r0,r1,r3,r6-r12 preserved
;       r4,r5 corrupted

362
MoveCAMatR0toR3 Entry "r0,r1,r6,r7"
Neil Turton's avatar
Neil Turton committed
363 364 365 366 367 368 369 370 371 372 373 374
        LDR     r5, =L2PT
        ADD     r4, r5, r0, LSR #10             ; r4 -> L2PT for log addr r0
        MOV     r2, r4, LSR #12
        LDR     r2, [r5, r2, LSL #2]            ; r2 = L2PT entry for r4
        TST     r2, #3                          ; if no page there
        BEQ     %FT90                           ; then cam corrupt

        LDR     r4, [r4]                        ; r4 = L2PT entry for r0
        TST     r4, #3                          ; check entry is valid too
        BEQ     %FT91
        MOV     r4, r4, LSR #12                 ; r4 = phys addr >> 12

Jeffrey Lee's avatar
Jeffrey Lee committed
375
        LDR     r2, =ZeroPage
Neil Turton's avatar
Neil Turton committed
376
        LDR     r6, [r2, #MaxCamEntry]
Jeffrey Lee's avatar
Jeffrey Lee committed
377 378 379 380
        ADD     r5, r2, #PhysRamTable
      [ ZeroPage <> 0
        MOV     r2, #0
      ]
Neil Turton's avatar
Neil Turton committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
10
        CMP     r2, r6                          ; if page we've got to is > max
        BHI     %FT92                           ; then corrupt
        LDMIA   r5!, {r7, lr}                   ; get phys.addr, size
        SUB     r7, r4, r7, LSR #12             ; number of pages into this bank
        CMP     r7, lr, LSR #12                 ; if too many
        ADDCS   r2, r2, lr, LSR #12             ; then advance physical page no.
        BCS     %BT10                           ; and loop

        ADD     r2, r2, r7                      ; add on number of pages within bank
        BL      BangCamUpdate
        CLRV
        EXIT

90
        ADR     lr, NoL2ForPageBeingRemovedError ; NB don't corrupt r0 yet - we need that in block as evidence
95
        STR     lr, [sp]                        ; update returned r0
        BL      StoreDebugRegs
        PullEnv                                 ; seriously broken memory
        SETV
        MOV     pc, lr

91
        ADR     lr, PageBeingRemovedNotPresentError
        B       %BT95

92
        ADR     lr, PhysicalAddressNotFoundError
        B       %BT95

Jeffrey Lee's avatar
Jeffrey Lee committed
412
StoreDebugRegs ; Note: Corrupts R0,R1
Neil Turton's avatar
Neil Turton committed
413
        Push    "lr"
Jeffrey Lee's avatar
Jeffrey Lee committed
414 415 416 417 418
        LDR     lr, =ZeroPage+CamMapCorruptDebugBlock
        STMIA   lr, {r0-r12}
        STR     sp, [lr, #13*4]!
        LDMIA   sp, {r0,r1}                     ; reload stacked LR & return R0 (error pointer)
        STMIB   lr, {r0,r1}                     ; LR -> LR, error -> PC
Neil Turton's avatar
Neil Turton committed
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
        Pull    "pc"

NoL2ForPageBeingRemovedError
        &       0
        =       "Memory Corrupt: No L2PT for page being removed", 0
        ALIGN

PageBeingRemovedNotPresentError
        &       0
        =       "Memory Corrupt: Page being removed was not present", 0
        ALIGN

PhysicalAddressNotFoundError
        &       0
        =       "Memory Corrupt: Physical address not found", 0
        ALIGN

CamMapBroke
        &       0
        =       "!!!! CAM Map Corrupt !!!!", 0
        ALIGN
440 441 442 443 444
; Call_CAM_Mapping
; in:   r2 = physical page number
;       r3 = logical address (2nd copy of doubly mapped area)
;       r9 = offset from 1st to 2nd copy of doubly mapped area (either source or dest, but not both)
;       r11 = PPL + CB bits
Neil Turton's avatar
Neil Turton committed
445 446 447 448 449
Call_CAM_Mapping
        Push    "r0, r1, r4, r6, lr"
        BL      BangCamUpdate
        Pull    "r0, r1, r4, r6, pc"

Jeffrey Lee's avatar
Jeffrey Lee committed
450 451 452 453
  [ FastCDA_Bulk
; RemoveCacheabilityR0ByMinusR2
; Make a range of pages (temporarily) uncacheable prior to (re)moving them
; Doesn't perform any cache/TLB maintenance
454 455 456
; in:   r0 = end of area
;       r2 = size of area (must be nonzero)
; out:  r6 has DynAreaFlags_NotCacheable set if entire region noncacheable
Jeffrey Lee's avatar
Jeffrey Lee committed
457
;              Flag clear if at least one page was cacheable
458 459 460
;       r0 points to start of area
;
;       4K page size assumed!
Jeffrey Lee's avatar
Jeffrey Lee committed
461 462 463 464
RemoveCacheabilityR0ByMinusR2 ROUT
        Entry   "r1-r5"
        MOV     r5, #DynAreaFlags_NotCacheable
        MOV     r1, #-1
465 466 467
10
        SUB     r0, r0, #4096
        BL      GetPageFlagsForR0IntoR6
Jeffrey Lee's avatar
Jeffrey Lee committed
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        TST     r6, #DynAreaFlags_NotCacheable
        BNE     %FT90
        ; Work out required page flags - use cached flags from last page if possible
        CMP     r1, r6
        BEQ     %FT20
        LDR     r3, =ZeroPage
        MOV     r1, r6
        LDR     r3, [r3, #MMU_PCBTrans]
        GetTempUncache r4, r6, r3, lr
20
        ; Update the current L2PT entry
        LDR     r3, =L2PT
        LDR     lr, =TempUncache_L2PTMask
        LDR     r5, [r3, r0, LSR #10]
        BIC     r5, r5, lr
        ORR     r5, r5, r4
        STR     r5, [r3, r0, LSR #10]
        ; Clear the flag from R5
        MOV     r5, #0
90
488 489
        SUBS    r2, r2, #4096
        BNE     %BT10
Jeffrey Lee's avatar
Jeffrey Lee committed
490
        MOV     r6, r5
491 492
        EXIT
  ]
Neil Turton's avatar
Neil Turton committed
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r0 bits 0..6 = area number
;       r0 bit 7 set => return max area size in r2 (implemented 13 Jun 1990)
;                       this will return an error if not implemented
; Out   r0 = address of area
;       r1 = current size of area
;       r2 = max size of area if r0 bit 7 set on entry (preserved otherwise)

; TMD 19-May-93: When this is updated to new CDA list, change meaning as follows:

; r0 in range 0..&7F    return address, size of area r0
;             &80..&FF  return address, size, maxsize of area (r0-&80)
;             &100..    return address, size, maxsize of area r0

; TMD 20-Aug-93: New bit added - if r0 = -1 on entry, then returns info on application space
; r0 = base address (&8000)
; r1 = current size (for current task)
; r2 = maximum size (eg 16M-&8000)

ReadDynamicArea ROUT

readdyn_returnR2bit     *       &80
        ASSERT  ChangeDyn_MaxArea < readdyn_returnR2bit

518
        CMP     r0, #ChangeDyn_AplSpace         ; if finding out about app space
Jeffrey Lee's avatar
Jeffrey Lee committed
519
      [ ZeroPage = 0
Neil Turton's avatar
Neil Turton committed
520
        LDREQ   r1, [r0, #AplWorkSize+1]        ; then r1 = current size
Jeffrey Lee's avatar
Jeffrey Lee committed
521 522 523 524
      |
        LDREQ   r1, =ZeroPage
        LDREQ   r1, [r1, #AplWorkSize]
      ]
525 526 527
; [ HAL32
;        LDREQ   r2, [r0, #RAMLIMIT+1]
; |
Neil Turton's avatar
Neil Turton committed
528
        LDREQ   r2, =AplWorkMaxSize             ; and r2 = max size
529
; ]
Neil Turton's avatar
Neil Turton committed
530 531 532 533 534 535 536 537 538 539 540
        MOVEQ   r0, #&8000                      ; r0 = base address
        SUBEQ   r1, r1, r0                      ; adjust size and maxsize
        SUBEQ   r2, r2, r0                      ; to remove bottom 32K
        ExitSWIHandler EQ

; first check if it's one of the new ones

        Push    "r1,lr"
        CMP     r0, #&100                       ; if area >= &100
        MOVCS   r1, r0                          ; then just use area
        BICCC   r1, r0, #readdyn_returnR2bit    ; else knock off bit 7
541 542 543
  [ DynArea_QuickHandles
        BL      QCheckAreaNumber                ; out: r10 -> node
  |
Neil Turton's avatar
Neil Turton committed
544
        BL      CheckAreaNumber                 ; out: r10 -> node
545
  ]
Neil Turton's avatar
Neil Turton committed
546 547 548
        Pull    "r1,lr"
        BCC     %FT05                           ; [not a new one, so use old code]

549 550 551
        LDR     r11, [r10, #DANode_Flags]
        TST     r11, #DynAreaFlags_PMP
        BNE     %FT01
Neil Turton's avatar
Neil Turton committed
552 553 554 555 556 557
        CMP     r0, #&80                        ; CS => load maxsize into R2
                                                ; (do this either if bit 7 set, or area >=&100)
        LDRCS   r2, [r10, #DANode_MaxSize]
        LDR     r1, [r10, #DANode_Size]         ; r1 = current size
        LDR     r0, [r10, #DANode_Base]         ; r0 -> base
        TST     r11, #DynAreaFlags_DoublyMapped
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
        SUBNE   r0, r0, r1                      ; if doubly mapped then return start of 1st copy for compatibility
        ExitSWIHandler
01
        ; Convert physical parameters into byte counts
        CMP     r0, #&80
        BCC     %FT02
        LDR     r2, [r10, #DANode_PMPMaxSize]
        CMP     r2, #DynArea_PMP_BigPageCount
        MOVLO   r2, r2, LSL #12
        LDRHS   r2, =DynArea_PMP_BigByteCount
02
        LDR     r1, [r10, #DANode_PMPSize]
        CMP     r1, #DynArea_PMP_BigPageCount
        MOVLO   r1, r1, LSL #12
        LDRHS   r1, =DynArea_PMP_BigByteCount
        LDR     r0, [r10, #DANode_Base]
Neil Turton's avatar
Neil Turton committed
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
        ExitSWIHandler
05
        ADRL    r0, ErrorBlock_BadDynamicArea
      [ International
        Push    "lr"
        BL      TranslateError
        Pull    "lr"
      ]
        B       SLVK_SetV

        MakeErrorBlock  BadDynamicArea

; *************************************************************************
; User access to CAM mapping
; ReadMemMapInfo:
; returns R0 = pagsize
;         R1 = number of pages in use  (= R2 returned from SetEnv/Pagesize)
; *************************************************************************

ReadMemMapInfo_Code
Jeffrey Lee's avatar
Jeffrey Lee committed
594
      LDR      R10, =ZeroPage
Neil Turton's avatar
Neil Turton committed
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
      LDR      R0, [R10, #Page_Size]
      LDR      R1, [R10, #RAMLIMIT]    ; = total memory size
      ADRL     R11, PageShifts-1
      LDRB     R11, [R11, R0, LSR #12]
      MOV      R1, R1, LSR R11
      ExitSWIHandler

; ************************************************************************
; SWI ReadMemMapEntries: R0 pointer to list.
;  Entries are three words long, the first of which is the CAM page number.
;  List terminated by -1.
; Returns pagenumber (unaltered)/address/PPL triads as below
; ************************************************************************

ReadMemMapEntries_Code  ROUT
        Push    "r0,r14"
Jeffrey Lee's avatar
Jeffrey Lee committed
611
        LDR     r14, =ZeroPage
Neil Turton's avatar
Neil Turton committed
612 613 614
        LDR     r10, [r14, #CamEntriesPointer]
        LDR     r14, [r14, #MaxCamEntry]
01
615
        LDR     r12, [r0], #4                   ; page number
Neil Turton's avatar
Neil Turton committed
616 617 618
        CMP     r12, r14
        Pull    "r0,r14", HI
        ExitSWIHandler HI
619 620 621 622 623 624 625 626 627

   [ ChocolateAMB
        ;may need AMB to make mapping honest (as if not lazy), if page is in currently mapped app
        Push    "r0, lr"
        MOV     r0, r12                         ; page number to make honest
        BL      AMB_MakeHonestPN
        Pull    "r0, lr"
   ]

628 629 630
        ADD     r11, r10, r12, LSL #CAM_EntrySizeLog2
        ASSERT  CAM_LogAddr=0
        ASSERT  CAM_PageFlags=4
Neil Turton's avatar
Neil Turton committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        LDMIA   r11, {r11, r12}
        STMIA   r0!, {r11, r12}
        B       %BT01

; ************************************************************************
; SWI FindMemMapEntries:
; In:  R0 -> table of 12-byte page entries
;       +0      4       probable page number (0..npages-1) (use 0 if no idea)
;       +4      4       logical address to match with
;       +8      4       undefined
;       terminated by a single word containing -1
;
; Out: table of 12-byte entries updated:
;       +0      4       actual page number (-1 => not found)
;       +4      4       address (preserved)
;       +8      4       page protection level (3 if not found)
;       terminator preserved
;
; ************************************************************************

FindMemMapEntries_Code  ROUT

; Code for expanded CAM map version

        Push    "r0, r9, r14"
Jeffrey Lee's avatar
Jeffrey Lee committed
656
        LDR     r14, =ZeroPage
Neil Turton's avatar
Neil Turton committed
657 658
        LDR     r9, [r14, #MaxCamEntry]
        LDR     r14, [r14, #CamEntriesPointer]  ; r14 -> start of cam map
659
        ADD     r9, r14, r9, LSL #CAM_EntrySizeLog2 ; r9 -> first word of last entry in cam map
Neil Turton's avatar
Neil Turton committed
660 661 662 663 664 665 666
10
        LDR     r10, [r0, #0]                   ; r10 = guess page number (or -1)
        CMP     r10, #-1                        ; if -1 then end of list
        Pull    "r0, r9, r14", EQ               ; so restore registers
        ExitSWIHandler EQ                       ; and exit

        LDR     r11, [r0, #4]                   ; r11 = logical address
667 668 669 670 671 672 673 674 675

   [ ChocolateAMB
        ;may need AMB to make mapping honest (as if not lazy), if page is in currently mapped app
        Push    "r0, lr"
        MOV     r0, r11                         ; logical address to make honest
        BL      AMB_MakeHonestLA                ; note, quickly dismisses non app space addresses
        Pull    "r0, lr"
   ]

676
        ADD     r10, r14, r10, LSL #CAM_EntrySizeLog2 ; form address with 'guess' page
Neil Turton's avatar
Neil Turton committed
677 678 679
        CMP     r10, r9                         ; if off end of CAM
        BHI     %FT20                           ; then don't try to use the guess

680
        LDR     r12, [r10, #CAM_LogAddr]        ; load address from guessed page
Neil Turton's avatar
Neil Turton committed
681 682 683 684 685 686 687 688 689 690 691 692 693
        TEQ     r11, r12                        ; compare address
        BEQ     %FT60                           ; if equal, then guessed page was OK
20

; for now, cheat by looking in L2PT, to see if we can speed things up

        Push    "r5-r8"                         ; need some registers here!
        LDR     r10, =L2PT
        MOV     r8, r11, LSR #12                ; r8 = logical page number
        ADD     r8, r10, r8, LSL #2             ; r8 -> L2PT entry for log.addr
        MOV     r5, r8, LSR #12                 ; r5 = page offset to L2PT entry for log.addr
        LDR     r5, [r10, r5, LSL #2]           ; r5 = L2PT entry for L2PT entry for log.addr
        TST     r5, #3                          ; if page not there
694
        SUBEQ   r10, r9, #CAM_EntrySizeLog2     ; then invalid page so go from last one
Neil Turton's avatar
Neil Turton committed
695 696 697 698
        BEQ     %FT45
        LDR     r8, [r8]                        ; r8 = L2PT entry for log.addr
        MOV     r8, r8, LSR #12                 ; r8 = physaddr / 4K

Jeffrey Lee's avatar
Jeffrey Lee committed
699
        LDR     r5, =ZeroPage+PhysRamTable
700
        SUB     r10, r14, #CAM_EntrySize
Neil Turton's avatar
Neil Turton committed
701 702 703 704 705 706
30
        CMP     r10, r9                         ; have we run out of RAM banks?
        BCS     %FT40                           ; then fail
        LDMIA   r5!, {r6,r7}                    ; load next address, size
        SUB     r6, r8, r6, LSR #12             ; number of pages into this bank
        CMP     r6, r7, LSR #12                 ; if more than there are
707
        ASSERT  CAM_EntrySizeLog2 <= 16
708
        BICCS   r7, r7, #&F00
709
        ADDCS   r10, r10, r7, LSR #12-CAM_EntrySizeLog2 ; then advance CAM entry position
Neil Turton's avatar
Neil Turton committed
710 711
        BCS     %BT30                           ; and loop to next bank

712
        ADD     r10, r10, r6, LSL #CAM_EntrySizeLog2 ; advance by 2 words for each page in this bank
Neil Turton's avatar
Neil Turton committed
713
40
714
        SUBCS   r10, r9, #CAM_EntrySize         ; search from last one, to fail quickly (if CS)
Neil Turton's avatar
Neil Turton committed
715 716 717 718
45
        Pull    "r5-r8"
50
        CMP     r10, r9                         ; if not just done last one,
719 720
        ASSERT  CAM_LogAddr=0
        LDRNE   r12, [r10, #CAM_EntrySize]!     ; then get logical address
Neil Turton's avatar
Neil Turton committed
721 722 723 724 725 726 727 728
        TEQNE   r11, r12                        ; compare address
        BNE     %BT50                           ; loop if not same and not at end

; either found page or run out of pages

        TEQ     r11, r12                        ; see if last one matched
                                                ; (we always load at least one!)
60
729
        LDREQ   r12, [r10, #CAM_PageFlags]      ; if match, then r12 = PPL
Neil Turton's avatar
Neil Turton committed
730
        SUBEQ   r10, r10, r14                   ; and page number=(r10-r14)>>3
731
        MOVEQ   r10, r10, LSR #CAM_EntrySizeLog2
Neil Turton's avatar
Neil Turton committed
732 733 734 735 736 737 738 739 740 741

        MOVNE   r10, #-1                        ; else unknown page number indicator
        MOVNE   r12, #3                         ; and PPL=3 (no user access)

        STMIA   r0!, {r10-r12}                  ; store all 3 words
        B       %BT10                           ; and go back for another one

;**************************************************************************
; SWI SetMemMapEntries: R0 pointer to list of CAM page/address/PPL triads,
;  terminated by -1.
742
; address of -1 means "put the page out of the way"
Neil Turton's avatar
Neil Turton committed
743 744
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

745 746 747 748 749
; note, if ChocolateAMB, no MakeHonest consideration here, this SWI just
; changes the mapping of pages regardless of their current mapping, and
; assumes the caller knows what he is doing (ho ho)
;

Neil Turton's avatar
Neil Turton committed
750 751 752 753
SetMemMapEntries_Code  ROUT
        Push    "r0-r6, r9, lr"
        MOV     r12, r0

754
; BangCamUpdate takes entry no in r2, logaddr to set to in r3, r11 = PPL
Neil Turton's avatar
Neil Turton committed
755 756
; corrupts r0,r1,r4,r6

Jeffrey Lee's avatar
Jeffrey Lee committed
757
        LDR     r9, =ZeroPage
Neil Turton's avatar
Neil Turton committed
758
        LDR     r5, [r9, #MaxCamEntry]
759 760
        LDR     r9, [r9, #CamEntriesPointer]
        ADD     r9, r9, #CAM_PageFlags
Neil Turton's avatar
Neil Turton committed
761 762 763 764 765
01
        LDR     r2, [r12], #4
        CMP     r2, r5
        BHI     %FT02                   ; finished
        LDMIA   r12!, {r3, r11}
Kevin Bracey's avatar
Kevin Bracey committed
766
 [ {FALSE}
Neil Turton's avatar
Neil Turton committed
767
        AND     r11, r11, #3
Kevin Bracey's avatar
Kevin Bracey committed
768
 ]
Neil Turton's avatar
Neil Turton committed
769 770 771
        CMP     r3, #-1
        LDRHS   r3, =DuffEntry
        MOVHS   r11, #AP_Duff
772 773 774 775 776 777
        ; Ensure PMP membership flag is retained - just in case caller doesn't
        ; know what he's doing
        LDR     r0, [r9, r2, LSL #CAM_EntrySizeLog2]
        AND     r0, r0, #DynAreaFlags_PMP
        BIC     r11, r11, #DynAreaFlags_PMP
        ORR     r11, r11, r0
Neil Turton's avatar
Neil Turton committed
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
        BL      BangCamUpdate
        B       %BT01
02
        Pull    "r0-r6, r9, lr"
        ExitSWIHandler

        LTORG



;**************************************************************************
;
;       DynamicAreaSWI - Code to handle SWI OS_DynamicArea
;
; in:   r0 = reason code
;       Other registers depend on reason code
;
; out:  Depends on reason code
;

798 799 800 801 802 803

DAReason_Create          *  0
DAReason_Remove          *  1
DAReason_GetInfo         *  2
DAReason_Enumerate       *  3
DAReason_Renumber        *  4
804
 [ ShrinkableDAs
805
DAReason_ReturnFree      *  5   ;if ShrinkableDAs, else reason code invalid
Neil Turton's avatar
Neil Turton committed
806
 ]
807 808 809 810
 [ DynArea_QuickHandles
DAReason_GetChangeInfo   *  6   ;if DynArea_Quickhandles, else reason code invalid
DAReason_EnumerateInfo   *  7   ;if DynArea_Quickhandles, else reason code invalid
DAReason_SetClamps       *  8   ;if DynArea_Quickhandles, else reason code invalid
Neil Turton's avatar
Neil Turton committed
811
 ]
812 813 814 815
 [ DA_Batman
DAReason_SparseClaim     *  9   ;if DA_Batman, else reason code invalid
DAReason_SparseRelease   * 10   ;if DA_Batman, else reason code invalid
 ]
816
DAReason_LocateAddress   * 20
817 818 819 820 821 822
DAReason_PMP_PhysOp      * 21
DAReason_PMP_LogOp       * 22
DAReason_PMP_Resize      * 23
DAReason_PMP_GetInfo     * 24
DAReason_PMP_GetPages    * 25
DAReason_Limit           * 26   ;end of defined DA reasons
Neil Turton's avatar
Neil Turton committed
823 824


825 826
DynArea_NewAreas *      &100            ; Allocated area numbers start here
DynArea_NewAreasBase *  &04000000       ; Allocated area addresses start here
827 828
DynArea_PMP_BigPageCount * 1:SHL:(31-12) ; If PMP has >= this many pages...
DynArea_PMP_BigByteCount * &7FFFF000     ; Then convert to this byte value
Neil Turton's avatar
Neil Turton committed
829

830 831 832 833 834 835 836 837 838 839 840 841 842 843
; Bits in dynamic area flags (and page flags)
;
; rearranged slightly for Ursula - allow room for some expansion of DA flags in future without moving page flags
; mjs June 2001 merged the Ursula arrangement into HALised kernel
;
DynAreaFlags_APBits             * 15 :SHL:  0   ; currently only uses 2 bits, but may extend to allow svc/usr read-only
DynAreaFlags_NotBufferable      *  1 :SHL:  4
DynAreaFlags_NotCacheable       *  1 :SHL:  5
DynAreaFlags_DoublyMapped       *  1 :SHL:  6
DynAreaFlags_NotUserDraggable   *  1 :SHL:  7
DynAreaFlags_NeedsSpecificPages *  1 :SHL:  8   ; whether area will ever require particular physical pages
DynAreaFlags_Shrinkable         *  1 :SHL:  9   ; whether area may be shrunk when need more space in free pool
DynAreaFlags_SparseMap          *  1 :SHL: 10   ; whether area may have non-contiguous mapping of pages (Holey dynamic areas Batman!)
DynAreaFlags_PiersBinding       *  1 :SHL: 11   ; whether area is bound to client application, and so may be swapped out with it (not implemented yet)
Kevin Bracey's avatar
Kevin Bracey committed
844 845 846 847 848 849
DynAreaFlags_CPBits             *  7 :SHL: 12   ; cache policy variant for NotBufferable and NotCacheable bits

; Cache policies
;
CP_NCNB_Default                 * 0             ; no policy variants

850
CP_NCB_Default                  * 0             ; OS decides buffer policy (currently always MergingIdempotent)
Kevin Bracey's avatar
Kevin Bracey committed
851 852
CP_NCB_NonMerging               * 1             ; Non-merging write buffer. If not available, unbuffered.
CP_NCB_Merging                  * 2             ; Merging write buffer. If not available, non-merging.
853
CP_NCB_MergingIdempotent        * 3             ; Merging write buffer with idempotent memory (i.e. VMSA "Normal" non-cacheable type). If not available, merging write buffer.
Kevin Bracey's avatar
Kevin Bracey committed
854 855 856 857 858 859 860 861 862 863 864

CP_CNB_Default                  * 0             ; OS decides cache policy (writethrough). NCNB if not available
CP_CNB_Writethrough             * 1             ; Writethrough cacheable, non-buffered. If not available, NCNB.
CP_CNB_Writeback                * 2             ; Writeback cacheable, non-buffered. If not available,CNB_Writethrough.

CP_CB_Default                   * 0             ; OS decides cache policy (WB if available, W alloc if HAL requests)
CP_CB_Writethrough              * 1             ; Writethrough cacheable, read allocate. If not available, NCB_Merging
CP_CB_WritebackReadAlloc        * 2             ; Writeback cacheable, read allocate. If not available, writethrough.
CP_CB_WritebackWriteAlloc       * 3             ; Writeback cacheable, write allocate. If not available, WB/R.
CP_CB_AlternativeDCache         * 4             ; Use XScale/SA11x0 mini-data cache. If not available, CB_Default.

865
DynAreaFlags_NeedsDMA           *  1 :SHL: 15   ; only allocate from DMAable memory
866 867 868 869
; Bits 16-19 are used by RISCOS Ltd. We can reuse them for internal flags, but
; should probably avoid allocating any public flags.
DynAreaFlags_PMP                *  1 :SHL: 20   ; DA is backed by PMP/page is member of PMP

870
;
871 872
; Public page flags (note - may overlap DA flags)
; DynAreaFlags_[PMP]AccessMask also describes public page flags
873
;
874 875
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)

876
;
877
; Internal page flags (note - may overlap DA flags)
878 879
;
TempUncacheableShift            * 16
880
PageFlags_TempUncacheableBits   * 15 :SHL: TempUncacheableShift    ; temporary count of uncacheability, used by DMA mgr (via OS_Memory 0)
881 882
PageFlags_Required              *  1 :SHL: 21                      ; physical page asked for by handler (only set temporarily)

883
;
884
; Temporary flags only used by kernel (note - may overlap DA flags)
885
;
886 887 888 889 890 891 892 893
PageFlags_Unsafe                *  1 :SHL: 31                      ; skip cache/TLB maintenance in BangCamUpdate. flag not saved to CAM map.

; Mask to convert DANode_Flags to page flags
DynAreaFlags_AccessMask * DynAreaFlags_APBits :OR: DynAreaFlags_NotBufferable :OR: DynAreaFlags_NotCacheable :OR: DynAreaFlags_DoublyMapped :OR: DynAreaFlags_CPBits :OR: DynAreaFlags_PMP
; PMP LogOp can specify these flags
DynAreaFlags_PMPLogOpAccessMask * (DynAreaFlags_AccessMask :OR: PageFlags_Unavailable) :AND: :NOT: (DynAreaFlags_DoublyMapped :OR: DynAreaFlags_PMP)
; PMP PhysOp can specify these flags
DynAreaFlags_PMPPhysOpAccessMask * PageFlags_Unavailable
Neil Turton's avatar
Neil Turton committed
894 895


896
DynamicAreaSWI Entry
Neil Turton's avatar
Neil Turton committed
897 898 899 900 901 902 903 904 905 906 907 908 909 910
        BL      DynAreaSub
        PullEnv
        ORRVS   lr, lr, #V_bit
        ExitSWIHandler

DynAreaSub
        CMP     r0, #DAReason_Limit
        ADDCC   pc, pc, r0, LSL #2
        B       DynArea_Unknown
        B       DynArea_Create
        B       DynArea_Remove
        B       DynArea_GetInfo
        B       DynArea_Enumerate
        B       DynArea_Renumber
911 912
 [ ShrinkableDAs
        B       DynArea_ReturnFree
913 914
 |
        B       DynArea_Unknown
Neil Turton's avatar
Neil Turton committed
915
 ]
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
 [ DynArea_QuickHandles
        B       DynArea_GetChangeInfo
        B       DynArea_EnumerateInfo
        B       DynArea_SetClamps
 |
        B       DynArea_Unknown
        B       DynArea_Unknown
        B       DynArea_Unknown
 ]
 [ DA_Batman
        B       DynArea_SparseClaim
        B       DynArea_SparseRelease
 |
        B       DynArea_Unknown
        B       DynArea_Unknown
 ]
932 933 934 935 936 937 938 939 940 941
        B       DynArea_Unknown ; 11
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; |--Reserved for ROL
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; |
        B       DynArea_Unknown ; 19
        B       DynArea_Locate
942 943 944 945 946
        B       DynArea_PMP_PhysOp
        B       DynArea_PMP_LogOp
        B       DynArea_PMP_Resize
        B       DynArea_PMP_GetInfo
        B       DynArea_PMP_GetPages
947

948
;
Neil Turton's avatar
Neil Turton committed
949
; unknown OS_DynamicArea reason code
950
;
Neil Turton's avatar
Neil Turton committed
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
DynArea_Unknown
        ADRL    r0, ErrorBlock_HeapBadReason
DynArea_TranslateAndReturnError
      [ International
        Push    lr
        BL      TranslateError
        Pull    lr
      ]
DynArea_ReturnError
        SETV
        MOV     pc, lr

;**************************************************************************
;
;       DynArea_Create - Create a dynamic area
;
;       Internal routine called by DynamicAreaSWI and by reset code
;
; in:   r0 = reason code (0)
;       r1 = new area number, or -1 => RISC OS allocates number
;       r2 = initial size of area (in bytes)
;       r3 = base logical address of area, or -1 => RISC OS allocates address space
;       r4 = area flags
;               bits 0..3 = access privileges
;               bit  4 = 1 => not bufferable
;               bit  5 = 1 => not cacheable
;               bit  6 = 0 => area is singly mapped
;                      = 1 => area is doubly mapped
;               bit  7 = 1 => area is not user draggable in TaskManager window
980 981 982 983 984
;               bit  8 = 1 => area may require specific physical pages
;               bit  9 = 1 => area is shrinkable (only implemented if ShrinkableDAs)
;               bit 10 = 1 => area may be sparsely mapped (only implemented if DA_Batman)
;               bit 11 = 1 => area is bound to client application (allows areas to be overlayed in address space)
;                             not implemented yet, but declared in public API for Ursula
985 986
;               bits 12..14 => cache policy (if bits 4 or 5 set)
;               bit 15 = 1 => area requires DMA capable pages (is bit 12 in ROL's OS!)
987 988 989
;               bits 16-19 used by ROL
;               bit 20 = 1 => area is backed by physical memory pool
;               other bits reserved for future expansion + internal page flags (should be 0)
Neil Turton's avatar
Neil Turton committed
990
;
991
;       r5 = maximum size of logical area, or -1 for total RAM size
Neil Turton's avatar
Neil Turton committed
992 993 994
;       r6 -> area handler routine
;       r7 = workspace pointer for area handler (-1 => use base address)
;       r8 -> area description string (null terminated) (gets copied)
995
;       r9 = initial physical area size limit, in pages (physical memory pools), otherwise ignored
Neil Turton's avatar
Neil Turton committed
996 997 998 999 1000 1001 1002 1003
;
; out:  r1 = given or allocated area number
;       r3 = given or allocated base address of area
;       r5 = given or allocated maximum size
;       r0, r2, r4, r6-r9 preserved
;       r10-r12 may be corrupted
;

1004
DynArea_Create Entry "r2,r6-r8"
Neil Turton's avatar
Neil Turton committed
1005 1006 1007
        CMP     r1, #-1         ; do we have to allocate a new area number
        BEQ     %FT10

1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
  [ DynArea_QuickHandles
        CMP     r1, #DynArea_NewAreas
        BLO     %FT06
        CMP     r1, #DynArea_NewAreas+DynArea_NumQHandles
        BLO     %FT08           ; can't choose your own quick handle
  ]

06
  [ DynArea_QuickHandles
        BL      QCheckAreaNumber ; see if area number is unique
  |
Neil Turton's avatar
Neil Turton committed
1019
        BL      CheckAreaNumber ; see if area number is unique
1020
  ]
Neil Turton's avatar
Neil Turton committed
1021 1022
        BCC     %FT20           ; didn't find it, so OK

1023
08
Neil Turton's avatar
Neil Turton committed
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
        ADR     r0, ErrorBlock_AreaAlreadyExists
DynArea_ErrorTranslateAndExit
        PullEnv
        B       DynArea_TranslateAndReturnError

        MakeErrorBlock  AreaAlreadyExists
        MakeErrorBlock  AreaNotOnPageBdy
        MakeErrorBlock  OverlappingAreas
        MakeErrorBlock  CantAllocateArea
        MakeErrorBlock  CantAllocateLevel2
        MakeErrorBlock  UnknownAreaHandler
1035 1036
        MakeErrorBlock  BadDynamicAreaOptions
        MakeErrorBlock  BadPageNumber
Neil Turton's avatar
Neil Turton committed
1037 1038 1039

; we have to allocate an area number for him

1040 1041
  [ DynArea_QuickHandles
10
Jeffrey Lee's avatar
Jeffrey Lee committed
1042
        LDR     r11, =ZeroPage
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
        LDR     r11, [r11, #DynArea_ws ]
        LDR     r1, DynArea_FreeQHandles          ;get index of next available quick handle, if any free
        CMP     r1, #0
        ADDNE   r1, r1, #DynArea_NewAreas-1       ;compute quick handle from index
        BNE     %FT20
        LDR     r1, DynArea_TreacleGuess          ;last non-quick number allocated
12
        ADD     r1, r1, #1                        ; increment for next guess (collisions should be *very* rare)
        CMP     r1, #DynArea_NewAreas+DynArea_NumQHandles
        MOVLO   r1, #DynArea_NewAreas+DynArea_NumQHandles
        BL      QCheckAreaNumber
        BCS     %BT12                             ; and try again
  |
Neil Turton's avatar
Neil Turton committed
1056 1057 1058 1059 1060 1061
10
        MOV     r1, #DynArea_NewAreas
12
        BL      CheckAreaNumber
        ADDCS   r1, r1, #1      ; that area number already exists, so increment
        BCS     %BT12           ; and try again
1062 1063
  ]

Neil Turton's avatar
Neil Turton committed
1064 1065
20

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
; Check PMP settings
; If PMP is requested:
; * Must require specific pages
; * Mustn't be sparse
; * Mustn't be doubly mapped
; * Mustn't be requesting DMA auto-alloc
; * Must be zero initial size
; * Must have handler code
; Some of these restrictions may be lifted in future (e.g. if not requesting specific pages, kernel could implement OS_ChangeDynamicArea?)
        TST     r4, #DynAreaFlags_PMP
        BEQ     %FT21
        LDR     r11, =DynAreaFlags_DoublyMapped+DynAreaFlags_NeedsSpecificPages+DynAreaFlags_SparseMap+DynAreaFlags_NeedsDMA
        AND     r11, r4, r11
        TEQ     r11, #DynAreaFlags_NeedsSpecificPages
        TEQEQ   r2, #0
        ADRNE   r0, ErrorBlock_BadDynamicAreaOptions
        BNE     DynArea_ErrorTranslateAndExit
        TEQ     r6, #0
        ADREQ   r0, ErrorBlock_BadDynamicAreaOptions
        BEQ     DynArea_ErrorTranslateAndExit
21

Neil Turton's avatar
Neil Turton committed
1088 1089
; now validate maximum size of area

1090 1091 1092 1093
  [ DynArea_QuickHandles
    ;
    ; apply clamps on max size, as set by last call to OS_DynamicArea 8
    ;
Jeffrey Lee's avatar
Jeffrey Lee committed
1094
        LDR     r11, =ZeroPage
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
        LDR     r11, [r11, #DynArea_ws]
    [ DA_Batman
        TST     r4, #DynAreaFlags_SparseMap
        BEQ     DAC_notsparse
        LDR     r10, DynArea_OD8Clamp3   ; clamp for sparse dynamic area
        CMP     r5, r10                  ; if requested max size is > relevant clamp
        MOVHI   r5, r10                  ; then clamp it!
        LDR     r10, [sp]                ; requested initial size, from stack
        CMP     r5, r10
        MOVLO   r5, r10                  ; we must try to honour initial size (allowed to break clamp)
Jeffrey Lee's avatar
Jeffrey Lee committed
1105
        LDR     r10, =ZeroPage
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
        LDR     r11, [r10, #Page_Size]
        B       DAC_roundup
DAC_notsparse
    ]
        CMP     r5, #-1
        LDREQ   r10, DynArea_OD8Clamp1   ; clamp for max size requested of -1
        LDRNE   r10, DynArea_OD8Clamp2   ; clamp for max size requested of some specific value
        CMP     r5, r10                  ; if requested max size is > relevant clamp
        MOVHI   r5, r10                  ; then clamp it!
        LDR     r10, [sp]                ; requested initial size, from stack
        CMP     r5, r10
        MOVLO   r5, r10                  ; we must try to honour initial size (allowed to break clamp)
  ]

Jeffrey Lee's avatar
Jeffrey Lee committed
1120
        LDR     r10, =ZeroPage
Neil Turton's avatar
Neil Turton committed
1121 1122 1123 1124 1125
        LDR     r11, [r10, #Page_Size]
        LDR     r10, [r10, #RAMLIMIT]   ; get total RAM size
        CMP     r5, r10                 ; if requested maximum size is > total
        MOVHI   r5, r10                 ; then set max to total (NB. -1 passed in always yields HI)

1126
DAC_roundup
Neil Turton's avatar
Neil Turton committed
1127 1128 1129 1130 1131
        SUB     r10, r11, #1            ; also round up to a page multiple
        ADD     r5, r5, r10
        BIC     r5, r5, r10

; now see if we have to allocate a logical address space
1132 1133 1134
        TEQ     r5, #0                  ; If no logical size (i.e. purely physical PMP)
        MOVEQ   r3, #0                  ; Then set base addr to 0
        BEQ     %FT41                   ; And skip straight to claiming the DANode
Neil Turton's avatar
Neil Turton committed
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157

        CMP     r3, #-1                 ; if we are to allocate the address space
        BEQ     %FT30                   ; then go do it

; otherwise we must check that the address does not clash with anything else

        TST     r3, r10                         ; does it start on a page boundary
        ADRNE   r0, ErrorBlock_AreaNotOnPageBdy ; if not then error
        BNE     DynArea_ErrorTranslateAndExit

        BL      CheckForOverlappingAreas        ; in: r3 = address, r4 = flags, r5 = size; out: if error, r0->error, V=1
        BVC     %FT40
25
        PullEnv
        B       DynArea_ReturnError

30
        BL      AllocateAreaAddress             ; in: r4 = flags, r5 = size of area needed; out: r3, or V=1, r0->error
        BVS     %BT25
40
        BL      AllocateBackingLevel2           ; in: r3 = address, r4 = flags, r5 = size; out: VS if error
        BVS     %BT25

1158
41
Neil Turton's avatar
Neil Turton committed
1159
        Push    "r0,r1,r3"
1160 1161 1162 1163 1164 1165
  [ DynArea_QuickHandles
    ;we save work and reduce stress on system heap by claiming only one block, consisting of node followed by
    ;string space (always maximum length, but typically not overly wasteful compared to 2nd block overhead)
    ;
        MOV     r3, #DANode_NodeSize + DynArea_MaxNameLength + 1
  |
Neil Turton's avatar
Neil Turton committed
1166
        MOV     r3, #DANode_NodeSize
1167
  ]
Neil Turton's avatar
Neil Turton committed
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
        BL      ClaimSysHeapNode                ; out: r2 -> node
        STRVS   r0, [sp]
        Pull    "r0,r1,r3"
        BVS     %BT25                           ; failed to claim node

; now store data in node (could probably use STM if we shuffled things around)

        CMP     r7, #-1                         ; if workspace ptr = -1
        MOVEQ   r7, r3                          ; then use base address

        STR     r1, [r2, #DANode_Number]
        STR     r3, [r2, #DANode_Base]
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
  [ DA_Batman
        ;disallow some awkward flag options if SparseMap set (no error), and temporarily create as not sparse
        ;also disallow a DA handler
        TST     r4, #DynAreaFlags_SparseMap
        STREQ   r4, [r2, #DANode_Flags]
        BICNE   r7, r4, #DynAreaFlags_DoublyMapped + DynAreaFlags_NeedsSpecificPages + DynAreaFlags_Shrinkable + DynAreaFlags_SparseMap
        ORRNE   r7, r7, #DynAreaFlags_NotUserDraggable
        STRNE   r7, [r2, #DANode_Flags]
        MOVNE   r6, #0
        MOVNE   r7, #0
  |
Neil Turton's avatar
Neil Turton committed
1191
        STR     r4, [r2, #DANode_Flags]
1192
  ]
Neil Turton's avatar
Neil Turton committed
1193 1194 1195 1196 1197
        STR     r5, [r2, #DANode_MaxSize]
        STR     r6, [r2, #DANode_Handler]
        STR     r7, [r2, #DANode_Workspace]
        MOV     r7, #0                          ; initial size is zero
        STR     r7, [r2, #DANode_Size]          ; before we grow it
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
        TST     r4, #DynAreaFlags_PMP
        STR     r7, [r2, #DANode_PMP]
        STREQ   r7, [r2, #DANode_PMPMaxSize]
        STR     r7, [r2, #DANode_PMPSize]
        BEQ     %FT44
        STR     r3, [r2, #DANode_SparseHWM]
        TEQ     r9, #0
        STR     r9, [r2, #DANode_PMPMaxSize]
        BEQ     %FT44
        ; Allocate and initialise PMP for this DA
        Push    "r0-r3"
        LDR     r0, =ZeroPage
        LDR     r0, [r0, #MaxCamEntry]
        CMP     r9, r0
        ADDHI   r9, r0, #1
        MOV     r3, r9, LSL #2
        BL      ClaimSysHeapNode
        BVS     %FT43
        MOV     r10, r2
        MOV     r0, #-1
42
        SUBS    r3, r3, #4
        STR     r0, [r2], #4
        BNE     %BT42
        Pull    "r0-r3"
        STR     r10, [r2, #DANode_PMP]
        B       %FT44
43
        STR     r0, [sp]
        LDR     r2, [sp, #8]
        BL      FreeSysHeapNode
        Pull    "r0-r3"
        SETV
        B       %BT25
44
Neil Turton's avatar
Neil Turton committed
1233

1234 1235
  [ HAL
        ; update lower limit on IO space growth, if this DA exceeds previous limit
Jeffrey Lee's avatar
Jeffrey Lee committed
1236 1237 1238
      [ ZeroPage <> 0
        LDR     r7, =ZeroPage
      ]
1239 1240 1241 1242 1243 1244
        LDR     r6, [r7, #IOAllocLimit]
        ADD     lr, r3, r5
        CMP     lr, r6
        STRHI   lr, [r7, #IOAllocLimit]
  ]

Neil Turton's avatar
Neil Turton committed
1245 1246
; now make copy of string - first find out length of string

1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
  [ DynArea_QuickHandles

        ADD     r7, r2, #DANode_NodeSize
        STR     r7, [r2, #DANode_Title]
        Push    "r0"
        MOV     r0, #DynArea_MaxNameLength
        TEQ     r8, #0
    [ DynArea_NullNamePtrMeansHexString
        ASSERT  DynArea_MaxNameLength > 8
        BNE     %FT45
        Push    "r1, r2"
        MOV     r0, r1                          ;string is 8-digit hex of DA number
        MOV     r1, r7
        MOV     r2, #DynArea_MaxNameLength+1
        SWI     XOS_ConvertHex8
        Pull    "r1, r2"
        B       %FT55
    |
        BEQ     %FT50                           ;assume NULL ptr to mean no DA name
    ]
45
        LDRB    r6, [r8], #1
        STRB    r6, [r7], #1
        SUB     r0, r0, #1
        TEQ     r6, #0
        TEQNE   r0, #0
        BNE     %BT45
50
        MOV     r0, #0
        STRB    r0, [r7], #1
55
        Pull    "r0"

  |

Neil Turton's avatar
Neil Turton committed
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
        MOV     r7, r8
45
        LDRB    r6, [r7], #1
        TEQ     r6, #0
        BNE     %BT45

        Push    "r0-r3"
        SUB     r3, r7, r8                      ; r3 = length inc. term.
        BL      ClaimSysHeapNode
        STRVS   r0, [sp]
        MOV     r7, r2
        Pull    "r0-r3"
        BVS     StringNodeClaimFailed

        STR     r7, [r2, #DANode_Title]
50
        LDRB    r6, [r8], #1                    ; copy string into claimed block
        STRB    r6, [r7], #1
        TEQ     r6, #0
        BNE     %BT50

1303 1304
 ] ;DynArea_QuickHandles

Neil Turton's avatar
Neil Turton committed
1305 1306
; now put node on list - list is sorted in ascending base address order

Jeffrey Lee's avatar
Jeffrey Lee committed
1307
        LDR     r8, =ZeroPage+DAList
Neil Turton's avatar
Neil Turton committed
1308 1309 1310
        LDR     r6, [r2, #DANode_Base]
60
        MOV     r7, r8
1311
        ASSERT  DANode_Link = 0                 ; For picking up pointer to first real node
Neil Turton's avatar
Neil Turton committed
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
        LDR     r8, [r7, #DANode_Link]          ; get next node
        TEQ     r8, #0                          ; if no more
        BEQ     %FT70                           ; then put it on here
        LDR     lr, [r8, #DANode_Base]
        CMP     lr, r6                          ; if this one is before ours
        BCC     %BT60                           ; then loop

70
        STR     r8, [r2, #DANode_Link]
        STR     r2, [r7, #DANode_Link]

1323
  [ DynArea_QuickHandles
Jeffrey Lee's avatar
Jeffrey Lee committed
1324
        LDR     r11, =ZeroPage
1325
        LDR     r11, [r11, #DynArea_ws]
1326
        BL      AddDAToAddrLookupTable
1327 1328 1329 1330 1331 1332 1333 1334 1335
        ;so XOS_ChangeDynamicArea can pick up the node we are still creating
        STR     r1, DynArea_CreatingHandle
        STR     r2, DynArea_CreatingPtr
        ;so initial grow won't leave resize signature
        LDR     lr, DynArea_OD6Signature
        ORR     lr, lr, #&80000000
        STR     lr, DynArea_OD6Signature
  ]