ARM600 21.9 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.
;
; > ARM600

Jeffrey Lee's avatar
Jeffrey Lee committed
17 18 19 20
        ; Convert given page flags to the equivalent temp uncacheable L2PT flags
        ; n.b. temp not used here but included for VMSAv6 compatibility
        MACRO
        GetTempUncache $out, $pageflags, $pcbtrans, $temp
Jeffrey Lee's avatar
Jeffrey Lee committed
21 22
        ASSERT  $out <> $pageflags ; For consistency with VMSAv6 version
        ASSERT  $out <> $pcbtrans
Jeffrey Lee's avatar
Jeffrey Lee committed
23
      [ "$temp" <> ""
Jeffrey Lee's avatar
Jeffrey Lee committed
24 25
        ASSERT  $out <> $temp      ; For consistency with VMSAv6 version
        ASSERT  $temp <> $pcbtrans ; For consistency with VMSAv6 version
Jeffrey Lee's avatar
Jeffrey Lee committed
26
      ]
Jeffrey Lee's avatar
Jeffrey Lee committed
27 28 29 30 31 32 33 34 35
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
        AND     $out, $pageflags, #DynAreaFlags_NotCacheable + DynAreaFlags_NotBufferable
        ORR     $out, $out, #DynAreaFlags_NotCacheable      ; treat as temp uncache
        LDRB    $out, [$pcbtrans, $out, LSR #4]             ; convert to X, C and B bits for this CPU
        MEND

TempUncache_L2PTMask * L2_X+L2_C+L2_B
Neil Turton's avatar
Neil Turton committed
36 37 38

; MMU interface file - ARM600 version

39 40
        KEEP

Neil Turton's avatar
Neil Turton committed
41 42 43 44
; **************** CAM manipulation utility routines ***********************************

; **************************************************************************************
;
45
;       BangCamUpdate - Update CAM, MMU for page move, coping with page currently mapped in
Neil Turton's avatar
Neil Turton committed
46
;
47 48
; mjs Oct 2000
; reworked to use generic ARM ops (vectored to appropriate routines during boot)
Neil Turton's avatar
Neil Turton committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
;
; First look in the CamEntries table to find the logical address L this physical page is
; currently allocated to. Then check in the Level 2 page tables to see if page L is currently
; at page R2. If it is, then map page L to be inaccessible, otherwise leave page L alone.
; Then map logical page R3 to physical page R2.
;
; in:   r2 = physical page number
;       r3 = logical address (2nd copy if 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
;
; out:  r0, r1, r4, r6 corrupted
;       r2, r3, r5, r7-r12 preserved
;

BangCamUpdate ROUT
        TST     r11, #DynAreaFlags_DoublyMapped ; if moving page to doubly mapped area
        SUBNE   r3, r3, r9                      ; then CAM soft copy holds ptr to 1st copy

Jeffrey Lee's avatar
Jeffrey Lee committed
68
        LDR     r1, =ZeroPage
Neil Turton's avatar
Neil Turton committed
69
        LDR     r1, [r1, #CamEntriesPointer]
70 71 72
        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
73
        LDMIA   r1, {r0, r6}                    ; r0 = current logaddress, r6 = current PPL
74
        Push    "r0, r6"                        ; save old logical address, PPL
75
        BIC     r4, r11, #PageFlags_Unsafe
76 77 78
        BIC     r4, r4, #StickyPageFlags
        AND     r6, r6, #StickyPageFlags
        ORR     r4, r4, r6
79
        STMIA   r1, {r3, r4}                    ; store new address, PPL
80

Jeffrey Lee's avatar
Jeffrey Lee committed
81
        LDR     r1, =ZeroPage+PhysRamTable      ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
82 83 84 85 86 87 88 89
        MOV     r6, r2                          ; make copy of r2 (since that must be preserved)
10
        LDMIA   r1!, {r0, r4}                   ; load next address, size
        SUBS    r6, r6, r4, LSR #12             ; subtract off that many pages
        BCS     %BT10                           ; if more than that, go onto next bank

        ADD     r6, r6, r4, LSR #12             ; put back the ones which were too many
        ADD     r0, r0, r6, LSL #12             ; move on address by the number of pages left
Robert Sprowson's avatar
Robert Sprowson committed
90
        LDR     r6, [sp]                        ; reload old logical address
Neil Turton's avatar
Neil Turton committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

; now we have r6 = old logical address, r2 = physical page number, r0 = physical address

        TEQ     r6, r3                          ; TMD 19-Jan-94: if old logaddr = new logaddr, then
        BEQ     %FT20                           ; don't remove page from where it is, to avoid window
                                                ; where page is nowhere.
        LDR     r1, =L2PT
        ADD     r6, r1, r6, LSR #10             ; r6 -> L2PT entry for old log.addr
        MOV     r4, r6, LSR #12                 ; r4 = word offset into L2 for address r6
        LDR     r4, [r1, r4, LSL #2]            ; r4 = L2PT entry for L2PT entry for old log.addr
        TST     r4, #3                          ; if page not there
        BEQ     %FT20                           ; then no point in trying to remove it

        LDR     r4, [r6]                        ; r4 = L2PT entry for old log.addr
        MOV     r4, r4, LSR #12                 ; r4 = physical address for old log.addr
        TEQ     r4, r0, LSR #12                 ; if equal to physical address of page being moved
        BNE     %FT20                           ; if not there, then just put in new page

109
        AND     r4, r11, #PageFlags_Unsafe
Neil Turton's avatar
Neil Turton committed
110 111 112
        Push    "r0, r3, r11, r14"              ; save phys.addr, new log.addr, new PPL, lr
        ADD     r3, sp, #4*4
        LDMIA   r3, {r3, r11}                   ; reload old logical address, old PPL
113 114 115
        LDR     r0, =DuffEntry                  ; Nothing to do if wasn't mapped in
        ORR     r11, r11, r4
        TEQ     r3, r0
Neil Turton's avatar
Neil Turton committed
116
        MOV     r0, #0                          ; cause translation fault
117
        BLNE    BangL2PT                        ; map page out
Neil Turton's avatar
Neil Turton committed
118 119 120 121 122 123 124
        Pull    "r0, r3, r11, r14"
20
        ADD     sp, sp, #8                      ; junk old logical address, PPL
        B       BangCamAltEntry                 ; and branch into BangCam code

; **************************************************************************************
;
125
;       BangCam - Update CAM, MMU for page move, assuming page currently mapped out
Neil Turton's avatar
Neil Turton committed
126 127
;
; This routine maps a physical page to a given logical address
128
; It is assumed that the physical page is currently not mapped anywhere else
Neil Turton's avatar
Neil Turton committed
129 130 131 132 133 134 135 136 137
;
; in:   r2 = physical page number
;       r3 = logical address (2nd copy if doubly mapped)
;       r9 = offset from 1st to 2nd copy of doubly mapped area (either source or dest, but not both)
;       r11 = PPL
;
; out:  r0, r1, r4, r6 corrupted
;       r2, r3, r5, r7-r12 preserved
;
138
; NB The physical page number MUST be in range.
Neil Turton's avatar
Neil Turton committed
139 140 141 142 143

BangCam ROUT
        TST     r11, #DynAreaFlags_DoublyMapped ; if area doubly mapped
        SUBNE   r3, r3, r9              ; then move ptr to 1st copy

Jeffrey Lee's avatar
Jeffrey Lee committed
144
        LDR     r1, =ZeroPage+PhysRamTable ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
145 146 147 148 149 150 151 152 153
        MOV     r6, r2                  ; make copy of r2 (since that must be preserved)
10
        LDMIA   r1!, {r0, r4}           ; load next address, size
        SUBS    r6, r6, r4, LSR #12     ; subtract off that many pages
        BCS     %BT10                   ; if more than that, go onto next bank

        ADD     r6, r6, r4, LSR #12     ; put back the ones which were too many
        ADD     r0, r0, r6, LSL #12     ; move on address by the number of pages left
BangCamAltEntry
154 155 156
        LDR     r4, =DuffEntry          ; check for requests to map a page to nowhere
        TEQ     r4, r3                  ; don't actually map anything to nowhere
        MOVEQ   pc, lr
157
        GetPTE  r0, 4K, r0, r11
Neil Turton's avatar
Neil Turton committed
158 159 160

        LDR     r1, =L2PT               ; point to level 2 page tables

161 162
        ;fall through to BangL2PT

Neil Turton's avatar
Neil Turton committed
163 164 165 166 167 168 169
;internal entry point for updating L2PT entry
;
; entry: r0 = new L2PT value, r1 -> L2PT, r3 = logical address (4k aligned), r11 = PPL
;
; exit: r0,r1,r4,r6 corrupted
;
BangL2PT                                        ; internal entry point used only by BangCamUpdate
170 171 172
        Push    "lr"
        MOV     r6, r0

173
        TST     r11, #PageFlags_Unsafe
174
        BNE     BangL2PT_unsafe
Neil Turton's avatar
Neil Turton committed
175

Jeffrey Lee's avatar
Jeffrey Lee committed
176 177 178 179 180 181 182 183
        ;In order to safely map out a cacheable page and remove it from the
        ;cache, we need to perform the following process:
        ;* Make the page uncacheable
        ;* Flush TLB
        ;* Clean+invalidate cache
        ;* Write new mapping (r6)
        ;* Flush TLB
        ;For uncacheable pages we can just do the last two steps
184 185
        ;
        TEQ     r6, #0                          ;EQ if mapping out
Kevin Bracey's avatar
Kevin Bracey committed
186
        TSTEQ   r11, #DynAreaFlags_NotCacheable ;EQ if also cacheable (overcautious for temp uncache+illegal PCB combos)
Jeffrey Lee's avatar
Jeffrey Lee committed
187
        LDR     r4, =ZeroPage
Jeffrey Lee's avatar
Jeffrey Lee committed
188 189 190 191 192 193
        BNE     %FT20
        LDR     lr, [r4, #MMU_PCBTrans]
        GetTempUncache r0, r11, lr
        LDR     lr, [r1, r3, LSR #10]           ;get current L2PT entry
        BIC     lr, lr, #TempUncache_L2PTMask   ;remove current attributes
        ORR     lr, lr, r0
194 195 196 197 198
        STR     lr, [r1, r3, LSR #10]!          ;Make uncacheable
        TST     r11, #DynAreaFlags_DoublyMapped
        BEQ     %FT19
        STR     lr, [r1, r9, LSR #10]           ;Update 2nd mapping too if required
        ADD     r0, r3, r9
199
        ARMop   MMU_ChangingEntry,,, r4
200
19
Jeffrey Lee's avatar
Jeffrey Lee committed
201
        MOV     r0, r3
202
        ARMop   MMU_ChangingEntry,,, r4
Jeffrey Lee's avatar
Jeffrey Lee committed
203
        LDR     r1, =L2PT
Neil Turton's avatar
Neil Turton committed
204

205 206 207 208 209 210 211 212
20      STR     r6, [r1, r3, LSR #10]!          ;update L2PT entry
        TST     r11, #DynAreaFlags_DoublyMapped
        BEQ     %FT21
        STR     r6, [r1, r9, LSR #10]           ;Update 2nd mapping
        MOV     r0, r3
        ARMop   MMU_ChangingUncachedEntry,,, r4 ; TLB flush for 1st mapping
        ADD     r3, r3, r9                      ;restore r3 back to 2nd copy
21
Jeffrey Lee's avatar
Jeffrey Lee committed
213 214 215
        Pull    "lr"
        MOV     r0, r3
        ARMop   MMU_ChangingUncachedEntry,,tailcall,r4
Neil Turton's avatar
Neil Turton committed
216

217 218
BangL2PT_unsafe
        STR     r6, [r1, r3, LSR #10]!          ; update level 2 page table (and update pointer so we can use bank-to-bank offset
Neil Turton's avatar
Neil Turton committed
219
        TST     r11, #DynAreaFlags_DoublyMapped ; if area doubly mapped
220 221 222
        STRNE   r6, [r1, r9, LSR #10]           ; then store entry for 2nd copy as well
        ADDNE   r3, r3, r9                      ; and point logical address back at 2nd copy
        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
223

224 225 226 227 228 229
 [ ARM6support
PPLTransARM6
        &       (AP_Full * L2_APMult) + L2_SmallPage      ; R any W any
        &       (AP_Read * L2_APMult) + L2_SmallPage      ; R any W sup
        &       (AP_None * L2_APMult) + L2_SmallPage      ; R sup W sup
        &       (AP_Read * L2_APMult) + L2_SmallPage      ; R any W sup
Neil Turton's avatar
Neil Turton committed
230

231 232 233 234 235 236 237 238
PPLAccessARM6        ; EL1EL0
                     ; RWXRWX
        GenPPLAccess 2_111111
        GenPPLAccess 2_111101
        GenPPLAccess 2_111000
        GenPPLAccess 2_111101
        DCD     -1
 ]
239

Neil Turton's avatar
Neil Turton committed
240 241 242 243
PPLTrans
        &       (AP_Full * L2_APMult) + L2_SmallPage      ; R any W any
        &       (AP_Read * L2_APMult) + L2_SmallPage      ; R any W sup
        &       (AP_None * L2_APMult) + L2_SmallPage      ; R sup W sup
244
        &       (AP_ROM  * L2_APMult) + L2_SmallPage      ; R any W none
Neil Turton's avatar
Neil Turton committed
245

Kevin Bracey's avatar
Kevin Bracey committed
246 247 248 249 250 251
PPLTransX
        &       (AP_Full * L2X_APMult) + L2_ExtPage       ; R any W any
        &       (AP_Read * L2X_APMult) + L2_ExtPage       ; R any W sup
        &       (AP_None * L2X_APMult) + L2_ExtPage       ; R sup W sup
        &       (AP_ROM  * L2X_APMult) + L2_ExtPage       ; R any W none

252 253 254 255 256 257 258
PPLAccess            ; EL1EL0
                     ; RWXRWX
        GenPPLAccess 2_111111
        GenPPLAccess 2_111101
        GenPPLAccess 2_111000
        GenPPLAccess 2_101101
        DCD     -1
Neil Turton's avatar
Neil Turton committed
259 260 261 262 263

PageShifts
        =       12, 13, 0, 14           ; 1 2 3 4
        =       0,  0,  0, 15           ; 5 6 7 8

Jeffrey Lee's avatar
Jeffrey Lee committed
264
        LTORG
Neil Turton's avatar
Neil Turton committed
265 266 267

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
Jeffrey Lee's avatar
Jeffrey Lee committed
268
; "ARM600"-specific OS_MMUControl code
Neil Turton's avatar
Neil Turton committed
269
;
Jeffrey Lee's avatar
Jeffrey Lee committed
270

Neil Turton's avatar
Neil Turton committed
271
; in:   r0 = 0 (reason code 0, for modify control register)
Neil Turton's avatar
Neil Turton committed
272 273 274 275 276 277 278
;       r1 = EOR mask
;       r2 = AND mask
;
;       new control = ((old control AND r2) EOR r1)
;
; out:  r1 = old value
;       r2 = new value
Neil Turton's avatar
Neil Turton committed
279
MMUControl_ModifyControl ROUT
280
        Push    "r0,r3,r4,r5"
Neil Turton's avatar
Neil Turton committed
281 282 283
        CMP     r1,#0
        CMPEQ   r2,#&FFFFFFFF
        BEQ     MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
284
        LDR     r3,=ZeroPage
285 286 287 288
        LDRB    r5,[r3, #ProcessorArch]
        PHPSEI  r4                      ; disable IRQs while we modify soft copy (and possibly switch caches off/on)

        CMP     r5,#ARMv4
289
        LDRLO   lr, [r3, #MMUControlSoftCopy]
290
        ARM_read_control lr,HS          ; if ARMv4 or later, we can read control reg. - trust this more than soft copy
Neil Turton's avatar
Neil Turton committed
291 292 293 294 295
        AND     r2, r2, lr
        EOR     r2, r2, r1
        MOV     r1, lr
        STR     r2, [r3, #MMUControlSoftCopy]
        BIC     lr, r2, r1              ; lr = bits going from 0->1
Neil Turton's avatar
Neil Turton committed
296
        TST     lr, #MMUC_C             ; if cache turning on then flush cache before we do it
297 298 299 300 301 302 303 304
        BEQ     %FT05

        ARMop   Cache_InvalidateAll,,,r3 ; D-cache turning on, I-cache invalidate is either necessary (both turning on) or a safe side-effect
        B       %FT10

05
        TST     lr, #MMUC_I
        ARMop   IMB_Full,NE,,r3         ; I-cache turning on, Cache_InvalidateAll could be unsafe
305

Neil Turton's avatar
Neil Turton committed
306
10
307
        BIC     lr, r1, r2              ; lr = bits going from 1->0
308 309
        TST     lr, #MMUC_C             ; if cache turning off then clean data cache first
        BEQ     %FT15
Jeffrey Lee's avatar
Jeffrey Lee committed
310
        ARMop   Cache_CleanAll,,,r3
Neil Turton's avatar
Neil Turton committed
311 312 313 314
15
        ARM_write_control r2
        BIC     lr, r1, r2              ; lr = bits going from 1->0
        TST     lr, #MMUC_C             ; if cache turning off then flush cache afterwards
315 316 317 318 319 320
        BEQ     %FT17
        LDR     r3,=ZeroPage
        ARMop   Cache_InvalidateAll,,,r3 ; D-cache turned off, can safely invalidate I+D
        B       %FT20
17
        TST     lr, #MMUC_I
Neil Turton's avatar
Neil Turton committed
321
        BEQ     %FT20
322 323
        LDR     r3,=ZeroPage
        ARMop   IMB_Full,,,r3           ; Only I-cache which turned off, clean D-cache & invalidate I-cache
Neil Turton's avatar
Neil Turton committed
324
20
Kevin Bracey's avatar
Kevin Bracey committed
325
        PLP     r4                      ; restore IRQ state
326
        Pull    "r0,r3,r4,r5,pc"
Neil Turton's avatar
Neil Turton committed
327 328

MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
329
        LDR     r3, =ZeroPage
330 331
        LDRB    r5, [r3, #ProcessorArch]
        CMP     r5, #ARMv4
332
        LDRLO   lr, [r3, #MMUControlSoftCopy]
333
        ARM_read_control lr,HS          ; if ARMv4 or later, we can read control reg. - trust this more than soft copy
334
        STRHS   lr, [r3, #MMUControlSoftCopy]
Neil Turton's avatar
Neil Turton committed
335 336
        MOV     r1, lr
        MOV     r2, lr
337
        Pull    "r0,r3,r4,r5,pc"
Neil Turton's avatar
Neil Turton committed
338

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 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 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
; If extended pages are supported:
; PPLTrans should contain L2X_AP + L2_ExtPage
; PCBTrans should contain L2_C+L2_B+L2_TEX (for an extended page)
; If extended pages aren't supported:
; PPLTrans should contain L2_AP + L2_SmallPage
; PCBTrans should contain L2_C+L2_B

; In:
; r0 = phys addr (aligned)
; r1 = page flags:
;      DynAreaFlags_APBits
;      DynAreaFlags_NotBufferable
;      DynAreaFlags_NotCacheable
;      DynAreaFlags_CPBits
;      PageFlags_TempUncacheableBits
; r2 -> PPLTrans
; r3 -> PCBTrans
; Out:
; r0 = PTE for 4K page ("small page" or "extended page" depending on PPLTrans)
Get4KPTE ROUT
        Entry   "r4"
        AND     lr, r1, #DynAreaFlags_APBits
        LDR     lr, [r2, lr, LSL #2]
        ; Insert AP bits, page type/size
        ORR     r0, r0, lr
        ; Insert CB+TEX bits
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
        TST     r1, #PageFlags_TempUncacheableBits
        AND     r4, r1, #DynAreaFlags_NotCacheable + DynAreaFlags_NotBufferable
        AND     lr, r1, #DynAreaFlags_CPBits
        ORRNE   r4, r4, #DynAreaFlags_NotCacheable      ; if temp uncache, set NC bit, ignore P
        ORREQ   r4, r4, lr, LSR #10-4                   ; else use NC, NB and P bits
        LDRB    r4, [r3, r4, LSR #4]                    ; convert to X, C and B bits for this CPU
        ORR     r0, r0, r4
        EXIT

; In:
; As per Get4KPTE
; Out:
; r0 = PTE for 64K page ("large page")
Get64KPTE ROUT
        Entry   "r4"
        AND     lr, r1, #DynAreaFlags_APBits
        LDR     lr, [r2, lr, LSL #2]
        ; Force to large page
        ORR     r0, r0, #L2_LargePage
        ; Insert AP bits
        AND     lr, lr, #L2X_AP ; If extended pages are supported, we need to expand L2X_AP to L2_AP
        MOV     r4, #L2_APMult/L2X_APMult
        MLA     r0, r4, lr, r0
50
        ; Insert CB+TEX bits
        ; Shared with Get1MPTE
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
        TST     r1, #PageFlags_TempUncacheableBits
        AND     r4, r1, #DynAreaFlags_NotCacheable + DynAreaFlags_NotBufferable
        AND     lr, r1, #DynAreaFlags_CPBits
        ORRNE   r4, r4, #DynAreaFlags_NotCacheable      ; if temp uncache, set NC bit, ignore P
        ORREQ   r4, r4, lr, LSR #10-4                   ; else use NC, NB and P bits
        LDRB    r4, [r3, r4, LSR #4]                    ; convert to X, C and B bits for this CPU
        ; Move TEX field up
        ORR     r4, r4, r4, LSL #L2L_TEXShift-L2_TEXShift
        BIC     r4, r4, #L2_TEX :OR: ((L2_C+L2_B) :SHL: (L2L_TEXShift-L2_TEXShift))
        ORR     r0, r0, r4
        EXIT

; In:
; As per Get4KPTE
; Out:
; r0 = PTE for 1M page ("section")
Get1MPTE
        ALTENTRY
        AND     lr, r1, #DynAreaFlags_APBits
      [ ARM6support
        ; Set U bit if cacheable and not ROM access
        ; (Because ROM access isn't supported, it'll get mapped to AP_Read.
        ;  Writes to ROM will presumably be ignored by the bus, but if we have
        ;  U set it will update the cache, effectively giving people the power
        ;  to temporarily overwrite ROM)
        CMP     lr, #2
        TSTLS   r1, #DynAreaFlags_NotCacheable
        ORREQ   r0, r0, #L1_U
      ]
        LDR     lr, [r2, lr, LSL #2]
        ; Force to section map
        ORR     r0, r0, #L1_Section
        ; Insert AP bits
        ASSERT  L1_AP = L2X_AP :SHL: 6
        AND     lr, lr, #L2X_AP
        ORR     r0, r0, lr, LSL #6
        ; Insert CB+TEX bits
        ASSERT  L1_C = L2_C
        ASSERT  L1_B = L2_B
        ASSERT  L1_TEXShift = L2L_TEXShift
        B       %BT50

; In:
; r0 = L2PT entry
; Out:
442 443
; r0,r1 = phys addr
; r2 = page flags
444
;      or -1 if fault
445
; r3 = page size (bytes)
446
DecodeL2Entry   ROUT
447 448
        ANDS    r3, r0, #3
        MOVEQ   r2, #-1
449
        MOVEQ   pc, lr
450
        Entry   "r4-r6"
451 452
        ; Get AP bits in low bits
        ASSERT  L2X_APMult = 1:SHL:4
453
        MOV     r2, r0, LSR #4
454 455 456
        ; Remap TEX+CB so that they're in the same position as an extended page entry
        ASSERT  L2_LargePage < L2_SmallPage
        ASSERT  L2_SmallPage < L2_ExtPage
457
        CMP     r3, #L2_SmallPage
458 459 460 461 462
        AND     r4, r0, #L2_C+L2_B
        ANDLT   lr, r0, #L2L_TEX
        ORRLT   r4, r4, lr, LSR #L2L_TEXShift-L2_TEXShift
        ANDGT   lr, r0, #L2_TEX
        ORRGT   r4, r4, lr
463
        ; Align phys addr to page size and set up r3
464 465 466
        MOV     r0, r0, LSR #12
        BICLT   r0, r0, #15
        MOV     r0, r0, LSL #12
467 468 469
        MOV     r1, #0
        MOVLT   r3, #65536
        MOVGE   r3, #4096
470 471 472 473 474 475
20
        ; Common code shared with DecodeL1Entry
        ; Only four PPL possibilities, so just directly decode it
        ; ARM access goes 0 => all R/O, 1 => user none, 2 => user R/O, 3  => user R/W
        ; PPL access goes 0 => user R/W, 1 => user R/O, 2 => user none, 3 => all R/0
        ; i.e. just invert the bits
476 477 478
        AND     r2, r2, #3
        LDR     r6, =ZeroPage
        EOR     r2, r2, #3
479 480
        ; Search through PCBTrans for a match on TEX+CB
        ; Funny order is used so that NCNB is preferred over other variants (since NCNB is common fallback)
481
        LDR     r6, [r6, #MMU_PCBTrans]
482 483
        MOV     lr, #3
30
484
        LDRB    r5, [r6, lr]
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
        CMP     r5, r4
        BEQ     %FT40
        TST     lr, #2_11
        SUBNE   lr, lr, #1                      ; loop goes 3,2,1,0,7,6,5,4,...,31,30,29,28
        ADDEQ   lr, lr, #7
        TEQ     lr, #35
        BNE     %BT30                           ; Give up if end of table reached
40
        ; Decode index back into page flags
        ; n.b. temp uncache is ignored (no way we can differentiate between real uncached)
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
        AND     r4, lr, #XCB_NC+XCB_NB
        AND     lr, lr, #7*XCB_P
500 501
        ORR     r2, r2, r4, LSL #4
        ORR     r2, r2, lr, LSL #10
502 503 504 505 506
        EXIT

; In:
; r0 = L1PT entry
; Out:
507 508
; r0,r1 = phys addr of section or L2PT entry
; r2 = page flags if 1MB page
509 510
;      or -1 if fault
;      or -2 if page table ptr
511
; r3 = section size (bytes) if section-mapped
512 513
DecodeL1Entry
        ALTENTRY
514
        AND     r2, r0, #3
515 516
        ASSERT  L1_Fault < L1_Page
        ASSERT  L1_Page < L1_Section
517
        CMP     r2, #L1_Page
518
        BGT     %FT50
519 520
        MOVLT   r2, #-1
        MOVEQ   r2, #-2
521 522
        MOVEQ   r0, r0, LSR #10
        MOVEQ   r0, r0, LSL #10
523
        MOVEQ   r1, #0
524 525 526 527
        EXIT
50
        ; Get AP bits in low bits
        ASSERT  L1_APMult = 1:SHL:10
528
        MOV     r2, r0, LSR #10
529 530 531 532 533 534
        ; Remap TEX+CB so that they're in the same position as an extended page entry
        ASSERT  L1_C = L2_C
        ASSERT  L1_B = L2_B
        AND     r4, r0, #L1_C+L1_B
        AND     lr, r0, #L1_TEX
        ORR     r4, r4, lr, LSR #L1_TEXShift-L2_TEXShift
535
        ; Align phys addr to page size and set up r3
536 537
        MOV     r0, r0, LSR #20
        MOV     r0, r0, LSL #20
538 539
        MOV     r1, #0
        MOV     r3, #1048576
540 541 542
        ; Jump to common code to do AP decode + PCBTrans search
        B       %BT20

543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
; In:
; r0 = phys addr (aligned)
; r1 -> ZeroPage
; Out:
; TTBR and any other related registers updated
; If MMU is currently on, it's assumed the mapping of ROM+stack will not be
; affected by this change
SetTTBR ROUT
        ARM_MMU_transbase r0
        MOV     pc, lr

 [ CacheablePageTables
; Out: R0 = desired page flags for the page tables
GetPageFlagsForCacheablePageTables ROUT
        ; For ARMv5 and below the MMU can't read from the L1 cache, so the
        ; best we can do is a write-through cache policy
        LDR     r0, =AreaFlags_PageTablesAccess :OR: (CP_CB_Writethrough :SHL: DynAreaFlags_CPShift)
        MOV     pc, lr
 ]

Neil Turton's avatar
Neil Turton committed
563
        END