| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/arch/arm/boot/compressed/head.S |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 1996-2002 Russell King |
|---|
| 5 | 6 | * Copyright (C) 2004 Hyok S. Choi (MPU support) |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | #include <linux/linkage.h> |
|---|
| 12 | 9 | #include <asm/assembler.h> |
|---|
| .. | .. |
|---|
| 31 | 28 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) |
|---|
| 32 | 29 | .macro loadsp, rb, tmp1, tmp2 |
|---|
| 33 | 30 | .endm |
|---|
| 34 | | - .macro writeb, ch, rb |
|---|
| 31 | + .macro writeb, ch, rb, tmp |
|---|
| 35 | 32 | mcr p14, 0, \ch, c0, c5, 0 |
|---|
| 36 | 33 | .endm |
|---|
| 37 | 34 | #elif defined(CONFIG_CPU_XSCALE) |
|---|
| 38 | 35 | .macro loadsp, rb, tmp1, tmp2 |
|---|
| 39 | 36 | .endm |
|---|
| 40 | | - .macro writeb, ch, rb |
|---|
| 37 | + .macro writeb, ch, rb, tmp |
|---|
| 41 | 38 | mcr p14, 0, \ch, c8, c0, 0 |
|---|
| 42 | 39 | .endm |
|---|
| 43 | 40 | #else |
|---|
| 44 | 41 | .macro loadsp, rb, tmp1, tmp2 |
|---|
| 45 | 42 | .endm |
|---|
| 46 | | - .macro writeb, ch, rb |
|---|
| 43 | + .macro writeb, ch, rb, tmp |
|---|
| 47 | 44 | mcr p14, 0, \ch, c1, c0, 0 |
|---|
| 48 | 45 | .endm |
|---|
| 49 | 46 | #endif |
|---|
| .. | .. |
|---|
| 52 | 49 | |
|---|
| 53 | 50 | #include CONFIG_DEBUG_LL_INCLUDE |
|---|
| 54 | 51 | |
|---|
| 55 | | - .macro writeb, ch, rb |
|---|
| 52 | + .macro writeb, ch, rb, tmp |
|---|
| 53 | +#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL |
|---|
| 54 | + waituartcts \tmp, \rb |
|---|
| 55 | +#endif |
|---|
| 56 | + waituarttxrdy \tmp, \rb |
|---|
| 56 | 57 | senduart \ch, \rb |
|---|
| 58 | + busyuart \tmp, \rb |
|---|
| 57 | 59 | .endm |
|---|
| 58 | 60 | |
|---|
| 59 | 61 | #if defined(CONFIG_ARCH_SA1100) |
|---|
| .. | .. |
|---|
| 84 | 86 | bl phex |
|---|
| 85 | 87 | .endm |
|---|
| 86 | 88 | |
|---|
| 87 | | - .macro debug_reloc_start |
|---|
| 89 | + /* |
|---|
| 90 | + * Debug kernel copy by printing the memory addresses involved |
|---|
| 91 | + */ |
|---|
| 92 | + .macro dbgkc, begin, end, cbegin, cend |
|---|
| 88 | 93 | #ifdef DEBUG |
|---|
| 89 | | - kputc #'\n' |
|---|
| 90 | | - kphex r6, 8 /* processor id */ |
|---|
| 91 | | - kputc #':' |
|---|
| 92 | | - kphex r7, 8 /* architecture id */ |
|---|
| 93 | | -#ifdef CONFIG_CPU_CP15 |
|---|
| 94 | | - kputc #':' |
|---|
| 95 | | - mrc p15, 0, r0, c1, c0 |
|---|
| 96 | | - kphex r0, 8 /* control reg */ |
|---|
| 97 | | -#endif |
|---|
| 98 | | - kputc #'\n' |
|---|
| 99 | | - kphex r5, 8 /* decompressed kernel start */ |
|---|
| 94 | + kputc #'C' |
|---|
| 95 | + kputc #':' |
|---|
| 96 | + kputc #'0' |
|---|
| 97 | + kputc #'x' |
|---|
| 98 | + kphex \begin, 8 /* Start of compressed kernel */ |
|---|
| 100 | 99 | kputc #'-' |
|---|
| 101 | | - kphex r9, 8 /* decompressed kernel end */ |
|---|
| 100 | + kputc #'0' |
|---|
| 101 | + kputc #'x' |
|---|
| 102 | + kphex \end, 8 /* End of compressed kernel */ |
|---|
| 103 | + kputc #'-' |
|---|
| 102 | 104 | kputc #'>' |
|---|
| 103 | | - kphex r4, 8 /* kernel execution address */ |
|---|
| 105 | + kputc #'0' |
|---|
| 106 | + kputc #'x' |
|---|
| 107 | + kphex \cbegin, 8 /* Start of kernel copy */ |
|---|
| 108 | + kputc #'-' |
|---|
| 109 | + kputc #'0' |
|---|
| 110 | + kputc #'x' |
|---|
| 111 | + kphex \cend, 8 /* End of kernel copy */ |
|---|
| 104 | 112 | kputc #'\n' |
|---|
| 105 | 113 | #endif |
|---|
| 106 | 114 | .endm |
|---|
| 107 | 115 | |
|---|
| 108 | | - .macro debug_reloc_end |
|---|
| 116 | + /* |
|---|
| 117 | + * Debug print of the final appended DTB location |
|---|
| 118 | + */ |
|---|
| 119 | + .macro dbgadtb, begin, size |
|---|
| 109 | 120 | #ifdef DEBUG |
|---|
| 110 | | - kphex r5, 8 /* end of kernel */ |
|---|
| 121 | + kputc #'D' |
|---|
| 122 | + kputc #'T' |
|---|
| 123 | + kputc #'B' |
|---|
| 124 | + kputc #':' |
|---|
| 125 | + kputc #'0' |
|---|
| 126 | + kputc #'x' |
|---|
| 127 | + kphex \begin, 8 /* Start of appended DTB */ |
|---|
| 128 | + kputc #' ' |
|---|
| 129 | + kputc #'(' |
|---|
| 130 | + kputc #'0' |
|---|
| 131 | + kputc #'x' |
|---|
| 132 | + kphex \size, 8 /* Size of appended DTB */ |
|---|
| 133 | + kputc #')' |
|---|
| 111 | 134 | kputc #'\n' |
|---|
| 112 | | - mov r0, r4 |
|---|
| 113 | | - bl memdump /* dump 256 bytes at start of kernel */ |
|---|
| 114 | 135 | #endif |
|---|
| 115 | 136 | .endm |
|---|
| 116 | 137 | |
|---|
| 117 | | - .section ".start", #alloc, #execinstr |
|---|
| 138 | + .macro enable_cp15_barriers, reg |
|---|
| 139 | + mrc p15, 0, \reg, c1, c0, 0 @ read SCTLR |
|---|
| 140 | + tst \reg, #(1 << 5) @ CP15BEN bit set? |
|---|
| 141 | + bne .L_\@ |
|---|
| 142 | + orr \reg, \reg, #(1 << 5) @ CP15 barrier instructions |
|---|
| 143 | + mcr p15, 0, \reg, c1, c0, 0 @ write SCTLR |
|---|
| 144 | + ARM( .inst 0xf57ff06f @ v7+ isb ) |
|---|
| 145 | + THUMB( isb ) |
|---|
| 146 | +.L_\@: |
|---|
| 147 | + .endm |
|---|
| 148 | + |
|---|
| 149 | + /* |
|---|
| 150 | + * The kernel build system appends the size of the |
|---|
| 151 | + * decompressed kernel at the end of the compressed data |
|---|
| 152 | + * in little-endian form. |
|---|
| 153 | + */ |
|---|
| 154 | + .macro get_inflated_image_size, res:req, tmp1:req, tmp2:req |
|---|
| 155 | + adr \res, .Linflated_image_size_offset |
|---|
| 156 | + ldr \tmp1, [\res] |
|---|
| 157 | + add \tmp1, \tmp1, \res @ address of inflated image size |
|---|
| 158 | + |
|---|
| 159 | + ldrb \res, [\tmp1] @ get_unaligned_le32 |
|---|
| 160 | + ldrb \tmp2, [\tmp1, #1] |
|---|
| 161 | + orr \res, \res, \tmp2, lsl #8 |
|---|
| 162 | + ldrb \tmp2, [\tmp1, #2] |
|---|
| 163 | + ldrb \tmp1, [\tmp1, #3] |
|---|
| 164 | + orr \res, \res, \tmp2, lsl #16 |
|---|
| 165 | + orr \res, \res, \tmp1, lsl #24 |
|---|
| 166 | + .endm |
|---|
| 167 | + |
|---|
| 168 | + .macro be32tocpu, val, tmp |
|---|
| 169 | +#ifndef __ARMEB__ |
|---|
| 170 | + /* convert to little endian */ |
|---|
| 171 | + rev_l \val, \tmp |
|---|
| 172 | +#endif |
|---|
| 173 | + .endm |
|---|
| 174 | + |
|---|
| 175 | + .section ".start", "ax" |
|---|
| 118 | 176 | /* |
|---|
| 119 | 177 | * sort out different calling conventions |
|---|
| 120 | 178 | */ |
|---|
| .. | .. |
|---|
| 127 | 185 | AR_CLASS( .arm ) |
|---|
| 128 | 186 | start: |
|---|
| 129 | 187 | .type start,#function |
|---|
| 130 | | - .rept 7 |
|---|
| 188 | + /* |
|---|
| 189 | + * These 7 nops along with the 1 nop immediately below for |
|---|
| 190 | + * !THUMB2 form 8 nops that make the compressed kernel bootable |
|---|
| 191 | + * on legacy ARM systems that were assuming the kernel in a.out |
|---|
| 192 | + * binary format. The boot loaders on these systems would |
|---|
| 193 | + * jump 32 bytes into the image to skip the a.out header. |
|---|
| 194 | + * with these 8 nops filling exactly 32 bytes, things still |
|---|
| 195 | + * work as expected on these legacy systems. Thumb2 mode keeps |
|---|
| 196 | + * 7 of the nops as it turns out that some boot loaders |
|---|
| 197 | + * were patching the initial instructions of the kernel, i.e |
|---|
| 198 | + * had started to exploit this "patch area". |
|---|
| 199 | + */ |
|---|
| 200 | + __initial_nops |
|---|
| 201 | + .rept 5 |
|---|
| 131 | 202 | __nop |
|---|
| 132 | 203 | .endr |
|---|
| 133 | 204 | #ifndef CONFIG_THUMB2_KERNEL |
|---|
| 134 | | - mov r0, r0 |
|---|
| 205 | + __nop |
|---|
| 135 | 206 | #else |
|---|
| 136 | 207 | AR_CLASS( sub pc, pc, #3 ) @ A/R: switch to Thumb2 mode |
|---|
| 137 | 208 | M_CLASS( nop.w ) @ M: already in Thumb2 mode |
|---|
| .. | .. |
|---|
| 220 | 291 | */ |
|---|
| 221 | 292 | mov r0, pc |
|---|
| 222 | 293 | cmp r0, r4 |
|---|
| 223 | | - ldrcc r0, LC0+32 |
|---|
| 294 | + ldrcc r0, .Lheadroom |
|---|
| 224 | 295 | addcc r0, r0, pc |
|---|
| 225 | 296 | cmpcc r4, r0 |
|---|
| 226 | 297 | orrcc r4, r4, #1 @ remember we skipped cache_on |
|---|
| 227 | 298 | blcs cache_on |
|---|
| 228 | 299 | |
|---|
| 229 | | -restart: adr r0, LC0 |
|---|
| 230 | | - ldmia r0, {r1, r2, r3, r6, r10, r11, r12} |
|---|
| 231 | | - ldr sp, [r0, #28] |
|---|
| 300 | +restart: adr r0, LC1 |
|---|
| 301 | + ldr sp, [r0] |
|---|
| 302 | + ldr r6, [r0, #4] |
|---|
| 303 | + add sp, sp, r0 |
|---|
| 304 | + add r6, r6, r0 |
|---|
| 232 | 305 | |
|---|
| 233 | | - /* |
|---|
| 234 | | - * We might be running at a different address. We need |
|---|
| 235 | | - * to fix up various pointers. |
|---|
| 236 | | - */ |
|---|
| 237 | | - sub r0, r0, r1 @ calculate the delta offset |
|---|
| 238 | | - add r6, r6, r0 @ _edata |
|---|
| 239 | | - add r10, r10, r0 @ inflated kernel size location |
|---|
| 240 | | - |
|---|
| 241 | | - /* |
|---|
| 242 | | - * The kernel build system appends the size of the |
|---|
| 243 | | - * decompressed kernel at the end of the compressed data |
|---|
| 244 | | - * in little-endian form. |
|---|
| 245 | | - */ |
|---|
| 246 | | - ldrb r9, [r10, #0] |
|---|
| 247 | | - ldrb lr, [r10, #1] |
|---|
| 248 | | - orr r9, r9, lr, lsl #8 |
|---|
| 249 | | - ldrb lr, [r10, #2] |
|---|
| 250 | | - ldrb r10, [r10, #3] |
|---|
| 251 | | - orr r9, r9, lr, lsl #16 |
|---|
| 252 | | - orr r9, r9, r10, lsl #24 |
|---|
| 306 | + get_inflated_image_size r9, r10, lr |
|---|
| 253 | 307 | |
|---|
| 254 | 308 | #ifndef CONFIG_ZBOOT_ROM |
|---|
| 255 | 309 | /* malloc space is above the relocated stack (64k max) */ |
|---|
| 256 | | - add sp, sp, r0 |
|---|
| 257 | | - add r10, sp, #0x10000 |
|---|
| 310 | + add r10, sp, #MALLOC_SIZE |
|---|
| 258 | 311 | #else |
|---|
| 259 | 312 | /* |
|---|
| 260 | 313 | * With ZBOOT_ROM the bss/stack is non relocatable, |
|---|
| .. | .. |
|---|
| 267 | 320 | mov r5, #0 @ init dtb size to 0 |
|---|
| 268 | 321 | #ifdef CONFIG_ARM_APPENDED_DTB |
|---|
| 269 | 322 | /* |
|---|
| 270 | | - * r0 = delta |
|---|
| 271 | | - * r2 = BSS start |
|---|
| 272 | | - * r3 = BSS end |
|---|
| 273 | 323 | * r4 = final kernel address (possibly with LSB set) |
|---|
| 274 | 324 | * r5 = appended dtb size (still unknown) |
|---|
| 275 | 325 | * r6 = _edata |
|---|
| .. | .. |
|---|
| 277 | 327 | * r8 = atags/device tree pointer |
|---|
| 278 | 328 | * r9 = size of decompressed image |
|---|
| 279 | 329 | * r10 = end of this image, including bss/stack/malloc space if non XIP |
|---|
| 280 | | - * r11 = GOT start |
|---|
| 281 | | - * r12 = GOT end |
|---|
| 282 | 330 | * sp = stack pointer |
|---|
| 283 | 331 | * |
|---|
| 284 | 332 | * if there are device trees (dtb) appended to zImage, advance r10 so that the |
|---|
| .. | .. |
|---|
| 306 | 354 | |
|---|
| 307 | 355 | /* Get the initial DTB size */ |
|---|
| 308 | 356 | ldr r5, [r6, #4] |
|---|
| 309 | | -#ifndef __ARMEB__ |
|---|
| 310 | | - /* convert to little endian */ |
|---|
| 311 | | - eor r1, r5, r5, ror #16 |
|---|
| 312 | | - bic r1, r1, #0x00ff0000 |
|---|
| 313 | | - mov r5, r5, ror #8 |
|---|
| 314 | | - eor r5, r5, r1, lsr #8 |
|---|
| 315 | | -#endif |
|---|
| 357 | + be32tocpu r5, r1 |
|---|
| 358 | + dbgadtb r6, r5 |
|---|
| 316 | 359 | /* 50% DTB growth should be good enough */ |
|---|
| 317 | 360 | add r5, r5, r5, lsr #1 |
|---|
| 318 | 361 | /* preserve 64-bit alignment */ |
|---|
| .. | .. |
|---|
| 326 | 369 | /* temporarily relocate the stack past the DTB work space */ |
|---|
| 327 | 370 | add sp, sp, r5 |
|---|
| 328 | 371 | |
|---|
| 329 | | - stmfd sp!, {r0-r3, ip, lr} |
|---|
| 330 | 372 | mov r0, r8 |
|---|
| 331 | 373 | mov r1, r6 |
|---|
| 332 | 374 | mov r2, r5 |
|---|
| .. | .. |
|---|
| 346 | 388 | mov r2, r5 |
|---|
| 347 | 389 | bleq atags_to_fdt |
|---|
| 348 | 390 | |
|---|
| 349 | | - ldmfd sp!, {r0-r3, ip, lr} |
|---|
| 350 | 391 | sub sp, sp, r5 |
|---|
| 351 | 392 | #endif |
|---|
| 352 | 393 | |
|---|
| .. | .. |
|---|
| 366 | 407 | |
|---|
| 367 | 408 | /* Get the current DTB size */ |
|---|
| 368 | 409 | ldr r5, [r6, #4] |
|---|
| 369 | | -#ifndef __ARMEB__ |
|---|
| 370 | | - /* convert r5 (dtb size) to little endian */ |
|---|
| 371 | | - eor r1, r5, r5, ror #16 |
|---|
| 372 | | - bic r1, r1, #0x00ff0000 |
|---|
| 373 | | - mov r5, r5, ror #8 |
|---|
| 374 | | - eor r5, r5, r1, lsr #8 |
|---|
| 375 | | -#endif |
|---|
| 410 | + be32tocpu r5, r1 |
|---|
| 376 | 411 | |
|---|
| 377 | 412 | /* preserve 64-bit alignment */ |
|---|
| 378 | 413 | add r5, r5, #7 |
|---|
| .. | .. |
|---|
| 452 | 487 | add r6, r9, r5 |
|---|
| 453 | 488 | add r9, r9, r10 |
|---|
| 454 | 489 | |
|---|
| 490 | +#ifdef DEBUG |
|---|
| 491 | + sub r10, r6, r5 |
|---|
| 492 | + sub r10, r9, r10 |
|---|
| 493 | + /* |
|---|
| 494 | + * We are about to copy the kernel to a new memory area. |
|---|
| 495 | + * The boundaries of the new memory area can be found in |
|---|
| 496 | + * r10 and r9, whilst r5 and r6 contain the boundaries |
|---|
| 497 | + * of the memory we are going to copy. |
|---|
| 498 | + * Calling dbgkc will help with the printing of this |
|---|
| 499 | + * information. |
|---|
| 500 | + */ |
|---|
| 501 | + dbgkc r5, r6, r10, r9 |
|---|
| 502 | +#endif |
|---|
| 503 | + |
|---|
| 455 | 504 | 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} |
|---|
| 456 | 505 | cmp r6, r5 |
|---|
| 457 | 506 | stmdb r9!, {r0 - r3, r10 - r12, lr} |
|---|
| .. | .. |
|---|
| 460 | 509 | /* Preserve offset to relocated code. */ |
|---|
| 461 | 510 | sub r6, r9, r6 |
|---|
| 462 | 511 | |
|---|
| 463 | | -#ifndef CONFIG_ZBOOT_ROM |
|---|
| 464 | | - /* cache_clean_flush may use the stack, so relocate it */ |
|---|
| 465 | | - add sp, sp, r6 |
|---|
| 466 | | -#endif |
|---|
| 467 | | - |
|---|
| 512 | + mov r0, r9 @ start of relocated zImage |
|---|
| 513 | + add r1, sp, r6 @ end of relocated zImage |
|---|
| 468 | 514 | bl cache_clean_flush |
|---|
| 469 | 515 | |
|---|
| 470 | 516 | badr r0, restart |
|---|
| .. | .. |
|---|
| 472 | 518 | mov pc, r0 |
|---|
| 473 | 519 | |
|---|
| 474 | 520 | wont_overwrite: |
|---|
| 521 | + adr r0, LC0 |
|---|
| 522 | + ldmia r0, {r1, r2, r3, r11, r12} |
|---|
| 523 | + sub r0, r0, r1 @ calculate the delta offset |
|---|
| 524 | + |
|---|
| 475 | 525 | /* |
|---|
| 476 | 526 | * If delta is zero, we are running at the address we were linked at. |
|---|
| 477 | 527 | * r0 = delta |
|---|
| .. | .. |
|---|
| 558 | 608 | */ |
|---|
| 559 | 609 | mov r0, r4 |
|---|
| 560 | 610 | mov r1, sp @ malloc space above stack |
|---|
| 561 | | - add r2, sp, #0x10000 @ 64k max |
|---|
| 611 | + add r2, sp, #MALLOC_SIZE @ 64k max |
|---|
| 562 | 612 | mov r3, r7 |
|---|
| 563 | 613 | bl decompress_kernel |
|---|
| 614 | + |
|---|
| 615 | + get_inflated_image_size r1, r2, r3 |
|---|
| 616 | + |
|---|
| 617 | + mov r0, r4 @ start of inflated image |
|---|
| 618 | + add r1, r1, r0 @ end of inflated image |
|---|
| 564 | 619 | bl cache_clean_flush |
|---|
| 565 | 620 | bl cache_off |
|---|
| 566 | 621 | |
|---|
| .. | .. |
|---|
| 590 | 645 | LC0: .word LC0 @ r1 |
|---|
| 591 | 646 | .word __bss_start @ r2 |
|---|
| 592 | 647 | .word _end @ r3 |
|---|
| 593 | | - .word _edata @ r6 |
|---|
| 594 | | - .word input_data_end - 4 @ r10 (inflated size location) |
|---|
| 595 | 648 | .word _got_start @ r11 |
|---|
| 596 | 649 | .word _got_end @ ip |
|---|
| 597 | | - .word .L_user_stack_end @ sp |
|---|
| 598 | | - .word _end - restart + 16384 + 1024*1024 |
|---|
| 599 | 650 | .size LC0, . - LC0 |
|---|
| 651 | + |
|---|
| 652 | + .type LC1, #object |
|---|
| 653 | +LC1: .word .L_user_stack_end - LC1 @ sp |
|---|
| 654 | + .word _edata - LC1 @ r6 |
|---|
| 655 | + .size LC1, . - LC1 |
|---|
| 656 | + |
|---|
| 657 | +.Lheadroom: |
|---|
| 658 | + .word _end - restart + 16384 + 1024*1024 |
|---|
| 659 | + |
|---|
| 660 | +.Linflated_image_size_offset: |
|---|
| 661 | + .long (input_data_end - 4) - . |
|---|
| 600 | 662 | |
|---|
| 601 | 663 | #ifdef CONFIG_ARCH_RPC |
|---|
| 602 | 664 | .globl params |
|---|
| .. | .. |
|---|
| 605 | 667 | .ltorg |
|---|
| 606 | 668 | .align |
|---|
| 607 | 669 | #endif |
|---|
| 670 | + |
|---|
| 671 | +/* |
|---|
| 672 | + * dcache_line_size - get the minimum D-cache line size from the CTR register |
|---|
| 673 | + * on ARMv7. |
|---|
| 674 | + */ |
|---|
| 675 | + .macro dcache_line_size, reg, tmp |
|---|
| 676 | +#ifdef CONFIG_CPU_V7M |
|---|
| 677 | + movw \tmp, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_CTR |
|---|
| 678 | + movt \tmp, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_CTR |
|---|
| 679 | + ldr \tmp, [\tmp] |
|---|
| 680 | +#else |
|---|
| 681 | + mrc p15, 0, \tmp, c0, c0, 1 @ read ctr |
|---|
| 682 | +#endif |
|---|
| 683 | + lsr \tmp, \tmp, #16 |
|---|
| 684 | + and \tmp, \tmp, #0xf @ cache line size encoding |
|---|
| 685 | + mov \reg, #4 @ bytes per word |
|---|
| 686 | + mov \reg, \reg, lsl \tmp @ actual cache line size |
|---|
| 687 | + .endm |
|---|
| 608 | 688 | |
|---|
| 609 | 689 | /* |
|---|
| 610 | 690 | * Turn on the cache. We need to setup some page tables so that we |
|---|
| .. | .. |
|---|
| 770 | 850 | mov pc, r12 |
|---|
| 771 | 851 | |
|---|
| 772 | 852 | __armv7_mmu_cache_on: |
|---|
| 853 | + enable_cp15_barriers r11 |
|---|
| 773 | 854 | mov r12, lr |
|---|
| 774 | 855 | #ifdef CONFIG_MMU |
|---|
| 775 | 856 | mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 |
|---|
| .. | .. |
|---|
| 1097 | 1178 | bic r0, r0, #0x0004 |
|---|
| 1098 | 1179 | #endif |
|---|
| 1099 | 1180 | mcr p15, 0, r0, c1, c0 @ turn MMU and cache off |
|---|
| 1100 | | - mov r12, lr |
|---|
| 1101 | | - bl __armv7_mmu_cache_flush |
|---|
| 1102 | 1181 | mov r0, #0 |
|---|
| 1103 | 1182 | #ifdef CONFIG_MMU |
|---|
| 1104 | 1183 | mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB |
|---|
| .. | .. |
|---|
| 1106 | 1185 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC |
|---|
| 1107 | 1186 | mcr p15, 0, r0, c7, c10, 4 @ DSB |
|---|
| 1108 | 1187 | mcr p15, 0, r0, c7, c5, 4 @ ISB |
|---|
| 1109 | | - mov pc, r12 |
|---|
| 1188 | + mov pc, lr |
|---|
| 1110 | 1189 | |
|---|
| 1111 | 1190 | /* |
|---|
| 1112 | 1191 | * Clean and flush the cache to maintain consistency. |
|---|
| 1113 | 1192 | * |
|---|
| 1193 | + * On entry, |
|---|
| 1194 | + * r0 = start address |
|---|
| 1195 | + * r1 = end address (exclusive) |
|---|
| 1114 | 1196 | * On exit, |
|---|
| 1115 | 1197 | * r1, r2, r3, r9, r10, r11, r12 corrupted |
|---|
| 1116 | 1198 | * This routine must preserve: |
|---|
| .. | .. |
|---|
| 1119 | 1201 | .align 5 |
|---|
| 1120 | 1202 | cache_clean_flush: |
|---|
| 1121 | 1203 | mov r3, #16 |
|---|
| 1204 | + mov r11, r1 |
|---|
| 1122 | 1205 | b call_cache_fn |
|---|
| 1123 | 1206 | |
|---|
| 1124 | 1207 | __armv4_mpu_cache_flush: |
|---|
| .. | .. |
|---|
| 1159 | 1242 | mov pc, lr |
|---|
| 1160 | 1243 | |
|---|
| 1161 | 1244 | __armv7_mmu_cache_flush: |
|---|
| 1245 | + enable_cp15_barriers r10 |
|---|
| 1162 | 1246 | tst r4, #1 |
|---|
| 1163 | 1247 | bne iflush |
|---|
| 1164 | 1248 | mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 |
|---|
| .. | .. |
|---|
| 1168 | 1252 | mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D |
|---|
| 1169 | 1253 | b iflush |
|---|
| 1170 | 1254 | hierarchical: |
|---|
| 1171 | | - mcr p15, 0, r10, c7, c10, 5 @ DMB |
|---|
| 1172 | | - stmfd sp!, {r0-r7, r9-r11} |
|---|
| 1173 | | - mrc p15, 1, r0, c0, c0, 1 @ read clidr |
|---|
| 1174 | | - ands r3, r0, #0x7000000 @ extract loc from clidr |
|---|
| 1175 | | - mov r3, r3, lsr #23 @ left align loc bit field |
|---|
| 1176 | | - beq finished @ if loc is 0, then no need to clean |
|---|
| 1177 | | - mov r10, #0 @ start clean at cache level 0 |
|---|
| 1178 | | -loop1: |
|---|
| 1179 | | - add r2, r10, r10, lsr #1 @ work out 3x current cache level |
|---|
| 1180 | | - mov r1, r0, lsr r2 @ extract cache type bits from clidr |
|---|
| 1181 | | - and r1, r1, #7 @ mask of the bits for current cache only |
|---|
| 1182 | | - cmp r1, #2 @ see what cache we have at this level |
|---|
| 1183 | | - blt skip @ skip if no cache, or just i-cache |
|---|
| 1184 | | - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
|---|
| 1185 | | - mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr |
|---|
| 1186 | | - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr |
|---|
| 1187 | | - and r2, r1, #7 @ extract the length of the cache lines |
|---|
| 1188 | | - add r2, r2, #4 @ add 4 (line length offset) |
|---|
| 1189 | | - ldr r4, =0x3ff |
|---|
| 1190 | | - ands r4, r4, r1, lsr #3 @ find maximum number on the way size |
|---|
| 1191 | | - clz r5, r4 @ find bit position of way size increment |
|---|
| 1192 | | - ldr r7, =0x7fff |
|---|
| 1193 | | - ands r7, r7, r1, lsr #13 @ extract max number of the index size |
|---|
| 1194 | | -loop2: |
|---|
| 1195 | | - mov r9, r4 @ create working copy of max way size |
|---|
| 1196 | | -loop3: |
|---|
| 1197 | | - ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 |
|---|
| 1198 | | - ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 |
|---|
| 1199 | | - THUMB( lsl r6, r9, r5 ) |
|---|
| 1200 | | - THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 |
|---|
| 1201 | | - THUMB( lsl r6, r7, r2 ) |
|---|
| 1202 | | - THUMB( orr r11, r11, r6 ) @ factor index number into r11 |
|---|
| 1203 | | - mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way |
|---|
| 1204 | | - subs r9, r9, #1 @ decrement the way |
|---|
| 1205 | | - bge loop3 |
|---|
| 1206 | | - subs r7, r7, #1 @ decrement the index |
|---|
| 1207 | | - bge loop2 |
|---|
| 1208 | | -skip: |
|---|
| 1209 | | - add r10, r10, #2 @ increment cache number |
|---|
| 1210 | | - cmp r3, r10 |
|---|
| 1211 | | - bgt loop1 |
|---|
| 1212 | | -finished: |
|---|
| 1213 | | - ldmfd sp!, {r0-r7, r9-r11} |
|---|
| 1214 | | - mov r10, #0 @ switch back to cache level 0 |
|---|
| 1215 | | - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
|---|
| 1255 | + dcache_line_size r1, r2 @ r1 := dcache min line size |
|---|
| 1256 | + sub r2, r1, #1 @ r2 := line size mask |
|---|
| 1257 | + bic r0, r0, r2 @ round down start to line size |
|---|
| 1258 | + sub r11, r11, #1 @ end address is exclusive |
|---|
| 1259 | + bic r11, r11, r2 @ round down end to line size |
|---|
| 1260 | +0: cmp r0, r11 @ finished? |
|---|
| 1261 | + bgt iflush |
|---|
| 1262 | + mcr p15, 0, r0, c7, c14, 1 @ Dcache clean/invalidate by VA |
|---|
| 1263 | + add r0, r0, r1 |
|---|
| 1264 | + b 0b |
|---|
| 1216 | 1265 | iflush: |
|---|
| 1217 | 1266 | mcr p15, 0, r10, c7, c10, 4 @ DSB |
|---|
| 1218 | 1267 | mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB |
|---|
| .. | .. |
|---|
| 1223 | 1272 | __armv5tej_mmu_cache_flush: |
|---|
| 1224 | 1273 | tst r4, #1 |
|---|
| 1225 | 1274 | movne pc, lr |
|---|
| 1226 | | -1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache |
|---|
| 1275 | +1: mrc p15, 0, APSR_nzcv, c7, c14, 3 @ test,clean,invalidate D cache |
|---|
| 1227 | 1276 | bne 1b |
|---|
| 1228 | 1277 | mcr p15, 0, r0, c7, c5, 0 @ flush I cache |
|---|
| 1229 | 1278 | mcr p15, 0, r0, c7, c10, 4 @ drain WB |
|---|
| .. | .. |
|---|
| 1301 | 1350 | 1: ldrb r2, [r0], #1 |
|---|
| 1302 | 1351 | teq r2, #0 |
|---|
| 1303 | 1352 | moveq pc, lr |
|---|
| 1304 | | -2: writeb r2, r3 |
|---|
| 1353 | +2: writeb r2, r3, r1 |
|---|
| 1305 | 1354 | mov r1, #0x00020000 |
|---|
| 1306 | 1355 | 3: subs r1, r1, #1 |
|---|
| 1307 | 1356 | bne 3b |
|---|
| .. | .. |
|---|
| 1355 | 1404 | __hyp_reentry_vectors: |
|---|
| 1356 | 1405 | W(b) . @ reset |
|---|
| 1357 | 1406 | W(b) . @ undef |
|---|
| 1407 | +#ifdef CONFIG_EFI_STUB |
|---|
| 1408 | + W(b) __enter_kernel_from_hyp @ hvc from HYP |
|---|
| 1409 | +#else |
|---|
| 1358 | 1410 | W(b) . @ svc |
|---|
| 1411 | +#endif |
|---|
| 1359 | 1412 | W(b) . @ pabort |
|---|
| 1360 | 1413 | W(b) . @ dabort |
|---|
| 1361 | 1414 | W(b) __enter_kernel @ hyp |
|---|
| .. | .. |
|---|
| 1374 | 1427 | reloc_code_end: |
|---|
| 1375 | 1428 | |
|---|
| 1376 | 1429 | #ifdef CONFIG_EFI_STUB |
|---|
| 1377 | | - .align 2 |
|---|
| 1378 | | -_start: .long start - . |
|---|
| 1430 | +__enter_kernel_from_hyp: |
|---|
| 1431 | + mrc p15, 4, r0, c1, c0, 0 @ read HSCTLR |
|---|
| 1432 | + bic r0, r0, #0x5 @ disable MMU and caches |
|---|
| 1433 | + mcr p15, 4, r0, c1, c0, 0 @ write HSCTLR |
|---|
| 1434 | + isb |
|---|
| 1435 | + b __enter_kernel |
|---|
| 1379 | 1436 | |
|---|
| 1380 | | -ENTRY(efi_stub_entry) |
|---|
| 1381 | | - @ allocate space on stack for passing current zImage address |
|---|
| 1382 | | - @ and for the EFI stub to return of new entry point of |
|---|
| 1383 | | - @ zImage, as EFI stub may copy the kernel. Pointer address |
|---|
| 1384 | | - @ is passed in r2. r0 and r1 are passed through from the |
|---|
| 1385 | | - @ EFI firmware to efi_entry |
|---|
| 1386 | | - adr ip, _start |
|---|
| 1387 | | - ldr r3, [ip] |
|---|
| 1388 | | - add r3, r3, ip |
|---|
| 1389 | | - stmfd sp!, {r3, lr} |
|---|
| 1390 | | - mov r2, sp @ pass zImage address in r2 |
|---|
| 1391 | | - bl efi_entry |
|---|
| 1437 | +ENTRY(efi_enter_kernel) |
|---|
| 1438 | + mov r4, r0 @ preserve image base |
|---|
| 1439 | + mov r8, r1 @ preserve DT pointer |
|---|
| 1392 | 1440 | |
|---|
| 1393 | | - @ Check for error return from EFI stub. r0 has FDT address |
|---|
| 1394 | | - @ or error code. |
|---|
| 1395 | | - cmn r0, #1 |
|---|
| 1396 | | - beq efi_load_fail |
|---|
| 1441 | + adr_l r0, call_cache_fn |
|---|
| 1442 | + adr r1, 0f @ clean the region of code we |
|---|
| 1443 | + bl cache_clean_flush @ may run with the MMU off |
|---|
| 1397 | 1444 | |
|---|
| 1398 | | - @ Preserve return value of efi_entry() in r4 |
|---|
| 1399 | | - mov r4, r0 |
|---|
| 1445 | +#ifdef CONFIG_ARM_VIRT_EXT |
|---|
| 1446 | + @ |
|---|
| 1447 | + @ The EFI spec does not support booting on ARM in HYP mode, |
|---|
| 1448 | + @ since it mandates that the MMU and caches are on, with all |
|---|
| 1449 | + @ 32-bit addressable DRAM mapped 1:1 using short descriptors. |
|---|
| 1450 | + @ |
|---|
| 1451 | + @ While the EDK2 reference implementation adheres to this, |
|---|
| 1452 | + @ U-Boot might decide to enter the EFI stub in HYP mode |
|---|
| 1453 | + @ anyway, with the MMU and caches either on or off. |
|---|
| 1454 | + @ |
|---|
| 1455 | + mrs r0, cpsr @ get the current mode |
|---|
| 1456 | + msr spsr_cxsf, r0 @ record boot mode |
|---|
| 1457 | + and r0, r0, #MODE_MASK @ are we running in HYP mode? |
|---|
| 1458 | + cmp r0, #HYP_MODE |
|---|
| 1459 | + bne .Lefi_svc |
|---|
| 1400 | 1460 | |
|---|
| 1401 | | - @ our cache maintenance code relies on CP15 barrier instructions |
|---|
| 1402 | | - @ but since we arrived here with the MMU and caches configured |
|---|
| 1403 | | - @ by UEFI, we must check that the CP15BEN bit is set in SCTLR. |
|---|
| 1404 | | - @ Note that this bit is RAO/WI on v6 and earlier, so the ISB in |
|---|
| 1405 | | - @ the enable path will be executed on v7+ only. |
|---|
| 1406 | | - mrc p15, 0, r1, c1, c0, 0 @ read SCTLR |
|---|
| 1407 | | - tst r1, #(1 << 5) @ CP15BEN bit set? |
|---|
| 1408 | | - bne 0f |
|---|
| 1409 | | - orr r1, r1, #(1 << 5) @ CP15 barrier instructions |
|---|
| 1410 | | - mcr p15, 0, r1, c1, c0, 0 @ write SCTLR |
|---|
| 1411 | | - ARM( .inst 0xf57ff06f @ v7+ isb ) |
|---|
| 1412 | | - THUMB( isb ) |
|---|
| 1461 | + mrc p15, 4, r1, c1, c0, 0 @ read HSCTLR |
|---|
| 1462 | + tst r1, #0x1 @ MMU enabled at HYP? |
|---|
| 1463 | + beq 1f |
|---|
| 1413 | 1464 | |
|---|
| 1414 | | -0: bl cache_clean_flush |
|---|
| 1415 | | - bl cache_off |
|---|
| 1465 | + @ |
|---|
| 1466 | + @ When running in HYP mode with the caches on, we're better |
|---|
| 1467 | + @ off just carrying on using the cached 1:1 mapping that the |
|---|
| 1468 | + @ firmware provided. Set up the HYP vectors so HVC instructions |
|---|
| 1469 | + @ issued from HYP mode take us to the correct handler code. We |
|---|
| 1470 | + @ will disable the MMU before jumping to the kernel proper. |
|---|
| 1471 | + @ |
|---|
| 1472 | + ARM( bic r1, r1, #(1 << 30) ) @ clear HSCTLR.TE |
|---|
| 1473 | + THUMB( orr r1, r1, #(1 << 30) ) @ set HSCTLR.TE |
|---|
| 1474 | + mcr p15, 4, r1, c1, c0, 0 |
|---|
| 1475 | + adr r0, __hyp_reentry_vectors |
|---|
| 1476 | + mcr p15, 4, r0, c12, c0, 0 @ set HYP vector base (HVBAR) |
|---|
| 1477 | + isb |
|---|
| 1478 | + b .Lefi_hyp |
|---|
| 1416 | 1479 | |
|---|
| 1417 | | - @ Set parameters for booting zImage according to boot protocol |
|---|
| 1418 | | - @ put FDT address in r2, it was returned by efi_entry() |
|---|
| 1419 | | - @ r1 is the machine type, and r0 needs to be 0 |
|---|
| 1420 | | - mov r0, #0 |
|---|
| 1421 | | - mov r1, #0xFFFFFFFF |
|---|
| 1422 | | - mov r2, r4 |
|---|
| 1480 | + @ |
|---|
| 1481 | + @ When running in HYP mode with the caches off, we need to drop |
|---|
| 1482 | + @ into SVC mode now, and let the decompressor set up its cached |
|---|
| 1483 | + @ 1:1 mapping as usual. |
|---|
| 1484 | + @ |
|---|
| 1485 | +1: mov r9, r4 @ preserve image base |
|---|
| 1486 | + bl __hyp_stub_install @ install HYP stub vectors |
|---|
| 1487 | + safe_svcmode_maskall r1 @ drop to SVC mode |
|---|
| 1488 | + msr spsr_cxsf, r0 @ record boot mode |
|---|
| 1489 | + orr r4, r9, #1 @ restore image base and set LSB |
|---|
| 1490 | + b .Lefi_hyp |
|---|
| 1491 | +.Lefi_svc: |
|---|
| 1492 | +#endif |
|---|
| 1493 | + mrc p15, 0, r0, c1, c0, 0 @ read SCTLR |
|---|
| 1494 | + tst r0, #0x1 @ MMU enabled? |
|---|
| 1495 | + orreq r4, r4, #1 @ set LSB if not |
|---|
| 1423 | 1496 | |
|---|
| 1424 | | - @ Branch to (possibly) relocated zImage that is in [sp] |
|---|
| 1425 | | - ldr lr, [sp] |
|---|
| 1426 | | - ldr ip, =start_offset |
|---|
| 1427 | | - add lr, lr, ip |
|---|
| 1428 | | - mov pc, lr @ no mode switch |
|---|
| 1497 | +.Lefi_hyp: |
|---|
| 1498 | + mov r0, r8 @ DT start |
|---|
| 1499 | + add r1, r8, r2 @ DT end |
|---|
| 1500 | + bl cache_clean_flush |
|---|
| 1429 | 1501 | |
|---|
| 1430 | | -efi_load_fail: |
|---|
| 1431 | | - @ Return EFI_LOAD_ERROR to EFI firmware on error. |
|---|
| 1432 | | - ldr r0, =0x80000001 |
|---|
| 1433 | | - ldmfd sp!, {ip, pc} |
|---|
| 1434 | | -ENDPROC(efi_stub_entry) |
|---|
| 1502 | + adr r0, 0f @ switch to our stack |
|---|
| 1503 | + ldr sp, [r0] |
|---|
| 1504 | + add sp, sp, r0 |
|---|
| 1505 | + |
|---|
| 1506 | + mov r5, #0 @ appended DTB size |
|---|
| 1507 | + mov r7, #0xFFFFFFFF @ machine ID |
|---|
| 1508 | + b wont_overwrite |
|---|
| 1509 | +ENDPROC(efi_enter_kernel) |
|---|
| 1510 | +0: .long .L_user_stack_end - . |
|---|
| 1435 | 1511 | #endif |
|---|
| 1436 | 1512 | |
|---|
| 1437 | 1513 | .align |
|---|