1/* 2 * Copyright (c) 2007-2022 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include "assym.s" 29#include <arm64/asm.h> 30#include <arm64/proc_reg.h> 31#include <arm64/machine_machdep.h> 32#include <arm64/proc_reg.h> 33#include <pexpert/arm64/board_config.h> 34#include <mach_assert.h> 35#include <machine/asm.h> 36#include <arm64/tunables/tunables.s> 37#include <arm64/exception_asm.h> 38 39#if __ARM_KERNEL_PROTECT__ 40#include <arm/pmap.h> 41#endif /* __ARM_KERNEL_PROTECT__ */ 42 43 44 45.macro MSR_VBAR_EL1_X0 46#if defined(KERNEL_INTEGRITY_KTRR) 47 mov x1, lr 48 bl EXT(pinst_set_vbar) 49 mov lr, x1 50#else 51 msr VBAR_EL1, x0 52#endif 53.endmacro 54 55.macro MSR_TCR_EL1_X1 56#if defined(KERNEL_INTEGRITY_KTRR) 57 mov x0, x1 58 mov x1, lr 59 bl EXT(pinst_set_tcr) 60 mov lr, x1 61#else 62 msr TCR_EL1, x1 63#endif 64.endmacro 65 66.macro MSR_TTBR1_EL1_X0 67#if defined(KERNEL_INTEGRITY_KTRR) 68 mov x1, lr 69 bl EXT(pinst_set_ttbr1) 70 mov lr, x1 71#else 72 msr TTBR1_EL1, x0 73#endif 74.endmacro 75 76.macro MSR_SCTLR_EL1_X0 77#if defined(KERNEL_INTEGRITY_KTRR) 78 mov x1, lr 79 80 // This may abort, do so on SP1 81 bl EXT(pinst_spsel_1) 82 83 bl EXT(pinst_set_sctlr) 84 msr SPSel, #0 // Back to SP0 85 mov lr, x1 86#else 87 msr SCTLR_EL1, x0 88#endif /* defined(KERNEL_INTEGRITY_KTRR) */ 89.endmacro 90 91/* 92 * Checks the reset handler for global and CPU-specific reset-assist functions, 93 * then jumps to the reset handler with boot args and cpu data. This is copied 94 * to the first physical page during CPU bootstrap (see cpu.c). 95 * 96 * Variables: 97 * x19 - Reset handler data pointer 98 * x20 - Boot args pointer 99 * x21 - CPU data pointer 100 */ 101 .text 102 .align 12 103 .globl EXT(LowResetVectorBase) 104LEXT(LowResetVectorBase) 105 /* 106 * On reset, both RVBAR_EL1 and VBAR_EL1 point here. SPSel.SP is 1, 107 * so on reset the CPU will jump to offset 0x0 and on exceptions 108 * the CPU will jump to offset 0x200, 0x280, 0x300, or 0x380. 109 * In order for both the reset vector and exception vectors to 110 * coexist in the same space, the reset code is moved to the end 111 * of the exception vector area. 112 */ 113 b EXT(reset_vector) 114 115 /* EL1 SP1: These vectors trap errors during early startup on non-boot CPUs. */ 116 .align 9 117 b . 118 .align 7 119 b . 120 .align 7 121 b . 122 .align 7 123 b . 124 125 .align 7 126 .globl EXT(reset_vector) 127LEXT(reset_vector) 128 // Preserve x0 for start_first_cpu, if called 129 // Unlock the core for debugging 130 msr OSLAR_EL1, xzr 131 msr DAIFSet, #(DAIFSC_ALL) // Disable all interrupts 132 133#if !(defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR)) 134 // Set low reset vector before attempting any loads 135 adrp x0, EXT(LowExceptionVectorBase)@page 136 add x0, x0, EXT(LowExceptionVectorBase)@pageoff 137 msr VBAR_EL1, x0 138#endif 139 140 141 142 // Process reset handlers 143 adrp x19, EXT(ResetHandlerData)@page // Get address of the reset handler data 144 add x19, x19, EXT(ResetHandlerData)@pageoff 145 mrs x15, MPIDR_EL1 // Load MPIDR to get CPU number 146#if HAS_CLUSTER 147 and x0, x15, #0xFFFF // CPU number in Affinity0, cluster ID in Affinity1 148#else 149 and x0, x15, #0xFF // CPU number is in MPIDR Affinity Level 0 150#endif 151 ldr x1, [x19, CPU_DATA_ENTRIES] // Load start of data entries 152 add x3, x1, MAX_CPUS * 16 // end addr of data entries = start + (16 * MAX_CPUS) 153Lcheck_cpu_data_entry: 154 ldr x21, [x1, CPU_DATA_PADDR] // Load physical CPU data address 155 cbz x21, Lnext_cpu_data_entry 156 ldr w2, [x21, CPU_PHYS_ID] // Load ccc cpu phys id 157 cmp x0, x2 // Compare cpu data phys cpu and MPIDR_EL1 phys cpu 158 b.eq Lfound_cpu_data_entry // Branch if match 159Lnext_cpu_data_entry: 160 add x1, x1, #16 // Increment to the next cpu data entry 161 cmp x1, x3 162 b.eq Lskip_cpu_reset_handler // Not found 163 b Lcheck_cpu_data_entry // loop 164Lfound_cpu_data_entry: 165 166#ifdef APPLEEVEREST 167 /* 168 * On H15, we need to configure PIO-only tunables and to apply 169 * PIO lockdown as early as possible. 170 */ 171 SET_PIO_ONLY_REGISTERS x21, x2, x3, x4, x5, x6 172#endif /* APPLEEVEREST */ 173 174 adrp x20, EXT(const_boot_args)@page 175 add x20, x20, EXT(const_boot_args)@pageoff 176 ldr x0, [x21, CPU_RESET_HANDLER] // Call CPU reset handler 177 cbz x0, Lskip_cpu_reset_handler 178 179 // Validate that our handler is one of the two expected handlers 180 adrp x2, EXT(resume_idle_cpu)@page 181 add x2, x2, EXT(resume_idle_cpu)@pageoff 182 cmp x0, x2 183 beq 1f 184 adrp x2, EXT(start_cpu)@page 185 add x2, x2, EXT(start_cpu)@pageoff 186 cmp x0, x2 187 bne Lskip_cpu_reset_handler 1881: 189 190#if HAS_BP_RET 191 bl EXT(set_bp_ret) 192#endif 193 194#if __ARM_KERNEL_PROTECT__ && defined(KERNEL_INTEGRITY_KTRR) 195 /* 196 * Populate TPIDR_EL1 (in case the CPU takes an exception while 197 * turning on the MMU). 198 */ 199 ldr x13, [x21, CPU_ACTIVE_THREAD] 200 msr TPIDR_EL1, x13 201#endif /* __ARM_KERNEL_PROTECT__ */ 202 203 blr x0 204Lskip_cpu_reset_handler: 205 b . // Hang if the handler is NULL or returns 206 207 .align 3 208 .global EXT(LowResetVectorEnd) 209LEXT(LowResetVectorEnd) 210 .global EXT(SleepToken) 211#if WITH_CLASSIC_S2R 212LEXT(SleepToken) 213 .space (stSize_NUM),0 214#endif 215 216 .section __DATA_CONST,__const 217 .align 3 218 .globl EXT(ResetHandlerData) 219LEXT(ResetHandlerData) 220 .space (rhdSize_NUM),0 // (filled with 0s) 221 .text 222 223 224/* 225 * __start trampoline is located at a position relative to LowResetVectorBase 226 * so that iBoot can compute the reset vector position to set IORVBAR using 227 * only the kernel entry point. Reset vector = (__start & ~0xfff) 228 */ 229 .align 3 230 .globl EXT(_start) 231LEXT(_start) 232 ARM64_PROLOG 233 b EXT(start_first_cpu) 234 235 236/* 237 * Provides an early-boot exception vector so that the processor will spin 238 * and preserve exception information (e.g., ELR_EL1) when early CPU bootstrap 239 * code triggers an exception. This is copied to the second physical page 240 * during CPU bootstrap (see cpu.c). 241 */ 242 .align 12, 0 243 .global EXT(LowExceptionVectorBase) 244LEXT(LowExceptionVectorBase) 245 /* EL1 SP 0 */ 246 b . 247 .align 7 248 b . 249 .align 7 250 b . 251 .align 7 252 b . 253 /* EL1 SP1 */ 254 .align 7 255 b . 256 .align 7 257 b . 258 .align 7 259 b . 260 .align 7 261 b . 262 /* EL0 64 */ 263 .align 7 264 b . 265 .align 7 266 b . 267 .align 7 268 b . 269 .align 7 270 b . 271 /* EL0 32 */ 272 .align 7 273 b . 274 .align 7 275 b . 276 .align 7 277 b . 278 .align 7 279 b . 280 .align 12, 0 281 282#if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) 283/* 284 * Provide a global symbol so that we can narrow the V=P mapping to cover 285 * this page during arm_vm_init. 286 */ 287.align ARM_PGSHIFT 288.globl EXT(bootstrap_instructions) 289LEXT(bootstrap_instructions) 290 291#endif /* defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) */ 292 .align 2 293 .globl EXT(resume_idle_cpu) 294LEXT(resume_idle_cpu) 295 adrp lr, EXT(arm_init_idle_cpu)@page 296 add lr, lr, EXT(arm_init_idle_cpu)@pageoff 297 b start_cpu 298 299 .align 2 300 .globl EXT(start_cpu) 301LEXT(start_cpu) 302 adrp lr, EXT(arm_init_cpu)@page 303 add lr, lr, EXT(arm_init_cpu)@pageoff 304 b start_cpu 305 306 .align 2 307start_cpu: 308#if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) 309 // This is done right away in reset vector for pre-KTRR devices 310 // Set low reset vector now that we are in the KTRR-free zone 311 adrp x0, EXT(LowExceptionVectorBase)@page 312 add x0, x0, EXT(LowExceptionVectorBase)@pageoff 313 MSR_VBAR_EL1_X0 314#endif /* defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) */ 315 316 // x20 set to BootArgs phys address 317 // x21 set to cpu data phys address 318 319 // Get the kernel memory parameters from the boot args 320 ldr x22, [x20, BA_VIRT_BASE] // Get the kernel virt base 321 ldr x23, [x20, BA_PHYS_BASE] // Get the kernel phys base 322 ldr x24, [x20, BA_MEM_SIZE] // Get the physical memory size 323 adrp x25, EXT(bootstrap_pagetables)@page // Get the start of the page tables 324 ldr x26, [x20, BA_BOOT_FLAGS] // Get the kernel boot flags 325 326 327 // Set TPIDR_EL0 with cached CPU info 328 ldr x0, [x21, CPU_TPIDR_EL0] 329 msr TPIDR_EL0, x0 330 331 // Set TPIDRRO_EL0 to 0 332 msr TPIDRRO_EL0, xzr 333 334 335 // Set the exception stack pointer 336 ldr x0, [x21, CPU_EXCEPSTACK_TOP] 337 338 339 // Set SP_EL1 to exception stack 340#if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) 341 mov x1, lr 342 bl EXT(pinst_spsel_1) 343 mov lr, x1 344#else 345 msr SPSel, #1 346#endif 347 mov sp, x0 348 349 // Set the interrupt stack pointer 350 ldr x0, [x21, CPU_INTSTACK_TOP] 351 msr SPSel, #0 352 mov sp, x0 353 354 // Convert lr to KVA 355 add lr, lr, x22 356 sub lr, lr, x23 357 358 b common_start 359 360/* 361 * create_l1_table_entry 362 * 363 * Given a virtual address, creates a table entry in an L1 translation table 364 * to point to an L2 translation table. 365 * arg0 - Virtual address 366 * arg1 - L1 table address 367 * arg2 - L2 table address 368 * arg3 - Scratch register 369 * arg4 - Scratch register 370 * arg5 - Scratch register 371 */ 372.macro create_l1_table_entry 373 and $3, $0, #(ARM_TT_L1_INDEX_MASK) 374 lsr $3, $3, #(ARM_TT_L1_SHIFT) // Get index in L1 table for L2 table 375 lsl $3, $3, #(TTE_SHIFT) // Convert index into pointer offset 376 add $3, $1, $3 // Get L1 entry pointer 377 mov $4, #(ARM_TTE_BOOT_TABLE) // Get L1 table entry template 378 and $5, $2, #(ARM_TTE_TABLE_MASK) // Get address bits of L2 table 379 orr $5, $4, $5 // Create table entry for L2 table 380 str $5, [$3] // Write entry to L1 table 381.endmacro 382 383/* 384 * create_l2_block_entries 385 * 386 * Given base virtual and physical addresses, creates consecutive block entries 387 * in an L2 translation table. 388 * arg0 - Virtual address 389 * arg1 - Physical address 390 * arg2 - L2 table address 391 * arg3 - Number of entries 392 * arg4 - Scratch register 393 * arg5 - Scratch register 394 * arg6 - Scratch register 395 * arg7 - Scratch register 396 */ 397.macro create_l2_block_entries 398 and $4, $0, #(ARM_TT_L2_INDEX_MASK) 399 lsr $4, $4, #(ARM_TTE_BLOCK_L2_SHIFT) // Get index in L2 table for block entry 400 lsl $4, $4, #(TTE_SHIFT) // Convert index into pointer offset 401 add $4, $2, $4 // Get L2 entry pointer 402 mov $5, #(ARM_TTE_BOOT_BLOCK_LOWER) // Get L2 block entry template 403 orr $5, $5, #(ARM_TTE_BOOT_BLOCK_UPPER) 404 and $6, $1, #(ARM_TTE_BLOCK_L2_MASK) // Get address bits of block mapping 405 orr $6, $5, $6 406 mov $5, $3 407 mov $7, #(ARM_TT_L2_SIZE) 4081: 409 str $6, [$4], #(1 << TTE_SHIFT) // Write entry to L2 table and advance 410 add $6, $6, $7 // Increment the output address 411 subs $5, $5, #1 // Decrement the number of entries 412 b.ne 1b 413.endmacro 414 415/* 416 * arg0 - virtual start address 417 * arg1 - physical start address 418 * arg2 - number of entries to map 419 * arg3 - L1 table address 420 * arg4 - free space pointer 421 * arg5 - scratch (entries mapped per loop) 422 * arg6 - scratch 423 * arg7 - scratch 424 * arg8 - scratch 425 * arg9 - scratch 426 */ 427.macro create_bootstrap_mapping 428 /* calculate entries left in this page */ 429 and $5, $0, #(ARM_TT_L2_INDEX_MASK) 430 lsr $5, $5, #(ARM_TT_L2_SHIFT) 431 mov $6, #(TTE_PGENTRIES) 432 sub $5, $6, $5 433 434 /* allocate an L2 table */ 4353: add $4, $4, PGBYTES 436 437 /* create_l1_table_entry(virt_base, L1 table, L2 table, scratch1, scratch2, scratch3) */ 438 create_l1_table_entry $0, $3, $4, $6, $7, $8 439 440 /* determine how many entries to map this loop - the smaller of entries 441 * remaining in page and total entries left */ 442 cmp $2, $5 443 csel $5, $2, $5, lt 444 445 /* create_l2_block_entries(virt_base, phys_base, L2 table, num_ents, scratch1, scratch2, scratch3) */ 446 create_l2_block_entries $0, $1, $4, $5, $6, $7, $8, $9 447 448 /* subtract entries just mapped and bail out if we're done */ 449 subs $2, $2, $5 450 beq 2f 451 452 /* entries left to map - advance base pointers */ 453 add $0, $0, $5, lsl #(ARM_TT_L2_SHIFT) 454 add $1, $1, $5, lsl #(ARM_TT_L2_SHIFT) 455 456 mov $5, #(TTE_PGENTRIES) /* subsequent loops map (up to) a whole L2 page */ 457 b 3b 4582: 459.endmacro 460 461/* 462 * _start_first_cpu 463 * Cold boot init routine. Called from __start 464 * x0 - Boot args 465 */ 466 .align 2 467 .globl EXT(start_first_cpu) 468LEXT(start_first_cpu) 469 470 // Unlock the core for debugging 471 msr OSLAR_EL1, xzr 472 msr DAIFSet, #(DAIFSC_ALL) // Disable all interrupts 473 474 mov x20, x0 475 mov x21, #0 476 477 // Set low reset vector before attempting any loads 478 adrp x0, EXT(LowExceptionVectorBase)@page 479 add x0, x0, EXT(LowExceptionVectorBase)@pageoff 480 MSR_VBAR_EL1_X0 481 482 483 // Get the kernel memory parameters from the boot args 484 ldr x22, [x20, BA_VIRT_BASE] // Get the kernel virt base 485 ldr x23, [x20, BA_PHYS_BASE] // Get the kernel phys base 486 ldr x24, [x20, BA_MEM_SIZE] // Get the physical memory size 487 adrp x25, EXT(bootstrap_pagetables)@page // Get the start of the page tables 488 ldr x26, [x20, BA_BOOT_FLAGS] // Get the kernel boot flags 489 490 // Clear the registers that will be used to store the userspace thread pointer and CPU number. 491 // We may not actually be booting from ordinal CPU 0, so this register will be updated 492 // in ml_parse_cpu_topology(), which happens later in bootstrap. 493 msr TPIDRRO_EL0, xzr 494 msr TPIDR_EL0, xzr 495 496 // Set up exception stack pointer 497 adrp x0, EXT(excepstack_top)@page // Load top of exception stack 498 add x0, x0, EXT(excepstack_top)@pageoff 499 add x0, x0, x22 // Convert to KVA 500 sub x0, x0, x23 501 502 // Set SP_EL1 to exception stack 503#if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) 504 bl EXT(pinst_spsel_1) 505#else 506 msr SPSel, #1 507#endif 508 509 mov sp, x0 510 511 // Set up interrupt stack pointer 512 adrp x0, EXT(intstack_top)@page // Load top of irq stack 513 add x0, x0, EXT(intstack_top)@pageoff 514 add x0, x0, x22 // Convert to KVA 515 sub x0, x0, x23 516 msr SPSel, #0 // Set SP_EL0 to interrupt stack 517 mov sp, x0 518 519 // Load address to the C init routine into link register 520 adrp lr, EXT(arm_init)@page 521 add lr, lr, EXT(arm_init)@pageoff 522 add lr, lr, x22 // Convert to KVA 523 sub lr, lr, x23 524 525 /* 526 * Set up the bootstrap page tables with a single block entry for the V=P 527 * mapping, a single block entry for the trampolined kernel address (KVA), 528 * and all else invalid. This requires four pages: 529 * Page 1 - V=P L1 table 530 * Page 2 - V=P L2 table 531 * Page 3 - KVA L1 table 532 * Page 4 - KVA L2 table 533 */ 534 535 // Invalidate all entries in the bootstrap page tables 536 mov x0, #(ARM_TTE_EMPTY) // Load invalid entry template 537 mov x1, x25 // Start at V=P pagetable root 538 mov x2, #(TTE_PGENTRIES) // Load number of entries per page 539 lsl x2, x2, #2 // Shift by 2 for num entries on 4 pages 540 541Linvalidate_bootstrap: // do { 542 str x0, [x1], #(1 << TTE_SHIFT) // Invalidate and advance 543 subs x2, x2, #1 // entries-- 544 b.ne Linvalidate_bootstrap // } while (entries != 0) 545 546 /* 547 * In order to reclaim memory on targets where TZ0 (or some other entity) 548 * must be located at the base of memory, iBoot may set the virtual and 549 * physical base addresses to immediately follow whatever lies at the 550 * base of physical memory. 551 * 552 * If the base address belongs to TZ0, it may be dangerous for xnu to map 553 * it (as it may be prefetched, despite being technically inaccessible). 554 * In order to avoid this issue while keeping the mapping code simple, we 555 * may continue to use block mappings, but we will only map the kernelcache 556 * mach header to the end of memory. 557 * 558 * Given that iBoot guarantees that the unslid kernelcache base address 559 * will begin on an L2 boundary, this should prevent us from accidentally 560 * mapping TZ0. 561 */ 562 adrp x0, EXT(_mh_execute_header)@page // address of kernel mach header 563 add x0, x0, EXT(_mh_execute_header)@pageoff 564 ldr w1, [x0, #0x18] // load mach_header->flags 565 tbz w1, #0x1f, Lkernelcache_base_found // if MH_DYLIB_IN_CACHE unset, base is kernel mach header 566 ldr w1, [x0, #0x20] // load first segment cmd (offset sizeof(kernel_mach_header_t)) 567 cmp w1, #0x19 // must be LC_SEGMENT_64 568 bne . 569 ldr x1, [x0, #0x38] // load first segment vmaddr 570 sub x1, x0, x1 // compute slide 571 MOV64 x0, VM_KERNEL_LINK_ADDRESS 572 add x0, x0, x1 // base is kernel link address + slide 573 574Lkernelcache_base_found: 575 /* 576 * Adjust physical and virtual base addresses to account for physical 577 * memory preceeding xnu Mach-O header 578 * x22 - Kernel virtual base 579 * x23 - Kernel physical base 580 * x24 - Physical memory size 581 */ 582 sub x18, x0, x23 583 sub x24, x24, x18 584 add x22, x22, x18 585 add x23, x23, x18 586 587 /* 588 * x0 - V=P virtual cursor 589 * x4 - V=P physical cursor 590 * x14 - KVA virtual cursor 591 * x15 - KVA physical cursor 592 */ 593 mov x4, x0 594 mov x14, x22 595 mov x15, x23 596 597 /* 598 * Allocate L1 tables 599 * x1 - V=P L1 page 600 * x3 - KVA L1 page 601 * x2 - free mem pointer from which we allocate a variable number of L2 602 * pages. The maximum number of bootstrap page table pages is limited to 603 * BOOTSTRAP_TABLE_SIZE. For a 2G 4k page device, assuming the worst-case 604 * slide, we need 1xL1 and up to 3xL2 pages (1GB mapped per L1 entry), so 605 * 8 total pages for V=P and KVA. 606 */ 607 mov x1, x25 608 add x3, x1, PGBYTES 609 mov x2, x3 610 611 /* 612 * Setup the V=P bootstrap mapping 613 * x5 - total number of L2 entries to allocate 614 */ 615 lsr x5, x24, #(ARM_TT_L2_SHIFT) 616 /* create_bootstrap_mapping(vbase, pbase, num_ents, L1 table, freeptr) */ 617 create_bootstrap_mapping x0, x4, x5, x1, x2, x6, x10, x11, x12, x13 618 619 /* Setup the KVA bootstrap mapping */ 620 lsr x5, x24, #(ARM_TT_L2_SHIFT) 621 create_bootstrap_mapping x14, x15, x5, x3, x2, x9, x10, x11, x12, x13 622 623 /* Ensure TTEs are visible */ 624 dsb ish 625 626 627 b common_start 628 629/* 630 * Begin common CPU initialization 631 * 632 * Regster state: 633 * x20 - PA of boot args 634 * x21 - zero on cold boot, PA of cpu data on warm reset 635 * x22 - Kernel virtual base 636 * x23 - Kernel physical base 637 * x25 - PA of the V=P pagetable root 638 * lr - KVA of C init routine 639 * sp - SP_EL0 selected 640 * 641 * SP_EL0 - KVA of CPU's interrupt stack 642 * SP_EL1 - KVA of CPU's exception stack 643 * TPIDRRO_EL0 - CPU number 644 */ 645common_start: 646 647#if HAS_NEX_PG 648 mov x19, lr 649 bl EXT(set_nex_pg) 650 mov lr, x19 651#endif 652 653 // Set the translation control register. 654 adrp x0, EXT(sysreg_restore)@page // Load TCR value from the system register restore structure 655 add x0, x0, EXT(sysreg_restore)@pageoff 656 ldr x1, [x0, SR_RESTORE_TCR_EL1] 657 MSR_TCR_EL1_X1 658 659 /* Set up translation table base registers. 660 * TTBR0 - V=P table @ top of kernel 661 * TTBR1 - KVA table @ top of kernel + 1 page 662 */ 663#if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR) 664 /* Note that for KTRR configurations, the V=P map will be modified by 665 * arm_vm_init.c. 666 */ 667#endif 668 and x0, x25, #(TTBR_BADDR_MASK) 669 mov x19, lr 670 bl EXT(set_mmu_ttb) 671 mov lr, x19 672 add x0, x25, PGBYTES 673 and x0, x0, #(TTBR_BADDR_MASK) 674 MSR_TTBR1_EL1_X0 675 676 // Set up MAIR attr0 for normal memory, attr1 for device memory 677 mov x0, xzr 678 mov x1, #(MAIR_WRITEBACK << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_WRITEBACK)) 679 orr x0, x0, x1 680 mov x1, #(MAIR_WRITETHRU << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_WRITETHRU)) 681 orr x0, x0, x1 682 mov x1, #(MAIR_WRITECOMB << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_WRITECOMB)) 683 orr x0, x0, x1 684 mov x1, #(MAIR_WRITEBACK << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_RESERVED)) 685 orr x0, x0, x1 686 mov x1, #(MAIR_POSTED_COMBINED_REORDERED << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_POSTED_COMBINED_REORDERED)) 687 orr x0, x0, x1 688 mov x1, #(MAIR_DISABLE << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_DISABLE)) 689 orr x0, x0, x1 690#if HAS_FEAT_XS 691 mov x1, #(MAIR_DISABLE_XS << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_DISABLE_XS)) 692 orr x0, x0, x1 693 mov x1, #(MAIR_POSTED_COMBINED_REORDERED_XS << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_POSTED_COMBINED_REORDERED_XS)) 694 orr x0, x0, x1 695#else 696 mov x1, #(MAIR_POSTED << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_POSTED)) 697 orr x0, x0, x1 698 mov x1, #(MAIR_POSTED_REORDERED << MAIR_ATTR_SHIFT(CACHE_ATTRINDX_POSTED_REORDERED)) 699 orr x0, x0, x1 700#endif /* HAS_FEAT_XS */ 701 msr MAIR_EL1, x0 702 isb 703 tlbi vmalle1 704 dsb ish 705 706 707#ifndef __ARM_IC_NOALIAS_ICACHE__ 708 /* Invalidate the TLB and icache on systems that do not guarantee that the 709 * caches are invalidated on reset. 710 */ 711 tlbi vmalle1 712 ic iallu 713#endif 714 715 /* If x21 is not 0, then this is either the start_cpu path or 716 * the resume_idle_cpu path. cpu_ttep should already be 717 * populated, so just switch to the kernel_pmap now. 718 */ 719 720 cbz x21, 1f 721 adrp x0, EXT(cpu_ttep)@page 722 add x0, x0, EXT(cpu_ttep)@pageoff 723 ldr x0, [x0] 724 MSR_TTBR1_EL1_X0 7251: 726 727 // Set up the exception vectors 728#if __ARM_KERNEL_PROTECT__ 729 /* If this is not the first reset of the boot CPU, the alternate mapping 730 * for the exception vectors will be set up, so use it. Otherwise, we 731 * should use the mapping located in the kernelcache mapping. 732 */ 733 MOV64 x0, ARM_KERNEL_PROTECT_EXCEPTION_START 734 735 cbnz x21, 1f 736#endif /* __ARM_KERNEL_PROTECT__ */ 737 adrp x0, EXT(ExceptionVectorsBase)@page // Load exception vectors base address 738 add x0, x0, EXT(ExceptionVectorsBase)@pageoff 739 add x0, x0, x22 // Convert exception vector address to KVA 740 sub x0, x0, x23 7411: 742 MSR_VBAR_EL1_X0 743 744#if HAS_APPLE_PAC 745 PAC_INIT_KEY_STATE tmp=x0, tmp2=x1 746#endif /* HAS_APPLE_PAC */ 747 748 // Enable caches, MMU, ROP and JOP 749 MOV64 x0, SCTLR_EL1_DEFAULT 750 MSR_SCTLR_EL1_X0 751 isb sy 752 753#if !VMAPPLE 754 MOV64 x1, SCTLR_EL1_DEFAULT 755 cmp x0, x1 756 bne . 757#endif /* !VMAPPLE */ 758 759#if (!CONFIG_KERNEL_INTEGRITY || (CONFIG_KERNEL_INTEGRITY && !defined(KERNEL_INTEGRITY_WT))) 760 /* Watchtower 761 * 762 * If we have a Watchtower monitor it will setup CPACR_EL1 for us, touching 763 * it here would trap to EL3. 764 */ 765 766 // Enable NEON 767 mov x0, #(CPACR_FPEN_ENABLE) 768 msr CPACR_EL1, x0 769#endif 770 771 // Clear thread pointer 772 msr TPIDR_EL1, xzr // Set thread register 773 774 775#if defined(APPLE_ARM64_ARCH_FAMILY) 776 mrs x12, MDSCR_EL1 777 orr x12, x12, MDSCR_TDCC 778 msr MDSCR_EL1, x12 779 // Initialization common to all non-virtual Apple targets 780#endif // APPLE_ARM64_ARCH_FAMILY 781 782 // Read MIDR before start of per-SoC tunables 783 mrs x12, MIDR_EL1 784 785 APPLY_TUNABLES x12, x13, x14 786 787#if HAS_CLUSTER && !NO_CPU_OVRD 788 // Unmask external IRQs if we're restarting from non-retention WFI 789 mrs x9, CPU_OVRD 790 and x9, x9, #(~(ARM64_REG_CYC_OVRD_irq_mask | ARM64_REG_CYC_OVRD_fiq_mask)) 791 msr CPU_OVRD, x9 792#endif 793 794 // If x21 != 0, we're doing a warm reset, so we need to trampoline to the kernel pmap. 795 cbnz x21, Ltrampoline 796 797 // Set KVA of boot args as first arg 798 add x0, x20, x22 799 sub x0, x0, x23 800 801#if KASAN 802 mov x20, x0 803 mov x21, lr 804 805 // x0: boot args 806 // x1: KVA page table phys base 807 mrs x1, TTBR1_EL1 808 bl EXT(kasan_bootstrap) 809 810 mov x0, x20 811 mov lr, x21 812#endif 813 814 // Return to arm_init() 815 ret 816 817Ltrampoline: 818 // Load VA of the trampoline 819 adrp x0, arm_init_tramp@page 820 add x0, x0, arm_init_tramp@pageoff 821 add x0, x0, x22 822 sub x0, x0, x23 823 824 // Branch to the trampoline 825 br x0 826 827/* 828 * V=P to KVA trampoline. 829 * x0 - KVA of cpu data pointer 830 */ 831 .text 832 .align 2 833arm_init_tramp: 834 ARM64_JUMP_TARGET 835 /* On a warm boot, the full kernel translation table is initialized in 836 * addition to the bootstrap tables. The layout is as follows: 837 * 838 * +--Top of Memory--+ 839 * ... 840 * | | 841 * | Primary Kernel | 842 * | Trans. Table | 843 * | | 844 * +--Top + 5 pages--+ 845 * | | 846 * | Invalid Table | 847 * | | 848 * +--Top + 4 pages--+ 849 * | | 850 * | KVA Table | 851 * | | 852 * +--Top + 2 pages--+ 853 * | | 854 * | V=P Table | 855 * | | 856 * +--Top of Kernel--+ 857 * | | 858 * | Kernel Mach-O | 859 * | | 860 * ... 861 * +---Kernel Base---+ 862 */ 863 864 865 mov x19, lr 866 // Convert CPU data PA to VA and set as first argument 867 mov x0, x21 868 bl EXT(phystokv) 869 870 mov lr, x19 871 872 /* Return to arm_init() */ 873 ret 874 875//#include "globals_asm.h" 876 877/* vim: set ts=4: */ 878