Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 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 194 195 196 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 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 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 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 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 | /* * Copyright (c) 2007-2014 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include <arm/asm.h> #include <arm/proc_reg.h> #include <mach_kdp.h> #include "assym.s" .text .align 12 .align 2 .globl EXT(resume_idle_cpu) LEXT(resume_idle_cpu) // r0 set to BootArgs phys address // r1 set to cpu data phys address LOAD_ADDR(lr, arm_init_idle_cpu) b L_start_cpu_0 .globl EXT(start_cpu) LEXT(start_cpu) // r0 set to BootArgs phys address // r1 set to cpu data phys address LOAD_ADDR(lr, arm_init_cpu) b L_start_cpu_0 L_start_cpu_0: cpsid if // Disable IRQ FIQ // Turn on L1 I-Cache, Branch prediction early mcr p15, 0, r11, c7, c5, 0 // invalidate the icache isb // before moving on mrc p15, 0, r11, c1, c0, 0 // read mmu control into r11 orr r11, r11, #(SCTLR_ICACHE | SCTLR_PREDIC) // enable i-cache, b-prediction mcr p15, 0, r11, c1, c0, 0 // set mmu control dsb // ensure mmu settings are inplace isb // before moving on // Get the kernel's phys & virt addr, and size from BootArgs ldr r8, [r0, BA_PHYS_BASE] // Get the phys base in r8 ldr r9, [r0, BA_VIRT_BASE] // Get the virt base in r9 ldr r10, [r0, BA_MEM_SIZE] // Get the mem size in r10 // Set the base of the translation table into the MMU ldr r4, [r0, BA_TOP_OF_KERNEL_DATA] // Get the top of kernel data orr r5, r4, #(TTBR_SETUP & 0x00FF) // Setup PTWs memory attribute orr r5, r5, #(TTBR_SETUP & 0xFF00) // Setup PTWs memory attribute mcr p15, 0, r5, c2, c0, 0 // write kernel to translation table base 0 mcr p15, 0, r5, c2, c0, 1 // also to translation table base 1 mov r5, #TTBCR_N_SETUP // identify the split between 0 and 1 mcr p15, 0, r5, c2, c0, 2 // and set up the translation control reg ldr r2, [r1, CPU_NUMBER_GS] // Get cpu number mcr p15, 0, r2, c13, c0, 3 // Write TPIDRURO ldr sp, [r1, CPU_INTSTACK_TOP] // Get interrupt stack top sub sp, sp, SS_SIZE // Set stack pointer sub r0, r1, r8 // Convert to virtual address add r0, r0, r9 b join_start .align 2 .globl EXT(_start) LEXT(_start) // r0 has the boot-args pointer // r1 set to zero mov r1, #0 LOAD_ADDR(lr, arm_init) cpsid if // Disable IRQ FIQ // Turn on L1 I-Cache, Branch prediction early mcr p15, 0, r11, c7, c5, 0 // invalidate the icache isb // before moving on mrc p15, 0, r11, c1, c0, 0 // read mmu control into r11 orr r11, r11, #(SCTLR_ICACHE | SCTLR_PREDIC) // enable i-cache, b-prediction mcr p15, 0, r11, c1, c0, 0 // set mmu control dsb // ensure mmu settings are inplace isb // before moving on // Get the kernel's phys & virt addr, and size from boot_args. ldr r8, [r0, BA_PHYS_BASE] // Get the phys base in r8 ldr r9, [r0, BA_VIRT_BASE] // Get the virt base in r9 ldr r10, [r0, BA_MEM_SIZE] // Get the mem size in r10 #define LOAD_PHYS_ADDR(reg, label) \ LOAD_ADDR(reg, label); \ sub reg, reg, r9; \ add reg, reg, r8 // Take this opportunity to patch the targets for the exception vectors LOAD_ADDR(r4, fleh_reset) LOAD_PHYS_ADDR(r5, ExceptionVectorsTable) str r4, [r5] LOAD_ADDR(r4, fleh_undef) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_swi) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_prefabt) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_dataabt) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_addrexc) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_irq) add r5, #4 str r4, [r5] LOAD_ADDR(r4, fleh_decirq) add r5, #4 str r4, [r5] // arm_init_tramp is sensitive, so for the moment, take the opportunity to store the // virtual address locally, so that we don't run into issues retrieving it later. // This is a pretty miserable solution, but it should be enough for the moment LOAD_ADDR(r4, arm_init_tramp) adr r5, arm_init_tramp_addr str r4, [r5] #undef LOAD_PHYS_ADDR // Set the base of the translation table into the MMU ldr r4, [r0, BA_TOP_OF_KERNEL_DATA] // Get the top of kernel data orr r5, r4, #(TTBR_SETUP & 0x00FF) // Setup PTWs memory attribute orr r5, r5, #(TTBR_SETUP & 0xFF00) // Setup PTWs memory attribute mcr p15, 0, r5, c2, c0, 0 // write kernel to translation table base 0 mcr p15, 0, r5, c2, c0, 1 // also to translation table base 1 mov r5, #TTBCR_N_SETUP // identify the split between 0 and 1 mcr p15, 0, r5, c2, c0, 2 // and set up the translation control reg // Mark the entries invalid in the 4 page trampoline translation table // Mark the entries invalid in the 4 page CPU translation table // Mark the entries invalid in the one page table for the final 1MB (if used) // Mark the entries invalid in the one page table for HIGH_EXC_VECTORS mov r5, r4 // local copy of base mov r11, #ARM_TTE_TYPE_FAULT // invalid entry template mov r2, PGBYTES >> 2 // number of ttes/page add r2, r2, r2, LSL #2 // 8 ttes + 2 ptes to clear. Multiply by 5... mov r2, r2, LSL #1 // ...then multiply by 2 invalidate_tte: str r11, [r5] // store the invalid tte add r5, r5, #4 // increment tte pointer subs r2, r2, #1 // decrement count bne invalidate_tte // create default section tte template mov r6, #ARM_TTE_TYPE_BLOCK // use block mapping entries mov r7, #(ARM_TTE_BLOCK_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xFF) orr r7, r7, #(ARM_TTE_BLOCK_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xFF00) orr r7, r7, #(ARM_TTE_BLOCK_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xF0000) orr r6, r6, r7 // with default cache attrs mov r7, #ARM_TTE_BLOCK_AP(AP_RWNA) // Set kernel rw, user no access orr r7, r7, #(ARM_TTE_BLOCK_AP(AP_RWNA) & 0xFF00) orr r7, r7, #(ARM_TTE_BLOCK_AP(AP_RWNA) & 0xF0000) orr r6, r6, r7 // Set RWNA protection orr r6, r6, #ARM_TTE_BLOCK_AF // Set access protection orr r6, r6, #ARM_TTE_BLOCK_SH // Set shareability // Set up the V=P mapping for the 1 MB section around the current pc lsr r7, pc, #ARM_TT_L1_SHIFT // Extract tte index for pc addr add r5, r4, r7, LSL #2 // convert tte index to tte pointer lsl r7, r7, #ARM_TT_L1_SHIFT // Truncate pc to 1MB aligned addr orr r11, r7, r6 // make tte entry value str r11, [r5] // store tte // Set up the virtual mapping for the kernel using 1Mb direct section TTE entries mov r7, r8 // Save original phys base add r5, r4, r9, LSR #ARM_TT_L1_SHIFT-2 // convert vaddr to tte pointer mov r3, #ARM_TT_L1_SIZE // set 1MB boundary mapveqp: cmp r3, r10 // Check if we're beyond the last 1MB section bgt mapveqpL2 // If so, a coarse entry is required orr r11, r7, r6 // make tte entry value str r11, [r5], #4 // store tte and move to next add r7, r7, #ARM_TT_L1_SIZE // move to next phys addr subs r10, r10, #ARM_TT_L1_SIZE // subtract tte size bne mapveqp b doneveqp // end is 1MB aligned, and we're done mapveqpL2: // The end is not 1MB aligned, so steal a page and set up L2 entries within // Coarse entry first add r6, r4, PGBYTES * 8 // add L2 offset mov r11, r6 orr r6, #ARM_TTE_TYPE_TABLE // coarse entry str r6, [r5] // store coarse tte entry // Fill in the L2 entries mov r5, r11 // create pte template mov r2, #ARM_PTE_TYPE // default pte type orr r2, r2, #(ARM_PTE_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xff) // with default cache attrs orr r2, r2, #(ARM_PTE_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xff00) orr r2, r2, #(ARM_PTE_AP(AP_RWNA) & 0xff) // with default cache attrs orr r2, r2, #(ARM_PTE_AP(AP_RWNA) & 0xff00) orr r2, r2, #ARM_PTE_AF // Set access orr r2, r2, #ARM_PTE_SH // Set shareability storepte: orr r11, r7, r2 // make pte entry value str r11, [r5], #4 // store pte and move to next add r7, r7, PGBYTES // move to next phys addr subs r10, r10, PGBYTES // subtract pte size bne storepte doneveqp: // Insert page table page for high address exception vectors into translation table mov r5, #0xff000000 // part of virt HIGH_EXC_VECTORS (HACK!) orr r5, r5, #0x00ff0000 // rest of virt HIGH_EXC_VECTORS (HACK!) mov r5, r5, LSR #ARM_TT_L1_SHIFT // convert virt addr to index add r5, r4, r5, LSL #2 // convert to tte pointer add r6, r4, PGBYTES * 9 // get page table base (past 4 + 4 + 1 tte/pte pages) add r6, r6, #0xc00 // adjust to last 1MB section mov r7, #(ARM_TTE_TABLE_MASK & 0xFFFF) // ARM_TTE_TABLE_MASK low halfword movt r7, #(ARM_TTE_TABLE_MASK >> 16) // ARM_TTE_TABLE_MASK top halfword and r11, r6, r7 // apply mask orr r11, r11, #ARM_TTE_TYPE_TABLE // mark it as a coarse page table str r11, [r5] // store tte entry for page table // create pte template mov r2, #ARM_PTE_TYPE // pte type orr r2, r2, #(ARM_PTE_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0x00ff) // default cache attrs orr r2, r2, #(ARM_PTE_ATTRINDX(CACHE_ATTRINDX_DEFAULT) & 0xff00) orr r2, r2, #(ARM_PTE_AP(AP_RWNA) & 0x00ff) // set RWNA protection orr r2, r2, #(ARM_PTE_AP(AP_RWNA) & 0xff00) orr r2, r2, #ARM_PTE_AF // Set access orr r2, r2, #ARM_PTE_SH // Set shareability // Now initialize the page table entry for the exception vectors mov r5, #0xff000000 // part of HIGH_EXC_VECTORS orr r5, r5, #0x00ff0000 // rest of HIGH_EXC_VECTORS mov r7, #(ARM_TT_L2_INDEX_MASK & 0xFFFF) // ARM_TT_L2_INDEX_MASK low halfword movt r7, #(ARM_TT_L2_INDEX_MASK >> 16) // ARM_TT_L2_INDEX_MASK top halfword and r5, r5, r7 // mask for getting index mov r5, r5, LSR #ARM_TT_L2_SHIFT // get page table index add r5, r6, r5, LSL #2 // convert to pte pointer LOAD_ADDR(r11, ExceptionVectorsBase) // get address of vectors addr sub r11, r11, r9 // convert to physical address add r11, r11, r8 mov r7, #(ARM_PTE_PAGE_MASK & 0xFFFF) // ARM_PTE_PAGE_MASK low halfword movt r7, #(ARM_PTE_PAGE_MASK >> 16) // ARM_PTE_PAGE_MASK top halfword and r11, r11, r7 // insert masked address into pte orr r11, r11, r2 // add template bits str r11, [r5] // store pte by base and index // clean the dcache mov r11, #0 cleanflushway: cleanflushline: mcr p15, 0, r11, c7, c14, 2 // cleanflush dcache line by way/set add r11, r11, #1 << MMU_I7SET // increment set index tst r11, #1 << (MMU_NSET + MMU_I7SET) // look for overflow beq cleanflushline bic r11, r11, #1 << (MMU_NSET + MMU_I7SET) // clear set overflow adds r11, r11, #1 << MMU_I7WAY // increment way bcc cleanflushway // loop #if __ARM_L2CACHE__ // Invalidate L2 cache mov r11, #2 invall2flushway: invall2flushline: mcr p15, 0, r11, c7, c14, 2 // Invalidate dcache line by way/set add r11, r11, #1 << L2_I7SET // increment set index tst r11, #1 << (L2_NSET + L2_I7SET) // look for overflow beq invall2flushline bic r11, r11, #1 << (L2_NSET + L2_I7SET) // clear set overflow adds r11, r11, #1 << L2_I7WAY // increment way bcc invall2flushway // loop #endif mov r11, #0 mcr p15, 0, r11, c13, c0, 3 // Write TPIDRURO LOAD_ADDR(sp, intstack_top) // Get interrupt stack top sub sp, sp, SS_SIZE // Set stack pointer sub r0, r0, r8 // Convert to virtual address add r0, r0, r9 join_start: // kernel page table is setup // lr set to return handler function virtual address // r0 set to return handler argument virtual address // sp set to interrupt context stack virtual address // Cpu specific configuration #ifdef ARMA7 #if __ARMA7_SMP__ mrc p15, 0, r11, c1, c0, 1 orr r11, r11, #(1<<6) // SMP mcr p15, 0, r11, c1, c0, 1 isb #endif #endif mrs r11, cpsr // Get cpsr bic r11, #0x100 // Allow async aborts msr cpsr_x, r11 // Update cpsr mov r11, #0 mcr p15, 0, r11, c8, c7, 0 // invalidate all TLB entries mcr p15, 0, r11, c7, c5, 0 // invalidate the icache // set DACR mov r11, #(ARM_DAC_SETUP & 0xFFFF) // ARM_DAC_SETUP low halfword movt r11, #(ARM_DAC_SETUP >> 16) // ARM_DAC_SETUP top halfword mcr p15, 0, r11, c3, c0, 0 // write to dac register // Set PRRR mov r11, #(PRRR_SETUP & 0xFFFF) // PRRR_SETUP low halfword movt r11, #(PRRR_SETUP >> 16) // PRRR_SETUP top halfword mcr p15, 0, r11, c10,c2,0 // write to PRRR register // Set NMRR mov r11, #(NMRR_SETUP & 0xFFFF) // NMRR_SETUP low halfword movt r11, #(NMRR_SETUP >> 16) // NMRR_SETUP top halfword mcr p15, 0, r11, c10,c2,1 // write to NMRR register // set SCTLR mrc p15, 0, r11, c1, c0, 0 // read system control bic r11, r11, #SCTLR_ALIGN // force off alignment exceptions mov r7, #(SCTLR_AFE|SCTLR_TRE) // Access flag, TEX remap orr r7, r7, #(SCTLR_HIGHVEC | SCTLR_ICACHE | SCTLR_PREDIC) orr r7, r7, #(SCTLR_DCACHE | SCTLR_ENABLE) #if (__ARM_ENABLE_SWAP__ == 1) orr r7, r7, #SCTLR_SW // SWP/SWPB Enable #endif orr r11, r11, r7 // or in the default settings mcr p15, 0, r11, c1, c0, 0 // set mmu control dsb // ensure mmu settings are inplace isb // before moving on #if __ARM_VFP__ // Initialize the VFP coprocessors. mrc p15, 0, r2, c1, c0, 2 // read coprocessor control register mov r3, #15 // 0xF orr r2, r2, r3, LSL #20 // enable 10 and 11 mcr p15, 0, r2, c1, c0, 2 // write coprocessor control register isb #endif /* __ARM_VFP__ */ // Running virtual. Prepare to call init code cmp r1, #0 // Test if invoked from start beq join_start_1 // Branch if yes ldr r7, arm_init_tramp_addr // Load trampoline address bx r7 // Branch to virtual trampoline address // Loading the virtual address for arm_init_tramp is a rather ugly // problem. There is probably a better solution, but for the moment, // patch the address in locally so that loading it is trivial arm_init_tramp_addr: .long 0 .globl EXT(arm_init_tramp) LEXT(arm_init_tramp) mrc p15, 0, r5, c2, c0, 0 // Read to translation table base 0 add r5, r5, PGBYTES * 4 // get kernel page table base (past 4 boot tte pages) mcr p15, 0, r5, c2, c0, 0 // write kernel to translation table base 0 mcr p15, 0, r5, c2, c0, 1 // also to translation table base 1 isb mov r5, #0 mcr p15, 0, r5, c8, c7, 0 // Flush all TLB entries dsb // ensure mmu settings are inplace isb // before moving on join_start_1: #if __ARM_VFP__ // Enable VFP for the bootstrap thread context. // VFP is enabled for the arm_init path as we may // execute VFP code before we can handle an undef. fmrx r2, fpexc // get fpexc orr r2, #FPEXC_EN // set the enable bit fmxr fpexc, r2 // set fpexc mov r2, #FPSCR_DEFAULT // set default fpscr fmxr fpscr, r2 // set fpscr #endif /* __ARM_VFP__ */ mov r7, #0 // Set stack frame 0 bx lr LOAD_ADDR_GEN_DEF(arm_init) LOAD_ADDR_GEN_DEF(arm_init_cpu) LOAD_ADDR_GEN_DEF(arm_init_idle_cpu) LOAD_ADDR_GEN_DEF(arm_init_tramp) LOAD_ADDR_GEN_DEF(fleh_reset) LOAD_ADDR_GEN_DEF(ExceptionVectorsTable) LOAD_ADDR_GEN_DEF(fleh_undef) LOAD_ADDR_GEN_DEF(fleh_swi) LOAD_ADDR_GEN_DEF(fleh_prefabt) LOAD_ADDR_GEN_DEF(fleh_dataabt) LOAD_ADDR_GEN_DEF(fleh_addrexc) LOAD_ADDR_GEN_DEF(fleh_irq) LOAD_ADDR_GEN_DEF(fleh_decirq) #include "globals_asm.h" /* vim: set ts=4: */ |