1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * linux/arch/arm/boot/compressed/head.S 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 1996-2002 Russell King 6*4882a593Smuzhiyun * Copyright (C) 2004 Hyok S. Choi (MPU support) 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun#include <linux/linkage.h> 9*4882a593Smuzhiyun#include <asm/assembler.h> 10*4882a593Smuzhiyun#include <asm/v7m.h> 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun#include "efi-header.S" 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun AR_CLASS( .arch armv7-a ) 15*4882a593Smuzhiyun M_CLASS( .arch armv7-m ) 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun/* 18*4882a593Smuzhiyun * Debugging stuff 19*4882a593Smuzhiyun * 20*4882a593Smuzhiyun * Note that these macros must not contain any code which is not 21*4882a593Smuzhiyun * 100% relocatable. Any attempt to do so will result in a crash. 22*4882a593Smuzhiyun * Please select one of the following when turning on debugging. 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun#ifdef DEBUG 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun#if defined(CONFIG_DEBUG_ICEDCC) 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) 29*4882a593Smuzhiyun .macro loadsp, rb, tmp1, tmp2 30*4882a593Smuzhiyun .endm 31*4882a593Smuzhiyun .macro writeb, ch, rb, tmp 32*4882a593Smuzhiyun mcr p14, 0, \ch, c0, c5, 0 33*4882a593Smuzhiyun .endm 34*4882a593Smuzhiyun#elif defined(CONFIG_CPU_XSCALE) 35*4882a593Smuzhiyun .macro loadsp, rb, tmp1, tmp2 36*4882a593Smuzhiyun .endm 37*4882a593Smuzhiyun .macro writeb, ch, rb, tmp 38*4882a593Smuzhiyun mcr p14, 0, \ch, c8, c0, 0 39*4882a593Smuzhiyun .endm 40*4882a593Smuzhiyun#else 41*4882a593Smuzhiyun .macro loadsp, rb, tmp1, tmp2 42*4882a593Smuzhiyun .endm 43*4882a593Smuzhiyun .macro writeb, ch, rb, tmp 44*4882a593Smuzhiyun mcr p14, 0, \ch, c1, c0, 0 45*4882a593Smuzhiyun .endm 46*4882a593Smuzhiyun#endif 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun#else 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun#include CONFIG_DEBUG_LL_INCLUDE 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun .macro writeb, ch, rb, tmp 53*4882a593Smuzhiyun#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL 54*4882a593Smuzhiyun waituartcts \tmp, \rb 55*4882a593Smuzhiyun#endif 56*4882a593Smuzhiyun waituarttxrdy \tmp, \rb 57*4882a593Smuzhiyun senduart \ch, \rb 58*4882a593Smuzhiyun busyuart \tmp, \rb 59*4882a593Smuzhiyun .endm 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun#if defined(CONFIG_ARCH_SA1100) 62*4882a593Smuzhiyun .macro loadsp, rb, tmp1, tmp2 63*4882a593Smuzhiyun mov \rb, #0x80000000 @ physical base address 64*4882a593Smuzhiyun#ifdef CONFIG_DEBUG_LL_SER3 65*4882a593Smuzhiyun add \rb, \rb, #0x00050000 @ Ser3 66*4882a593Smuzhiyun#else 67*4882a593Smuzhiyun add \rb, \rb, #0x00010000 @ Ser1 68*4882a593Smuzhiyun#endif 69*4882a593Smuzhiyun .endm 70*4882a593Smuzhiyun#else 71*4882a593Smuzhiyun .macro loadsp, rb, tmp1, tmp2 72*4882a593Smuzhiyun addruart \rb, \tmp1, \tmp2 73*4882a593Smuzhiyun .endm 74*4882a593Smuzhiyun#endif 75*4882a593Smuzhiyun#endif 76*4882a593Smuzhiyun#endif 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun .macro kputc,val 79*4882a593Smuzhiyun mov r0, \val 80*4882a593Smuzhiyun bl putc 81*4882a593Smuzhiyun .endm 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun .macro kphex,val,len 84*4882a593Smuzhiyun mov r0, \val 85*4882a593Smuzhiyun mov r1, #\len 86*4882a593Smuzhiyun bl phex 87*4882a593Smuzhiyun .endm 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun /* 90*4882a593Smuzhiyun * Debug kernel copy by printing the memory addresses involved 91*4882a593Smuzhiyun */ 92*4882a593Smuzhiyun .macro dbgkc, begin, end, cbegin, cend 93*4882a593Smuzhiyun#ifdef DEBUG 94*4882a593Smuzhiyun kputc #'C' 95*4882a593Smuzhiyun kputc #':' 96*4882a593Smuzhiyun kputc #'0' 97*4882a593Smuzhiyun kputc #'x' 98*4882a593Smuzhiyun kphex \begin, 8 /* Start of compressed kernel */ 99*4882a593Smuzhiyun kputc #'-' 100*4882a593Smuzhiyun kputc #'0' 101*4882a593Smuzhiyun kputc #'x' 102*4882a593Smuzhiyun kphex \end, 8 /* End of compressed kernel */ 103*4882a593Smuzhiyun kputc #'-' 104*4882a593Smuzhiyun kputc #'>' 105*4882a593Smuzhiyun kputc #'0' 106*4882a593Smuzhiyun kputc #'x' 107*4882a593Smuzhiyun kphex \cbegin, 8 /* Start of kernel copy */ 108*4882a593Smuzhiyun kputc #'-' 109*4882a593Smuzhiyun kputc #'0' 110*4882a593Smuzhiyun kputc #'x' 111*4882a593Smuzhiyun kphex \cend, 8 /* End of kernel copy */ 112*4882a593Smuzhiyun kputc #'\n' 113*4882a593Smuzhiyun#endif 114*4882a593Smuzhiyun .endm 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun /* 117*4882a593Smuzhiyun * Debug print of the final appended DTB location 118*4882a593Smuzhiyun */ 119*4882a593Smuzhiyun .macro dbgadtb, begin, size 120*4882a593Smuzhiyun#ifdef DEBUG 121*4882a593Smuzhiyun kputc #'D' 122*4882a593Smuzhiyun kputc #'T' 123*4882a593Smuzhiyun kputc #'B' 124*4882a593Smuzhiyun kputc #':' 125*4882a593Smuzhiyun kputc #'0' 126*4882a593Smuzhiyun kputc #'x' 127*4882a593Smuzhiyun kphex \begin, 8 /* Start of appended DTB */ 128*4882a593Smuzhiyun kputc #' ' 129*4882a593Smuzhiyun kputc #'(' 130*4882a593Smuzhiyun kputc #'0' 131*4882a593Smuzhiyun kputc #'x' 132*4882a593Smuzhiyun kphex \size, 8 /* Size of appended DTB */ 133*4882a593Smuzhiyun kputc #')' 134*4882a593Smuzhiyun kputc #'\n' 135*4882a593Smuzhiyun#endif 136*4882a593Smuzhiyun .endm 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun .macro enable_cp15_barriers, reg 139*4882a593Smuzhiyun mrc p15, 0, \reg, c1, c0, 0 @ read SCTLR 140*4882a593Smuzhiyun tst \reg, #(1 << 5) @ CP15BEN bit set? 141*4882a593Smuzhiyun bne .L_\@ 142*4882a593Smuzhiyun orr \reg, \reg, #(1 << 5) @ CP15 barrier instructions 143*4882a593Smuzhiyun mcr p15, 0, \reg, c1, c0, 0 @ write SCTLR 144*4882a593Smuzhiyun ARM( .inst 0xf57ff06f @ v7+ isb ) 145*4882a593Smuzhiyun THUMB( isb ) 146*4882a593Smuzhiyun.L_\@: 147*4882a593Smuzhiyun .endm 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun /* 150*4882a593Smuzhiyun * The kernel build system appends the size of the 151*4882a593Smuzhiyun * decompressed kernel at the end of the compressed data 152*4882a593Smuzhiyun * in little-endian form. 153*4882a593Smuzhiyun */ 154*4882a593Smuzhiyun .macro get_inflated_image_size, res:req, tmp1:req, tmp2:req 155*4882a593Smuzhiyun adr \res, .Linflated_image_size_offset 156*4882a593Smuzhiyun ldr \tmp1, [\res] 157*4882a593Smuzhiyun add \tmp1, \tmp1, \res @ address of inflated image size 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun ldrb \res, [\tmp1] @ get_unaligned_le32 160*4882a593Smuzhiyun ldrb \tmp2, [\tmp1, #1] 161*4882a593Smuzhiyun orr \res, \res, \tmp2, lsl #8 162*4882a593Smuzhiyun ldrb \tmp2, [\tmp1, #2] 163*4882a593Smuzhiyun ldrb \tmp1, [\tmp1, #3] 164*4882a593Smuzhiyun orr \res, \res, \tmp2, lsl #16 165*4882a593Smuzhiyun orr \res, \res, \tmp1, lsl #24 166*4882a593Smuzhiyun .endm 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun .macro be32tocpu, val, tmp 169*4882a593Smuzhiyun#ifndef __ARMEB__ 170*4882a593Smuzhiyun /* convert to little endian */ 171*4882a593Smuzhiyun rev_l \val, \tmp 172*4882a593Smuzhiyun#endif 173*4882a593Smuzhiyun .endm 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun .section ".start", "ax" 176*4882a593Smuzhiyun/* 177*4882a593Smuzhiyun * sort out different calling conventions 178*4882a593Smuzhiyun */ 179*4882a593Smuzhiyun .align 180*4882a593Smuzhiyun /* 181*4882a593Smuzhiyun * Always enter in ARM state for CPUs that support the ARM ISA. 182*4882a593Smuzhiyun * As of today (2014) that's exactly the members of the A and R 183*4882a593Smuzhiyun * classes. 184*4882a593Smuzhiyun */ 185*4882a593Smuzhiyun AR_CLASS( .arm ) 186*4882a593Smuzhiyunstart: 187*4882a593Smuzhiyun .type start,#function 188*4882a593Smuzhiyun /* 189*4882a593Smuzhiyun * These 7 nops along with the 1 nop immediately below for 190*4882a593Smuzhiyun * !THUMB2 form 8 nops that make the compressed kernel bootable 191*4882a593Smuzhiyun * on legacy ARM systems that were assuming the kernel in a.out 192*4882a593Smuzhiyun * binary format. The boot loaders on these systems would 193*4882a593Smuzhiyun * jump 32 bytes into the image to skip the a.out header. 194*4882a593Smuzhiyun * with these 8 nops filling exactly 32 bytes, things still 195*4882a593Smuzhiyun * work as expected on these legacy systems. Thumb2 mode keeps 196*4882a593Smuzhiyun * 7 of the nops as it turns out that some boot loaders 197*4882a593Smuzhiyun * were patching the initial instructions of the kernel, i.e 198*4882a593Smuzhiyun * had started to exploit this "patch area". 199*4882a593Smuzhiyun */ 200*4882a593Smuzhiyun __initial_nops 201*4882a593Smuzhiyun .rept 5 202*4882a593Smuzhiyun __nop 203*4882a593Smuzhiyun .endr 204*4882a593Smuzhiyun#ifndef CONFIG_THUMB2_KERNEL 205*4882a593Smuzhiyun __nop 206*4882a593Smuzhiyun#else 207*4882a593Smuzhiyun AR_CLASS( sub pc, pc, #3 ) @ A/R: switch to Thumb2 mode 208*4882a593Smuzhiyun M_CLASS( nop.w ) @ M: already in Thumb2 mode 209*4882a593Smuzhiyun .thumb 210*4882a593Smuzhiyun#endif 211*4882a593Smuzhiyun W(b) 1f 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun .word _magic_sig @ Magic numbers to help the loader 214*4882a593Smuzhiyun .word _magic_start @ absolute load/run zImage address 215*4882a593Smuzhiyun .word _magic_end @ zImage end address 216*4882a593Smuzhiyun .word 0x04030201 @ endianness flag 217*4882a593Smuzhiyun .word 0x45454545 @ another magic number to indicate 218*4882a593Smuzhiyun .word _magic_table @ additional data table 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun __EFI_HEADER 221*4882a593Smuzhiyun1: 222*4882a593Smuzhiyun ARM_BE8( setend be ) @ go BE8 if compiled for BE8 223*4882a593Smuzhiyun AR_CLASS( mrs r9, cpsr ) 224*4882a593Smuzhiyun#ifdef CONFIG_ARM_VIRT_EXT 225*4882a593Smuzhiyun bl __hyp_stub_install @ get into SVC mode, reversibly 226*4882a593Smuzhiyun#endif 227*4882a593Smuzhiyun mov r7, r1 @ save architecture ID 228*4882a593Smuzhiyun mov r8, r2 @ save atags pointer 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun#ifndef CONFIG_CPU_V7M 231*4882a593Smuzhiyun /* 232*4882a593Smuzhiyun * Booting from Angel - need to enter SVC mode and disable 233*4882a593Smuzhiyun * FIQs/IRQs (numeric definitions from angel arm.h source). 234*4882a593Smuzhiyun * We only do this if we were in user mode on entry. 235*4882a593Smuzhiyun */ 236*4882a593Smuzhiyun mrs r2, cpsr @ get current mode 237*4882a593Smuzhiyun tst r2, #3 @ not user? 238*4882a593Smuzhiyun bne not_angel 239*4882a593Smuzhiyun mov r0, #0x17 @ angel_SWIreason_EnterSVC 240*4882a593Smuzhiyun ARM( swi 0x123456 ) @ angel_SWI_ARM 241*4882a593Smuzhiyun THUMB( svc 0xab ) @ angel_SWI_THUMB 242*4882a593Smuzhiyunnot_angel: 243*4882a593Smuzhiyun safe_svcmode_maskall r0 244*4882a593Smuzhiyun msr spsr_cxsf, r9 @ Save the CPU boot mode in 245*4882a593Smuzhiyun @ SPSR 246*4882a593Smuzhiyun#endif 247*4882a593Smuzhiyun /* 248*4882a593Smuzhiyun * Note that some cache flushing and other stuff may 249*4882a593Smuzhiyun * be needed here - is there an Angel SWI call for this? 250*4882a593Smuzhiyun */ 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun /* 253*4882a593Smuzhiyun * some architecture specific code can be inserted 254*4882a593Smuzhiyun * by the linker here, but it should preserve r7, r8, and r9. 255*4882a593Smuzhiyun */ 256*4882a593Smuzhiyun 257*4882a593Smuzhiyun .text 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun#ifdef CONFIG_AUTO_ZRELADDR 260*4882a593Smuzhiyun /* 261*4882a593Smuzhiyun * Find the start of physical memory. As we are executing 262*4882a593Smuzhiyun * without the MMU on, we are in the physical address space. 263*4882a593Smuzhiyun * We just need to get rid of any offset by aligning the 264*4882a593Smuzhiyun * address. 265*4882a593Smuzhiyun * 266*4882a593Smuzhiyun * This alignment is a balance between the requirements of 267*4882a593Smuzhiyun * different platforms - we have chosen 128MB to allow 268*4882a593Smuzhiyun * platforms which align the start of their physical memory 269*4882a593Smuzhiyun * to 128MB to use this feature, while allowing the zImage 270*4882a593Smuzhiyun * to be placed within the first 128MB of memory on other 271*4882a593Smuzhiyun * platforms. Increasing the alignment means we place 272*4882a593Smuzhiyun * stricter alignment requirements on the start of physical 273*4882a593Smuzhiyun * memory, but relaxing it means that we break people who 274*4882a593Smuzhiyun * are already placing their zImage in (eg) the top 64MB 275*4882a593Smuzhiyun * of this range. 276*4882a593Smuzhiyun */ 277*4882a593Smuzhiyun mov r4, pc 278*4882a593Smuzhiyun and r4, r4, #0xf8000000 279*4882a593Smuzhiyun /* Determine final kernel image address. */ 280*4882a593Smuzhiyun add r4, r4, #(TEXT_OFFSET & 0xffff0000) 281*4882a593Smuzhiyun add r4, r4, #(TEXT_OFFSET & 0x0000ffff) 282*4882a593Smuzhiyun#else 283*4882a593Smuzhiyun ldr r4, =zreladdr 284*4882a593Smuzhiyun#endif 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun /* 287*4882a593Smuzhiyun * Set up a page table only if it won't overwrite ourself. 288*4882a593Smuzhiyun * That means r4 < pc || r4 - 16k page directory > &_end. 289*4882a593Smuzhiyun * Given that r4 > &_end is most unfrequent, we add a rough 290*4882a593Smuzhiyun * additional 1MB of room for a possible appended DTB. 291*4882a593Smuzhiyun */ 292*4882a593Smuzhiyun mov r0, pc 293*4882a593Smuzhiyun cmp r0, r4 294*4882a593Smuzhiyun ldrcc r0, .Lheadroom 295*4882a593Smuzhiyun addcc r0, r0, pc 296*4882a593Smuzhiyun cmpcc r4, r0 297*4882a593Smuzhiyun orrcc r4, r4, #1 @ remember we skipped cache_on 298*4882a593Smuzhiyun blcs cache_on 299*4882a593Smuzhiyun 300*4882a593Smuzhiyunrestart: adr r0, LC1 301*4882a593Smuzhiyun ldr sp, [r0] 302*4882a593Smuzhiyun ldr r6, [r0, #4] 303*4882a593Smuzhiyun add sp, sp, r0 304*4882a593Smuzhiyun add r6, r6, r0 305*4882a593Smuzhiyun 306*4882a593Smuzhiyun get_inflated_image_size r9, r10, lr 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun#ifndef CONFIG_ZBOOT_ROM 309*4882a593Smuzhiyun /* malloc space is above the relocated stack (64k max) */ 310*4882a593Smuzhiyun add r10, sp, #MALLOC_SIZE 311*4882a593Smuzhiyun#else 312*4882a593Smuzhiyun /* 313*4882a593Smuzhiyun * With ZBOOT_ROM the bss/stack is non relocatable, 314*4882a593Smuzhiyun * but someone could still run this code from RAM, 315*4882a593Smuzhiyun * in which case our reference is _edata. 316*4882a593Smuzhiyun */ 317*4882a593Smuzhiyun mov r10, r6 318*4882a593Smuzhiyun#endif 319*4882a593Smuzhiyun 320*4882a593Smuzhiyun mov r5, #0 @ init dtb size to 0 321*4882a593Smuzhiyun#ifdef CONFIG_ARM_APPENDED_DTB 322*4882a593Smuzhiyun/* 323*4882a593Smuzhiyun * r4 = final kernel address (possibly with LSB set) 324*4882a593Smuzhiyun * r5 = appended dtb size (still unknown) 325*4882a593Smuzhiyun * r6 = _edata 326*4882a593Smuzhiyun * r7 = architecture ID 327*4882a593Smuzhiyun * r8 = atags/device tree pointer 328*4882a593Smuzhiyun * r9 = size of decompressed image 329*4882a593Smuzhiyun * r10 = end of this image, including bss/stack/malloc space if non XIP 330*4882a593Smuzhiyun * sp = stack pointer 331*4882a593Smuzhiyun * 332*4882a593Smuzhiyun * if there are device trees (dtb) appended to zImage, advance r10 so that the 333*4882a593Smuzhiyun * dtb data will get relocated along with the kernel if necessary. 334*4882a593Smuzhiyun */ 335*4882a593Smuzhiyun 336*4882a593Smuzhiyun ldr lr, [r6, #0] 337*4882a593Smuzhiyun#ifndef __ARMEB__ 338*4882a593Smuzhiyun ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian 339*4882a593Smuzhiyun#else 340*4882a593Smuzhiyun ldr r1, =0xd00dfeed 341*4882a593Smuzhiyun#endif 342*4882a593Smuzhiyun cmp lr, r1 343*4882a593Smuzhiyun bne dtb_check_done @ not found 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun#ifdef CONFIG_ARM_ATAG_DTB_COMPAT 346*4882a593Smuzhiyun /* 347*4882a593Smuzhiyun * OK... Let's do some funky business here. 348*4882a593Smuzhiyun * If we do have a DTB appended to zImage, and we do have 349*4882a593Smuzhiyun * an ATAG list around, we want the later to be translated 350*4882a593Smuzhiyun * and folded into the former here. No GOT fixup has occurred 351*4882a593Smuzhiyun * yet, but none of the code we're about to call uses any 352*4882a593Smuzhiyun * global variable. 353*4882a593Smuzhiyun */ 354*4882a593Smuzhiyun 355*4882a593Smuzhiyun /* Get the initial DTB size */ 356*4882a593Smuzhiyun ldr r5, [r6, #4] 357*4882a593Smuzhiyun be32tocpu r5, r1 358*4882a593Smuzhiyun dbgadtb r6, r5 359*4882a593Smuzhiyun /* 50% DTB growth should be good enough */ 360*4882a593Smuzhiyun add r5, r5, r5, lsr #1 361*4882a593Smuzhiyun /* preserve 64-bit alignment */ 362*4882a593Smuzhiyun add r5, r5, #7 363*4882a593Smuzhiyun bic r5, r5, #7 364*4882a593Smuzhiyun /* clamp to 32KB min and 1MB max */ 365*4882a593Smuzhiyun cmp r5, #(1 << 15) 366*4882a593Smuzhiyun movlo r5, #(1 << 15) 367*4882a593Smuzhiyun cmp r5, #(1 << 20) 368*4882a593Smuzhiyun movhi r5, #(1 << 20) 369*4882a593Smuzhiyun /* temporarily relocate the stack past the DTB work space */ 370*4882a593Smuzhiyun add sp, sp, r5 371*4882a593Smuzhiyun 372*4882a593Smuzhiyun mov r0, r8 373*4882a593Smuzhiyun mov r1, r6 374*4882a593Smuzhiyun mov r2, r5 375*4882a593Smuzhiyun bl atags_to_fdt 376*4882a593Smuzhiyun 377*4882a593Smuzhiyun /* 378*4882a593Smuzhiyun * If returned value is 1, there is no ATAG at the location 379*4882a593Smuzhiyun * pointed by r8. Try the typical 0x100 offset from start 380*4882a593Smuzhiyun * of RAM and hope for the best. 381*4882a593Smuzhiyun */ 382*4882a593Smuzhiyun cmp r0, #1 383*4882a593Smuzhiyun sub r0, r4, #(TEXT_OFFSET & 0xffff0000) 384*4882a593Smuzhiyun sub r0, r0, #(TEXT_OFFSET & 0x0000ffff) 385*4882a593Smuzhiyun bic r0, r0, #1 386*4882a593Smuzhiyun add r0, r0, #0x100 387*4882a593Smuzhiyun mov r1, r6 388*4882a593Smuzhiyun mov r2, r5 389*4882a593Smuzhiyun bleq atags_to_fdt 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun sub sp, sp, r5 392*4882a593Smuzhiyun#endif 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun mov r8, r6 @ use the appended device tree 395*4882a593Smuzhiyun 396*4882a593Smuzhiyun /* 397*4882a593Smuzhiyun * Make sure that the DTB doesn't end up in the final 398*4882a593Smuzhiyun * kernel's .bss area. To do so, we adjust the decompressed 399*4882a593Smuzhiyun * kernel size to compensate if that .bss size is larger 400*4882a593Smuzhiyun * than the relocated code. 401*4882a593Smuzhiyun */ 402*4882a593Smuzhiyun ldr r5, =_kernel_bss_size 403*4882a593Smuzhiyun adr r1, wont_overwrite 404*4882a593Smuzhiyun sub r1, r6, r1 405*4882a593Smuzhiyun subs r1, r5, r1 406*4882a593Smuzhiyun addhi r9, r9, r1 407*4882a593Smuzhiyun 408*4882a593Smuzhiyun /* Get the current DTB size */ 409*4882a593Smuzhiyun ldr r5, [r6, #4] 410*4882a593Smuzhiyun be32tocpu r5, r1 411*4882a593Smuzhiyun 412*4882a593Smuzhiyun /* preserve 64-bit alignment */ 413*4882a593Smuzhiyun add r5, r5, #7 414*4882a593Smuzhiyun bic r5, r5, #7 415*4882a593Smuzhiyun 416*4882a593Smuzhiyun /* relocate some pointers past the appended dtb */ 417*4882a593Smuzhiyun add r6, r6, r5 418*4882a593Smuzhiyun add r10, r10, r5 419*4882a593Smuzhiyun add sp, sp, r5 420*4882a593Smuzhiyundtb_check_done: 421*4882a593Smuzhiyun#endif 422*4882a593Smuzhiyun 423*4882a593Smuzhiyun/* 424*4882a593Smuzhiyun * Check to see if we will overwrite ourselves. 425*4882a593Smuzhiyun * r4 = final kernel address (possibly with LSB set) 426*4882a593Smuzhiyun * r9 = size of decompressed image 427*4882a593Smuzhiyun * r10 = end of this image, including bss/stack/malloc space if non XIP 428*4882a593Smuzhiyun * We basically want: 429*4882a593Smuzhiyun * r4 - 16k page directory >= r10 -> OK 430*4882a593Smuzhiyun * r4 + image length <= address of wont_overwrite -> OK 431*4882a593Smuzhiyun * Note: the possible LSB in r4 is harmless here. 432*4882a593Smuzhiyun */ 433*4882a593Smuzhiyun add r10, r10, #16384 434*4882a593Smuzhiyun cmp r4, r10 435*4882a593Smuzhiyun bhs wont_overwrite 436*4882a593Smuzhiyun add r10, r4, r9 437*4882a593Smuzhiyun adr r9, wont_overwrite 438*4882a593Smuzhiyun cmp r10, r9 439*4882a593Smuzhiyun bls wont_overwrite 440*4882a593Smuzhiyun 441*4882a593Smuzhiyun/* 442*4882a593Smuzhiyun * Relocate ourselves past the end of the decompressed kernel. 443*4882a593Smuzhiyun * r6 = _edata 444*4882a593Smuzhiyun * r10 = end of the decompressed kernel 445*4882a593Smuzhiyun * Because we always copy ahead, we need to do it from the end and go 446*4882a593Smuzhiyun * backward in case the source and destination overlap. 447*4882a593Smuzhiyun */ 448*4882a593Smuzhiyun /* 449*4882a593Smuzhiyun * Bump to the next 256-byte boundary with the size of 450*4882a593Smuzhiyun * the relocation code added. This avoids overwriting 451*4882a593Smuzhiyun * ourself when the offset is small. 452*4882a593Smuzhiyun */ 453*4882a593Smuzhiyun add r10, r10, #((reloc_code_end - restart + 256) & ~255) 454*4882a593Smuzhiyun bic r10, r10, #255 455*4882a593Smuzhiyun 456*4882a593Smuzhiyun /* Get start of code we want to copy and align it down. */ 457*4882a593Smuzhiyun adr r5, restart 458*4882a593Smuzhiyun bic r5, r5, #31 459*4882a593Smuzhiyun 460*4882a593Smuzhiyun/* Relocate the hyp vector base if necessary */ 461*4882a593Smuzhiyun#ifdef CONFIG_ARM_VIRT_EXT 462*4882a593Smuzhiyun mrs r0, spsr 463*4882a593Smuzhiyun and r0, r0, #MODE_MASK 464*4882a593Smuzhiyun cmp r0, #HYP_MODE 465*4882a593Smuzhiyun bne 1f 466*4882a593Smuzhiyun 467*4882a593Smuzhiyun /* 468*4882a593Smuzhiyun * Compute the address of the hyp vectors after relocation. 469*4882a593Smuzhiyun * This requires some arithmetic since we cannot directly 470*4882a593Smuzhiyun * reference __hyp_stub_vectors in a PC-relative way. 471*4882a593Smuzhiyun * Call __hyp_set_vectors with the new address so that we 472*4882a593Smuzhiyun * can HVC again after the copy. 473*4882a593Smuzhiyun */ 474*4882a593Smuzhiyun0: adr r0, 0b 475*4882a593Smuzhiyun movw r1, #:lower16:__hyp_stub_vectors - 0b 476*4882a593Smuzhiyun movt r1, #:upper16:__hyp_stub_vectors - 0b 477*4882a593Smuzhiyun add r0, r0, r1 478*4882a593Smuzhiyun sub r0, r0, r5 479*4882a593Smuzhiyun add r0, r0, r10 480*4882a593Smuzhiyun bl __hyp_set_vectors 481*4882a593Smuzhiyun1: 482*4882a593Smuzhiyun#endif 483*4882a593Smuzhiyun 484*4882a593Smuzhiyun sub r9, r6, r5 @ size to copy 485*4882a593Smuzhiyun add r9, r9, #31 @ rounded up to a multiple 486*4882a593Smuzhiyun bic r9, r9, #31 @ ... of 32 bytes 487*4882a593Smuzhiyun add r6, r9, r5 488*4882a593Smuzhiyun add r9, r9, r10 489*4882a593Smuzhiyun 490*4882a593Smuzhiyun#ifdef DEBUG 491*4882a593Smuzhiyun sub r10, r6, r5 492*4882a593Smuzhiyun sub r10, r9, r10 493*4882a593Smuzhiyun /* 494*4882a593Smuzhiyun * We are about to copy the kernel to a new memory area. 495*4882a593Smuzhiyun * The boundaries of the new memory area can be found in 496*4882a593Smuzhiyun * r10 and r9, whilst r5 and r6 contain the boundaries 497*4882a593Smuzhiyun * of the memory we are going to copy. 498*4882a593Smuzhiyun * Calling dbgkc will help with the printing of this 499*4882a593Smuzhiyun * information. 500*4882a593Smuzhiyun */ 501*4882a593Smuzhiyun dbgkc r5, r6, r10, r9 502*4882a593Smuzhiyun#endif 503*4882a593Smuzhiyun 504*4882a593Smuzhiyun1: ldmdb r6!, {r0 - r3, r10 - r12, lr} 505*4882a593Smuzhiyun cmp r6, r5 506*4882a593Smuzhiyun stmdb r9!, {r0 - r3, r10 - r12, lr} 507*4882a593Smuzhiyun bhi 1b 508*4882a593Smuzhiyun 509*4882a593Smuzhiyun /* Preserve offset to relocated code. */ 510*4882a593Smuzhiyun sub r6, r9, r6 511*4882a593Smuzhiyun 512*4882a593Smuzhiyun mov r0, r9 @ start of relocated zImage 513*4882a593Smuzhiyun add r1, sp, r6 @ end of relocated zImage 514*4882a593Smuzhiyun bl cache_clean_flush 515*4882a593Smuzhiyun 516*4882a593Smuzhiyun badr r0, restart 517*4882a593Smuzhiyun add r0, r0, r6 518*4882a593Smuzhiyun mov pc, r0 519*4882a593Smuzhiyun 520*4882a593Smuzhiyunwont_overwrite: 521*4882a593Smuzhiyun adr r0, LC0 522*4882a593Smuzhiyun ldmia r0, {r1, r2, r3, r11, r12} 523*4882a593Smuzhiyun sub r0, r0, r1 @ calculate the delta offset 524*4882a593Smuzhiyun 525*4882a593Smuzhiyun/* 526*4882a593Smuzhiyun * If delta is zero, we are running at the address we were linked at. 527*4882a593Smuzhiyun * r0 = delta 528*4882a593Smuzhiyun * r2 = BSS start 529*4882a593Smuzhiyun * r3 = BSS end 530*4882a593Smuzhiyun * r4 = kernel execution address (possibly with LSB set) 531*4882a593Smuzhiyun * r5 = appended dtb size (0 if not present) 532*4882a593Smuzhiyun * r7 = architecture ID 533*4882a593Smuzhiyun * r8 = atags pointer 534*4882a593Smuzhiyun * r11 = GOT start 535*4882a593Smuzhiyun * r12 = GOT end 536*4882a593Smuzhiyun * sp = stack pointer 537*4882a593Smuzhiyun */ 538*4882a593Smuzhiyun orrs r1, r0, r5 539*4882a593Smuzhiyun beq not_relocated 540*4882a593Smuzhiyun 541*4882a593Smuzhiyun add r11, r11, r0 542*4882a593Smuzhiyun add r12, r12, r0 543*4882a593Smuzhiyun 544*4882a593Smuzhiyun#ifndef CONFIG_ZBOOT_ROM 545*4882a593Smuzhiyun /* 546*4882a593Smuzhiyun * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, 547*4882a593Smuzhiyun * we need to fix up pointers into the BSS region. 548*4882a593Smuzhiyun * Note that the stack pointer has already been fixed up. 549*4882a593Smuzhiyun */ 550*4882a593Smuzhiyun add r2, r2, r0 551*4882a593Smuzhiyun add r3, r3, r0 552*4882a593Smuzhiyun 553*4882a593Smuzhiyun /* 554*4882a593Smuzhiyun * Relocate all entries in the GOT table. 555*4882a593Smuzhiyun * Bump bss entries to _edata + dtb size 556*4882a593Smuzhiyun */ 557*4882a593Smuzhiyun1: ldr r1, [r11, #0] @ relocate entries in the GOT 558*4882a593Smuzhiyun add r1, r1, r0 @ This fixes up C references 559*4882a593Smuzhiyun cmp r1, r2 @ if entry >= bss_start && 560*4882a593Smuzhiyun cmphs r3, r1 @ bss_end > entry 561*4882a593Smuzhiyun addhi r1, r1, r5 @ entry += dtb size 562*4882a593Smuzhiyun str r1, [r11], #4 @ next entry 563*4882a593Smuzhiyun cmp r11, r12 564*4882a593Smuzhiyun blo 1b 565*4882a593Smuzhiyun 566*4882a593Smuzhiyun /* bump our bss pointers too */ 567*4882a593Smuzhiyun add r2, r2, r5 568*4882a593Smuzhiyun add r3, r3, r5 569*4882a593Smuzhiyun 570*4882a593Smuzhiyun#else 571*4882a593Smuzhiyun 572*4882a593Smuzhiyun /* 573*4882a593Smuzhiyun * Relocate entries in the GOT table. We only relocate 574*4882a593Smuzhiyun * the entries that are outside the (relocated) BSS region. 575*4882a593Smuzhiyun */ 576*4882a593Smuzhiyun1: ldr r1, [r11, #0] @ relocate entries in the GOT 577*4882a593Smuzhiyun cmp r1, r2 @ entry < bss_start || 578*4882a593Smuzhiyun cmphs r3, r1 @ _end < entry 579*4882a593Smuzhiyun addlo r1, r1, r0 @ table. This fixes up the 580*4882a593Smuzhiyun str r1, [r11], #4 @ C references. 581*4882a593Smuzhiyun cmp r11, r12 582*4882a593Smuzhiyun blo 1b 583*4882a593Smuzhiyun#endif 584*4882a593Smuzhiyun 585*4882a593Smuzhiyunnot_relocated: mov r0, #0 586*4882a593Smuzhiyun1: str r0, [r2], #4 @ clear bss 587*4882a593Smuzhiyun str r0, [r2], #4 588*4882a593Smuzhiyun str r0, [r2], #4 589*4882a593Smuzhiyun str r0, [r2], #4 590*4882a593Smuzhiyun cmp r2, r3 591*4882a593Smuzhiyun blo 1b 592*4882a593Smuzhiyun 593*4882a593Smuzhiyun /* 594*4882a593Smuzhiyun * Did we skip the cache setup earlier? 595*4882a593Smuzhiyun * That is indicated by the LSB in r4. 596*4882a593Smuzhiyun * Do it now if so. 597*4882a593Smuzhiyun */ 598*4882a593Smuzhiyun tst r4, #1 599*4882a593Smuzhiyun bic r4, r4, #1 600*4882a593Smuzhiyun blne cache_on 601*4882a593Smuzhiyun 602*4882a593Smuzhiyun/* 603*4882a593Smuzhiyun * The C runtime environment should now be setup sufficiently. 604*4882a593Smuzhiyun * Set up some pointers, and start decompressing. 605*4882a593Smuzhiyun * r4 = kernel execution address 606*4882a593Smuzhiyun * r7 = architecture ID 607*4882a593Smuzhiyun * r8 = atags pointer 608*4882a593Smuzhiyun */ 609*4882a593Smuzhiyun mov r0, r4 610*4882a593Smuzhiyun mov r1, sp @ malloc space above stack 611*4882a593Smuzhiyun add r2, sp, #MALLOC_SIZE @ 64k max 612*4882a593Smuzhiyun mov r3, r7 613*4882a593Smuzhiyun bl decompress_kernel 614*4882a593Smuzhiyun 615*4882a593Smuzhiyun get_inflated_image_size r1, r2, r3 616*4882a593Smuzhiyun 617*4882a593Smuzhiyun mov r0, r4 @ start of inflated image 618*4882a593Smuzhiyun add r1, r1, r0 @ end of inflated image 619*4882a593Smuzhiyun bl cache_clean_flush 620*4882a593Smuzhiyun bl cache_off 621*4882a593Smuzhiyun 622*4882a593Smuzhiyun#ifdef CONFIG_ARM_VIRT_EXT 623*4882a593Smuzhiyun mrs r0, spsr @ Get saved CPU boot mode 624*4882a593Smuzhiyun and r0, r0, #MODE_MASK 625*4882a593Smuzhiyun cmp r0, #HYP_MODE @ if not booted in HYP mode... 626*4882a593Smuzhiyun bne __enter_kernel @ boot kernel directly 627*4882a593Smuzhiyun 628*4882a593Smuzhiyun adr r12, .L__hyp_reentry_vectors_offset 629*4882a593Smuzhiyun ldr r0, [r12] 630*4882a593Smuzhiyun add r0, r0, r12 631*4882a593Smuzhiyun 632*4882a593Smuzhiyun bl __hyp_set_vectors 633*4882a593Smuzhiyun __HVC(0) @ otherwise bounce to hyp mode 634*4882a593Smuzhiyun 635*4882a593Smuzhiyun b . @ should never be reached 636*4882a593Smuzhiyun 637*4882a593Smuzhiyun .align 2 638*4882a593Smuzhiyun.L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - . 639*4882a593Smuzhiyun#else 640*4882a593Smuzhiyun b __enter_kernel 641*4882a593Smuzhiyun#endif 642*4882a593Smuzhiyun 643*4882a593Smuzhiyun .align 2 644*4882a593Smuzhiyun .type LC0, #object 645*4882a593SmuzhiyunLC0: .word LC0 @ r1 646*4882a593Smuzhiyun .word __bss_start @ r2 647*4882a593Smuzhiyun .word _end @ r3 648*4882a593Smuzhiyun .word _got_start @ r11 649*4882a593Smuzhiyun .word _got_end @ ip 650*4882a593Smuzhiyun .size LC0, . - LC0 651*4882a593Smuzhiyun 652*4882a593Smuzhiyun .type LC1, #object 653*4882a593SmuzhiyunLC1: .word .L_user_stack_end - LC1 @ sp 654*4882a593Smuzhiyun .word _edata - LC1 @ r6 655*4882a593Smuzhiyun .size LC1, . - LC1 656*4882a593Smuzhiyun 657*4882a593Smuzhiyun.Lheadroom: 658*4882a593Smuzhiyun .word _end - restart + 16384 + 1024*1024 659*4882a593Smuzhiyun 660*4882a593Smuzhiyun.Linflated_image_size_offset: 661*4882a593Smuzhiyun .long (input_data_end - 4) - . 662*4882a593Smuzhiyun 663*4882a593Smuzhiyun#ifdef CONFIG_ARCH_RPC 664*4882a593Smuzhiyun .globl params 665*4882a593Smuzhiyunparams: ldr r0, =0x10000100 @ params_phys for RPC 666*4882a593Smuzhiyun mov pc, lr 667*4882a593Smuzhiyun .ltorg 668*4882a593Smuzhiyun .align 669*4882a593Smuzhiyun#endif 670*4882a593Smuzhiyun 671*4882a593Smuzhiyun/* 672*4882a593Smuzhiyun * dcache_line_size - get the minimum D-cache line size from the CTR register 673*4882a593Smuzhiyun * on ARMv7. 674*4882a593Smuzhiyun */ 675*4882a593Smuzhiyun .macro dcache_line_size, reg, tmp 676*4882a593Smuzhiyun#ifdef CONFIG_CPU_V7M 677*4882a593Smuzhiyun movw \tmp, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_CTR 678*4882a593Smuzhiyun movt \tmp, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_CTR 679*4882a593Smuzhiyun ldr \tmp, [\tmp] 680*4882a593Smuzhiyun#else 681*4882a593Smuzhiyun mrc p15, 0, \tmp, c0, c0, 1 @ read ctr 682*4882a593Smuzhiyun#endif 683*4882a593Smuzhiyun lsr \tmp, \tmp, #16 684*4882a593Smuzhiyun and \tmp, \tmp, #0xf @ cache line size encoding 685*4882a593Smuzhiyun mov \reg, #4 @ bytes per word 686*4882a593Smuzhiyun mov \reg, \reg, lsl \tmp @ actual cache line size 687*4882a593Smuzhiyun .endm 688*4882a593Smuzhiyun 689*4882a593Smuzhiyun/* 690*4882a593Smuzhiyun * Turn on the cache. We need to setup some page tables so that we 691*4882a593Smuzhiyun * can have both the I and D caches on. 692*4882a593Smuzhiyun * 693*4882a593Smuzhiyun * We place the page tables 16k down from the kernel execution address, 694*4882a593Smuzhiyun * and we hope that nothing else is using it. If we're using it, we 695*4882a593Smuzhiyun * will go pop! 696*4882a593Smuzhiyun * 697*4882a593Smuzhiyun * On entry, 698*4882a593Smuzhiyun * r4 = kernel execution address 699*4882a593Smuzhiyun * r7 = architecture number 700*4882a593Smuzhiyun * r8 = atags pointer 701*4882a593Smuzhiyun * On exit, 702*4882a593Smuzhiyun * r0, r1, r2, r3, r9, r10, r12 corrupted 703*4882a593Smuzhiyun * This routine must preserve: 704*4882a593Smuzhiyun * r4, r7, r8 705*4882a593Smuzhiyun */ 706*4882a593Smuzhiyun .align 5 707*4882a593Smuzhiyuncache_on: mov r3, #8 @ cache_on function 708*4882a593Smuzhiyun b call_cache_fn 709*4882a593Smuzhiyun 710*4882a593Smuzhiyun/* 711*4882a593Smuzhiyun * Initialize the highest priority protection region, PR7 712*4882a593Smuzhiyun * to cover all 32bit address and cacheable and bufferable. 713*4882a593Smuzhiyun */ 714*4882a593Smuzhiyun__armv4_mpu_cache_on: 715*4882a593Smuzhiyun mov r0, #0x3f @ 4G, the whole 716*4882a593Smuzhiyun mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting 717*4882a593Smuzhiyun mcr p15, 0, r0, c6, c7, 1 718*4882a593Smuzhiyun 719*4882a593Smuzhiyun mov r0, #0x80 @ PR7 720*4882a593Smuzhiyun mcr p15, 0, r0, c2, c0, 0 @ D-cache on 721*4882a593Smuzhiyun mcr p15, 0, r0, c2, c0, 1 @ I-cache on 722*4882a593Smuzhiyun mcr p15, 0, r0, c3, c0, 0 @ write-buffer on 723*4882a593Smuzhiyun 724*4882a593Smuzhiyun mov r0, #0xc000 725*4882a593Smuzhiyun mcr p15, 0, r0, c5, c0, 1 @ I-access permission 726*4882a593Smuzhiyun mcr p15, 0, r0, c5, c0, 0 @ D-access permission 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun mov r0, #0 729*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 730*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache 731*4882a593Smuzhiyun mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache 732*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read control reg 733*4882a593Smuzhiyun @ ...I .... ..D. WC.M 734*4882a593Smuzhiyun orr r0, r0, #0x002d @ .... .... ..1. 11.1 735*4882a593Smuzhiyun orr r0, r0, #0x1000 @ ...1 .... .... .... 736*4882a593Smuzhiyun 737*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0, 0 @ write control reg 738*4882a593Smuzhiyun 739*4882a593Smuzhiyun mov r0, #0 740*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache 741*4882a593Smuzhiyun mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache 742*4882a593Smuzhiyun mov pc, lr 743*4882a593Smuzhiyun 744*4882a593Smuzhiyun__armv3_mpu_cache_on: 745*4882a593Smuzhiyun mov r0, #0x3f @ 4G, the whole 746*4882a593Smuzhiyun mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting 747*4882a593Smuzhiyun 748*4882a593Smuzhiyun mov r0, #0x80 @ PR7 749*4882a593Smuzhiyun mcr p15, 0, r0, c2, c0, 0 @ cache on 750*4882a593Smuzhiyun mcr p15, 0, r0, c3, c0, 0 @ write-buffer on 751*4882a593Smuzhiyun 752*4882a593Smuzhiyun mov r0, #0xc000 753*4882a593Smuzhiyun mcr p15, 0, r0, c5, c0, 0 @ access permission 754*4882a593Smuzhiyun 755*4882a593Smuzhiyun mov r0, #0 756*4882a593Smuzhiyun mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 757*4882a593Smuzhiyun /* 758*4882a593Smuzhiyun * ?? ARMv3 MMU does not allow reading the control register, 759*4882a593Smuzhiyun * does this really work on ARMv3 MPU? 760*4882a593Smuzhiyun */ 761*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read control reg 762*4882a593Smuzhiyun @ .... .... .... WC.M 763*4882a593Smuzhiyun orr r0, r0, #0x000d @ .... .... .... 11.1 764*4882a593Smuzhiyun /* ?? this overwrites the value constructed above? */ 765*4882a593Smuzhiyun mov r0, #0 766*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0, 0 @ write control reg 767*4882a593Smuzhiyun 768*4882a593Smuzhiyun /* ?? invalidate for the second time? */ 769*4882a593Smuzhiyun mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 770*4882a593Smuzhiyun mov pc, lr 771*4882a593Smuzhiyun 772*4882a593Smuzhiyun#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 773*4882a593Smuzhiyun#define CB_BITS 0x08 774*4882a593Smuzhiyun#else 775*4882a593Smuzhiyun#define CB_BITS 0x0c 776*4882a593Smuzhiyun#endif 777*4882a593Smuzhiyun 778*4882a593Smuzhiyun__setup_mmu: sub r3, r4, #16384 @ Page directory size 779*4882a593Smuzhiyun bic r3, r3, #0xff @ Align the pointer 780*4882a593Smuzhiyun bic r3, r3, #0x3f00 781*4882a593Smuzhiyun/* 782*4882a593Smuzhiyun * Initialise the page tables, turning on the cacheable and bufferable 783*4882a593Smuzhiyun * bits for the RAM area only. 784*4882a593Smuzhiyun */ 785*4882a593Smuzhiyun mov r0, r3 786*4882a593Smuzhiyun mov r9, r0, lsr #20 787*4882a593Smuzhiyun mov r9, r9, lsl #20 @ start of RAM 788*4882a593Smuzhiyun add r10, r9, #0x10000000 @ a reasonable RAM size 789*4882a593Smuzhiyun mov r1, #0x12 @ XN|U + section mapping 790*4882a593Smuzhiyun orr r1, r1, #3 << 10 @ AP=11 791*4882a593Smuzhiyun add r2, r3, #16384 792*4882a593Smuzhiyun1: cmp r1, r9 @ if virt > start of RAM 793*4882a593Smuzhiyun cmphs r10, r1 @ && end of RAM > virt 794*4882a593Smuzhiyun bic r1, r1, #0x1c @ clear XN|U + C + B 795*4882a593Smuzhiyun orrlo r1, r1, #0x10 @ Set XN|U for non-RAM 796*4882a593Smuzhiyun orrhs r1, r1, r6 @ set RAM section settings 797*4882a593Smuzhiyun str r1, [r0], #4 @ 1:1 mapping 798*4882a593Smuzhiyun add r1, r1, #1048576 799*4882a593Smuzhiyun teq r0, r2 800*4882a593Smuzhiyun bne 1b 801*4882a593Smuzhiyun/* 802*4882a593Smuzhiyun * If ever we are running from Flash, then we surely want the cache 803*4882a593Smuzhiyun * to be enabled also for our execution instance... We map 2MB of it 804*4882a593Smuzhiyun * so there is no map overlap problem for up to 1 MB compressed kernel. 805*4882a593Smuzhiyun * If the execution is in RAM then we would only be duplicating the above. 806*4882a593Smuzhiyun */ 807*4882a593Smuzhiyun orr r1, r6, #0x04 @ ensure B is set for this 808*4882a593Smuzhiyun orr r1, r1, #3 << 10 809*4882a593Smuzhiyun mov r2, pc 810*4882a593Smuzhiyun mov r2, r2, lsr #20 811*4882a593Smuzhiyun orr r1, r1, r2, lsl #20 812*4882a593Smuzhiyun add r0, r3, r2, lsl #2 813*4882a593Smuzhiyun str r1, [r0], #4 814*4882a593Smuzhiyun add r1, r1, #1048576 815*4882a593Smuzhiyun str r1, [r0] 816*4882a593Smuzhiyun mov pc, lr 817*4882a593SmuzhiyunENDPROC(__setup_mmu) 818*4882a593Smuzhiyun 819*4882a593Smuzhiyun@ Enable unaligned access on v6, to allow better code generation 820*4882a593Smuzhiyun@ for the decompressor C code: 821*4882a593Smuzhiyun__armv6_mmu_cache_on: 822*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read SCTLR 823*4882a593Smuzhiyun bic r0, r0, #2 @ A (no unaligned access fault) 824*4882a593Smuzhiyun orr r0, r0, #1 << 22 @ U (v6 unaligned access model) 825*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0, 0 @ write SCTLR 826*4882a593Smuzhiyun b __armv4_mmu_cache_on 827*4882a593Smuzhiyun 828*4882a593Smuzhiyun__arm926ejs_mmu_cache_on: 829*4882a593Smuzhiyun#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 830*4882a593Smuzhiyun mov r0, #4 @ put dcache in WT mode 831*4882a593Smuzhiyun mcr p15, 7, r0, c15, c0, 0 832*4882a593Smuzhiyun#endif 833*4882a593Smuzhiyun 834*4882a593Smuzhiyun__armv4_mmu_cache_on: 835*4882a593Smuzhiyun mov r12, lr 836*4882a593Smuzhiyun#ifdef CONFIG_MMU 837*4882a593Smuzhiyun mov r6, #CB_BITS | 0x12 @ U 838*4882a593Smuzhiyun bl __setup_mmu 839*4882a593Smuzhiyun mov r0, #0 840*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 841*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 842*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read control reg 843*4882a593Smuzhiyun orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement 844*4882a593Smuzhiyun orr r0, r0, #0x0030 845*4882a593Smuzhiyun ARM_BE8( orr r0, r0, #1 << 25 ) @ big-endian page tables 846*4882a593Smuzhiyun bl __common_mmu_cache_on 847*4882a593Smuzhiyun mov r0, #0 848*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 849*4882a593Smuzhiyun#endif 850*4882a593Smuzhiyun mov pc, r12 851*4882a593Smuzhiyun 852*4882a593Smuzhiyun__armv7_mmu_cache_on: 853*4882a593Smuzhiyun enable_cp15_barriers r11 854*4882a593Smuzhiyun mov r12, lr 855*4882a593Smuzhiyun#ifdef CONFIG_MMU 856*4882a593Smuzhiyun mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 857*4882a593Smuzhiyun tst r11, #0xf @ VMSA 858*4882a593Smuzhiyun movne r6, #CB_BITS | 0x02 @ !XN 859*4882a593Smuzhiyun blne __setup_mmu 860*4882a593Smuzhiyun mov r0, #0 861*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 862*4882a593Smuzhiyun tst r11, #0xf @ VMSA 863*4882a593Smuzhiyun mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 864*4882a593Smuzhiyun#endif 865*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read control reg 866*4882a593Smuzhiyun bic r0, r0, #1 << 28 @ clear SCTLR.TRE 867*4882a593Smuzhiyun orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement 868*4882a593Smuzhiyun orr r0, r0, #0x003c @ write buffer 869*4882a593Smuzhiyun bic r0, r0, #2 @ A (no unaligned access fault) 870*4882a593Smuzhiyun orr r0, r0, #1 << 22 @ U (v6 unaligned access model) 871*4882a593Smuzhiyun @ (needed for ARM1176) 872*4882a593Smuzhiyun#ifdef CONFIG_MMU 873*4882a593Smuzhiyun ARM_BE8( orr r0, r0, #1 << 25 ) @ big-endian page tables 874*4882a593Smuzhiyun mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg 875*4882a593Smuzhiyun orrne r0, r0, #1 @ MMU enabled 876*4882a593Smuzhiyun movne r1, #0xfffffffd @ domain 0 = client 877*4882a593Smuzhiyun bic r6, r6, #1 << 31 @ 32-bit translation system 878*4882a593Smuzhiyun bic r6, r6, #(7 << 0) | (1 << 4) @ use only ttbr0 879*4882a593Smuzhiyun mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer 880*4882a593Smuzhiyun mcrne p15, 0, r1, c3, c0, 0 @ load domain access control 881*4882a593Smuzhiyun mcrne p15, 0, r6, c2, c0, 2 @ load ttb control 882*4882a593Smuzhiyun#endif 883*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 4 @ ISB 884*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0, 0 @ load control register 885*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ and read it back 886*4882a593Smuzhiyun mov r0, #0 887*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 4 @ ISB 888*4882a593Smuzhiyun mov pc, r12 889*4882a593Smuzhiyun 890*4882a593Smuzhiyun__fa526_cache_on: 891*4882a593Smuzhiyun mov r12, lr 892*4882a593Smuzhiyun mov r6, #CB_BITS | 0x12 @ U 893*4882a593Smuzhiyun bl __setup_mmu 894*4882a593Smuzhiyun mov r0, #0 895*4882a593Smuzhiyun mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache 896*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 897*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7, 0 @ flush UTLB 898*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read control reg 899*4882a593Smuzhiyun orr r0, r0, #0x1000 @ I-cache enable 900*4882a593Smuzhiyun bl __common_mmu_cache_on 901*4882a593Smuzhiyun mov r0, #0 902*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7, 0 @ flush UTLB 903*4882a593Smuzhiyun mov pc, r12 904*4882a593Smuzhiyun 905*4882a593Smuzhiyun__common_mmu_cache_on: 906*4882a593Smuzhiyun#ifndef CONFIG_THUMB2_KERNEL 907*4882a593Smuzhiyun#ifndef DEBUG 908*4882a593Smuzhiyun orr r0, r0, #0x000d @ Write buffer, mmu 909*4882a593Smuzhiyun#endif 910*4882a593Smuzhiyun mov r1, #-1 911*4882a593Smuzhiyun mcr p15, 0, r3, c2, c0, 0 @ load page table pointer 912*4882a593Smuzhiyun mcr p15, 0, r1, c3, c0, 0 @ load domain access control 913*4882a593Smuzhiyun b 1f 914*4882a593Smuzhiyun .align 5 @ cache line aligned 915*4882a593Smuzhiyun1: mcr p15, 0, r0, c1, c0, 0 @ load control register 916*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ and read it back to 917*4882a593Smuzhiyun sub pc, lr, r0, lsr #32 @ properly flush pipeline 918*4882a593Smuzhiyun#endif 919*4882a593Smuzhiyun 920*4882a593Smuzhiyun#define PROC_ENTRY_SIZE (4*5) 921*4882a593Smuzhiyun 922*4882a593Smuzhiyun/* 923*4882a593Smuzhiyun * Here follow the relocatable cache support functions for the 924*4882a593Smuzhiyun * various processors. This is a generic hook for locating an 925*4882a593Smuzhiyun * entry and jumping to an instruction at the specified offset 926*4882a593Smuzhiyun * from the start of the block. Please note this is all position 927*4882a593Smuzhiyun * independent code. 928*4882a593Smuzhiyun * 929*4882a593Smuzhiyun * r1 = corrupted 930*4882a593Smuzhiyun * r2 = corrupted 931*4882a593Smuzhiyun * r3 = block offset 932*4882a593Smuzhiyun * r9 = corrupted 933*4882a593Smuzhiyun * r12 = corrupted 934*4882a593Smuzhiyun */ 935*4882a593Smuzhiyun 936*4882a593Smuzhiyuncall_cache_fn: adr r12, proc_types 937*4882a593Smuzhiyun#ifdef CONFIG_CPU_CP15 938*4882a593Smuzhiyun mrc p15, 0, r9, c0, c0 @ get processor ID 939*4882a593Smuzhiyun#elif defined(CONFIG_CPU_V7M) 940*4882a593Smuzhiyun /* 941*4882a593Smuzhiyun * On v7-M the processor id is located in the V7M_SCB_CPUID 942*4882a593Smuzhiyun * register, but as cache handling is IMPLEMENTATION DEFINED on 943*4882a593Smuzhiyun * v7-M (if existant at all) we just return early here. 944*4882a593Smuzhiyun * If V7M_SCB_CPUID were used the cpu ID functions (i.e. 945*4882a593Smuzhiyun * __armv7_mmu_cache_{on,off,flush}) would be selected which 946*4882a593Smuzhiyun * use cp15 registers that are not implemented on v7-M. 947*4882a593Smuzhiyun */ 948*4882a593Smuzhiyun bx lr 949*4882a593Smuzhiyun#else 950*4882a593Smuzhiyun ldr r9, =CONFIG_PROCESSOR_ID 951*4882a593Smuzhiyun#endif 952*4882a593Smuzhiyun1: ldr r1, [r12, #0] @ get value 953*4882a593Smuzhiyun ldr r2, [r12, #4] @ get mask 954*4882a593Smuzhiyun eor r1, r1, r9 @ (real ^ match) 955*4882a593Smuzhiyun tst r1, r2 @ & mask 956*4882a593Smuzhiyun ARM( addeq pc, r12, r3 ) @ call cache function 957*4882a593Smuzhiyun THUMB( addeq r12, r3 ) 958*4882a593Smuzhiyun THUMB( moveq pc, r12 ) @ call cache function 959*4882a593Smuzhiyun add r12, r12, #PROC_ENTRY_SIZE 960*4882a593Smuzhiyun b 1b 961*4882a593Smuzhiyun 962*4882a593Smuzhiyun/* 963*4882a593Smuzhiyun * Table for cache operations. This is basically: 964*4882a593Smuzhiyun * - CPU ID match 965*4882a593Smuzhiyun * - CPU ID mask 966*4882a593Smuzhiyun * - 'cache on' method instruction 967*4882a593Smuzhiyun * - 'cache off' method instruction 968*4882a593Smuzhiyun * - 'cache flush' method instruction 969*4882a593Smuzhiyun * 970*4882a593Smuzhiyun * We match an entry using: ((real_id ^ match) & mask) == 0 971*4882a593Smuzhiyun * 972*4882a593Smuzhiyun * Writethrough caches generally only need 'on' and 'off' 973*4882a593Smuzhiyun * methods. Writeback caches _must_ have the flush method 974*4882a593Smuzhiyun * defined. 975*4882a593Smuzhiyun */ 976*4882a593Smuzhiyun .align 2 977*4882a593Smuzhiyun .type proc_types,#object 978*4882a593Smuzhiyunproc_types: 979*4882a593Smuzhiyun .word 0x41000000 @ old ARM ID 980*4882a593Smuzhiyun .word 0xff00f000 981*4882a593Smuzhiyun mov pc, lr 982*4882a593Smuzhiyun THUMB( nop ) 983*4882a593Smuzhiyun mov pc, lr 984*4882a593Smuzhiyun THUMB( nop ) 985*4882a593Smuzhiyun mov pc, lr 986*4882a593Smuzhiyun THUMB( nop ) 987*4882a593Smuzhiyun 988*4882a593Smuzhiyun .word 0x41007000 @ ARM7/710 989*4882a593Smuzhiyun .word 0xfff8fe00 990*4882a593Smuzhiyun mov pc, lr 991*4882a593Smuzhiyun THUMB( nop ) 992*4882a593Smuzhiyun mov pc, lr 993*4882a593Smuzhiyun THUMB( nop ) 994*4882a593Smuzhiyun mov pc, lr 995*4882a593Smuzhiyun THUMB( nop ) 996*4882a593Smuzhiyun 997*4882a593Smuzhiyun .word 0x41807200 @ ARM720T (writethrough) 998*4882a593Smuzhiyun .word 0xffffff00 999*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1000*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1001*4882a593Smuzhiyun mov pc, lr 1002*4882a593Smuzhiyun THUMB( nop ) 1003*4882a593Smuzhiyun 1004*4882a593Smuzhiyun .word 0x41007400 @ ARM74x 1005*4882a593Smuzhiyun .word 0xff00ff00 1006*4882a593Smuzhiyun W(b) __armv3_mpu_cache_on 1007*4882a593Smuzhiyun W(b) __armv3_mpu_cache_off 1008*4882a593Smuzhiyun W(b) __armv3_mpu_cache_flush 1009*4882a593Smuzhiyun 1010*4882a593Smuzhiyun .word 0x41009400 @ ARM94x 1011*4882a593Smuzhiyun .word 0xff00ff00 1012*4882a593Smuzhiyun W(b) __armv4_mpu_cache_on 1013*4882a593Smuzhiyun W(b) __armv4_mpu_cache_off 1014*4882a593Smuzhiyun W(b) __armv4_mpu_cache_flush 1015*4882a593Smuzhiyun 1016*4882a593Smuzhiyun .word 0x41069260 @ ARM926EJ-S (v5TEJ) 1017*4882a593Smuzhiyun .word 0xff0ffff0 1018*4882a593Smuzhiyun W(b) __arm926ejs_mmu_cache_on 1019*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1020*4882a593Smuzhiyun W(b) __armv5tej_mmu_cache_flush 1021*4882a593Smuzhiyun 1022*4882a593Smuzhiyun .word 0x00007000 @ ARM7 IDs 1023*4882a593Smuzhiyun .word 0x0000f000 1024*4882a593Smuzhiyun mov pc, lr 1025*4882a593Smuzhiyun THUMB( nop ) 1026*4882a593Smuzhiyun mov pc, lr 1027*4882a593Smuzhiyun THUMB( nop ) 1028*4882a593Smuzhiyun mov pc, lr 1029*4882a593Smuzhiyun THUMB( nop ) 1030*4882a593Smuzhiyun 1031*4882a593Smuzhiyun @ Everything from here on will be the new ID system. 1032*4882a593Smuzhiyun 1033*4882a593Smuzhiyun .word 0x4401a100 @ sa110 / sa1100 1034*4882a593Smuzhiyun .word 0xffffffe0 1035*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1036*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1037*4882a593Smuzhiyun W(b) __armv4_mmu_cache_flush 1038*4882a593Smuzhiyun 1039*4882a593Smuzhiyun .word 0x6901b110 @ sa1110 1040*4882a593Smuzhiyun .word 0xfffffff0 1041*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1042*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1043*4882a593Smuzhiyun W(b) __armv4_mmu_cache_flush 1044*4882a593Smuzhiyun 1045*4882a593Smuzhiyun .word 0x56056900 1046*4882a593Smuzhiyun .word 0xffffff00 @ PXA9xx 1047*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1048*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1049*4882a593Smuzhiyun W(b) __armv4_mmu_cache_flush 1050*4882a593Smuzhiyun 1051*4882a593Smuzhiyun .word 0x56158000 @ PXA168 1052*4882a593Smuzhiyun .word 0xfffff000 1053*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1054*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1055*4882a593Smuzhiyun W(b) __armv5tej_mmu_cache_flush 1056*4882a593Smuzhiyun 1057*4882a593Smuzhiyun .word 0x56050000 @ Feroceon 1058*4882a593Smuzhiyun .word 0xff0f0000 1059*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1060*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1061*4882a593Smuzhiyun W(b) __armv5tej_mmu_cache_flush 1062*4882a593Smuzhiyun 1063*4882a593Smuzhiyun#ifdef CONFIG_CPU_FEROCEON_OLD_ID 1064*4882a593Smuzhiyun /* this conflicts with the standard ARMv5TE entry */ 1065*4882a593Smuzhiyun .long 0x41009260 @ Old Feroceon 1066*4882a593Smuzhiyun .long 0xff00fff0 1067*4882a593Smuzhiyun b __armv4_mmu_cache_on 1068*4882a593Smuzhiyun b __armv4_mmu_cache_off 1069*4882a593Smuzhiyun b __armv5tej_mmu_cache_flush 1070*4882a593Smuzhiyun#endif 1071*4882a593Smuzhiyun 1072*4882a593Smuzhiyun .word 0x66015261 @ FA526 1073*4882a593Smuzhiyun .word 0xff01fff1 1074*4882a593Smuzhiyun W(b) __fa526_cache_on 1075*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1076*4882a593Smuzhiyun W(b) __fa526_cache_flush 1077*4882a593Smuzhiyun 1078*4882a593Smuzhiyun @ These match on the architecture ID 1079*4882a593Smuzhiyun 1080*4882a593Smuzhiyun .word 0x00020000 @ ARMv4T 1081*4882a593Smuzhiyun .word 0x000f0000 1082*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1083*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1084*4882a593Smuzhiyun W(b) __armv4_mmu_cache_flush 1085*4882a593Smuzhiyun 1086*4882a593Smuzhiyun .word 0x00050000 @ ARMv5TE 1087*4882a593Smuzhiyun .word 0x000f0000 1088*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1089*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1090*4882a593Smuzhiyun W(b) __armv4_mmu_cache_flush 1091*4882a593Smuzhiyun 1092*4882a593Smuzhiyun .word 0x00060000 @ ARMv5TEJ 1093*4882a593Smuzhiyun .word 0x000f0000 1094*4882a593Smuzhiyun W(b) __armv4_mmu_cache_on 1095*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1096*4882a593Smuzhiyun W(b) __armv5tej_mmu_cache_flush 1097*4882a593Smuzhiyun 1098*4882a593Smuzhiyun .word 0x0007b000 @ ARMv6 1099*4882a593Smuzhiyun .word 0x000ff000 1100*4882a593Smuzhiyun W(b) __armv6_mmu_cache_on 1101*4882a593Smuzhiyun W(b) __armv4_mmu_cache_off 1102*4882a593Smuzhiyun W(b) __armv6_mmu_cache_flush 1103*4882a593Smuzhiyun 1104*4882a593Smuzhiyun .word 0x000f0000 @ new CPU Id 1105*4882a593Smuzhiyun .word 0x000f0000 1106*4882a593Smuzhiyun W(b) __armv7_mmu_cache_on 1107*4882a593Smuzhiyun W(b) __armv7_mmu_cache_off 1108*4882a593Smuzhiyun W(b) __armv7_mmu_cache_flush 1109*4882a593Smuzhiyun 1110*4882a593Smuzhiyun .word 0 @ unrecognised type 1111*4882a593Smuzhiyun .word 0 1112*4882a593Smuzhiyun mov pc, lr 1113*4882a593Smuzhiyun THUMB( nop ) 1114*4882a593Smuzhiyun mov pc, lr 1115*4882a593Smuzhiyun THUMB( nop ) 1116*4882a593Smuzhiyun mov pc, lr 1117*4882a593Smuzhiyun THUMB( nop ) 1118*4882a593Smuzhiyun 1119*4882a593Smuzhiyun .size proc_types, . - proc_types 1120*4882a593Smuzhiyun 1121*4882a593Smuzhiyun /* 1122*4882a593Smuzhiyun * If you get a "non-constant expression in ".if" statement" 1123*4882a593Smuzhiyun * error from the assembler on this line, check that you have 1124*4882a593Smuzhiyun * not accidentally written a "b" instruction where you should 1125*4882a593Smuzhiyun * have written W(b). 1126*4882a593Smuzhiyun */ 1127*4882a593Smuzhiyun .if (. - proc_types) % PROC_ENTRY_SIZE != 0 1128*4882a593Smuzhiyun .error "The size of one or more proc_types entries is wrong." 1129*4882a593Smuzhiyun .endif 1130*4882a593Smuzhiyun 1131*4882a593Smuzhiyun/* 1132*4882a593Smuzhiyun * Turn off the Cache and MMU. ARMv3 does not support 1133*4882a593Smuzhiyun * reading the control register, but ARMv4 does. 1134*4882a593Smuzhiyun * 1135*4882a593Smuzhiyun * On exit, 1136*4882a593Smuzhiyun * r0, r1, r2, r3, r9, r12 corrupted 1137*4882a593Smuzhiyun * This routine must preserve: 1138*4882a593Smuzhiyun * r4, r7, r8 1139*4882a593Smuzhiyun */ 1140*4882a593Smuzhiyun .align 5 1141*4882a593Smuzhiyuncache_off: mov r3, #12 @ cache_off function 1142*4882a593Smuzhiyun b call_cache_fn 1143*4882a593Smuzhiyun 1144*4882a593Smuzhiyun__armv4_mpu_cache_off: 1145*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0 1146*4882a593Smuzhiyun bic r0, r0, #0x000d 1147*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0 @ turn MPU and cache off 1148*4882a593Smuzhiyun mov r0, #0 1149*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 1150*4882a593Smuzhiyun mcr p15, 0, r0, c7, c6, 0 @ flush D-Cache 1151*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 0 @ flush I-Cache 1152*4882a593Smuzhiyun mov pc, lr 1153*4882a593Smuzhiyun 1154*4882a593Smuzhiyun__armv3_mpu_cache_off: 1155*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0 1156*4882a593Smuzhiyun bic r0, r0, #0x000d 1157*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0, 0 @ turn MPU and cache off 1158*4882a593Smuzhiyun mov r0, #0 1159*4882a593Smuzhiyun mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 1160*4882a593Smuzhiyun mov pc, lr 1161*4882a593Smuzhiyun 1162*4882a593Smuzhiyun__armv4_mmu_cache_off: 1163*4882a593Smuzhiyun#ifdef CONFIG_MMU 1164*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0 1165*4882a593Smuzhiyun bic r0, r0, #0x000d 1166*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0 @ turn MMU and cache off 1167*4882a593Smuzhiyun mov r0, #0 1168*4882a593Smuzhiyun mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 1169*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 1170*4882a593Smuzhiyun#endif 1171*4882a593Smuzhiyun mov pc, lr 1172*4882a593Smuzhiyun 1173*4882a593Smuzhiyun__armv7_mmu_cache_off: 1174*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0 1175*4882a593Smuzhiyun#ifdef CONFIG_MMU 1176*4882a593Smuzhiyun bic r0, r0, #0x0005 1177*4882a593Smuzhiyun#else 1178*4882a593Smuzhiyun bic r0, r0, #0x0004 1179*4882a593Smuzhiyun#endif 1180*4882a593Smuzhiyun mcr p15, 0, r0, c1, c0 @ turn MMU and cache off 1181*4882a593Smuzhiyun mov r0, #0 1182*4882a593Smuzhiyun#ifdef CONFIG_MMU 1183*4882a593Smuzhiyun mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB 1184*4882a593Smuzhiyun#endif 1185*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC 1186*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ DSB 1187*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 4 @ ISB 1188*4882a593Smuzhiyun mov pc, lr 1189*4882a593Smuzhiyun 1190*4882a593Smuzhiyun/* 1191*4882a593Smuzhiyun * Clean and flush the cache to maintain consistency. 1192*4882a593Smuzhiyun * 1193*4882a593Smuzhiyun * On entry, 1194*4882a593Smuzhiyun * r0 = start address 1195*4882a593Smuzhiyun * r1 = end address (exclusive) 1196*4882a593Smuzhiyun * On exit, 1197*4882a593Smuzhiyun * r1, r2, r3, r9, r10, r11, r12 corrupted 1198*4882a593Smuzhiyun * This routine must preserve: 1199*4882a593Smuzhiyun * r4, r6, r7, r8 1200*4882a593Smuzhiyun */ 1201*4882a593Smuzhiyun .align 5 1202*4882a593Smuzhiyuncache_clean_flush: 1203*4882a593Smuzhiyun mov r3, #16 1204*4882a593Smuzhiyun mov r11, r1 1205*4882a593Smuzhiyun b call_cache_fn 1206*4882a593Smuzhiyun 1207*4882a593Smuzhiyun__armv4_mpu_cache_flush: 1208*4882a593Smuzhiyun tst r4, #1 1209*4882a593Smuzhiyun movne pc, lr 1210*4882a593Smuzhiyun mov r2, #1 1211*4882a593Smuzhiyun mov r3, #0 1212*4882a593Smuzhiyun mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 1213*4882a593Smuzhiyun mov r1, #7 << 5 @ 8 segments 1214*4882a593Smuzhiyun1: orr r3, r1, #63 << 26 @ 64 entries 1215*4882a593Smuzhiyun2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index 1216*4882a593Smuzhiyun subs r3, r3, #1 << 26 1217*4882a593Smuzhiyun bcs 2b @ entries 63 to 0 1218*4882a593Smuzhiyun subs r1, r1, #1 << 5 1219*4882a593Smuzhiyun bcs 1b @ segments 7 to 0 1220*4882a593Smuzhiyun 1221*4882a593Smuzhiyun teq r2, #0 1222*4882a593Smuzhiyun mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 1223*4882a593Smuzhiyun mcr p15, 0, ip, c7, c10, 4 @ drain WB 1224*4882a593Smuzhiyun mov pc, lr 1225*4882a593Smuzhiyun 1226*4882a593Smuzhiyun__fa526_cache_flush: 1227*4882a593Smuzhiyun tst r4, #1 1228*4882a593Smuzhiyun movne pc, lr 1229*4882a593Smuzhiyun mov r1, #0 1230*4882a593Smuzhiyun mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache 1231*4882a593Smuzhiyun mcr p15, 0, r1, c7, c5, 0 @ flush I cache 1232*4882a593Smuzhiyun mcr p15, 0, r1, c7, c10, 4 @ drain WB 1233*4882a593Smuzhiyun mov pc, lr 1234*4882a593Smuzhiyun 1235*4882a593Smuzhiyun__armv6_mmu_cache_flush: 1236*4882a593Smuzhiyun mov r1, #0 1237*4882a593Smuzhiyun tst r4, #1 1238*4882a593Smuzhiyun mcreq p15, 0, r1, c7, c14, 0 @ clean+invalidate D 1239*4882a593Smuzhiyun mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB 1240*4882a593Smuzhiyun mcreq p15, 0, r1, c7, c15, 0 @ clean+invalidate unified 1241*4882a593Smuzhiyun mcr p15, 0, r1, c7, c10, 4 @ drain WB 1242*4882a593Smuzhiyun mov pc, lr 1243*4882a593Smuzhiyun 1244*4882a593Smuzhiyun__armv7_mmu_cache_flush: 1245*4882a593Smuzhiyun enable_cp15_barriers r10 1246*4882a593Smuzhiyun tst r4, #1 1247*4882a593Smuzhiyun bne iflush 1248*4882a593Smuzhiyun mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 1249*4882a593Smuzhiyun tst r10, #0xf << 16 @ hierarchical cache (ARMv7) 1250*4882a593Smuzhiyun mov r10, #0 1251*4882a593Smuzhiyun beq hierarchical 1252*4882a593Smuzhiyun mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D 1253*4882a593Smuzhiyun b iflush 1254*4882a593Smuzhiyunhierarchical: 1255*4882a593Smuzhiyun dcache_line_size r1, r2 @ r1 := dcache min line size 1256*4882a593Smuzhiyun sub r2, r1, #1 @ r2 := line size mask 1257*4882a593Smuzhiyun bic r0, r0, r2 @ round down start to line size 1258*4882a593Smuzhiyun sub r11, r11, #1 @ end address is exclusive 1259*4882a593Smuzhiyun bic r11, r11, r2 @ round down end to line size 1260*4882a593Smuzhiyun0: cmp r0, r11 @ finished? 1261*4882a593Smuzhiyun bgt iflush 1262*4882a593Smuzhiyun mcr p15, 0, r0, c7, c14, 1 @ Dcache clean/invalidate by VA 1263*4882a593Smuzhiyun add r0, r0, r1 1264*4882a593Smuzhiyun b 0b 1265*4882a593Smuzhiyuniflush: 1266*4882a593Smuzhiyun mcr p15, 0, r10, c7, c10, 4 @ DSB 1267*4882a593Smuzhiyun mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB 1268*4882a593Smuzhiyun mcr p15, 0, r10, c7, c10, 4 @ DSB 1269*4882a593Smuzhiyun mcr p15, 0, r10, c7, c5, 4 @ ISB 1270*4882a593Smuzhiyun mov pc, lr 1271*4882a593Smuzhiyun 1272*4882a593Smuzhiyun__armv5tej_mmu_cache_flush: 1273*4882a593Smuzhiyun tst r4, #1 1274*4882a593Smuzhiyun movne pc, lr 1275*4882a593Smuzhiyun1: mrc p15, 0, APSR_nzcv, c7, c14, 3 @ test,clean,invalidate D cache 1276*4882a593Smuzhiyun bne 1b 1277*4882a593Smuzhiyun mcr p15, 0, r0, c7, c5, 0 @ flush I cache 1278*4882a593Smuzhiyun mcr p15, 0, r0, c7, c10, 4 @ drain WB 1279*4882a593Smuzhiyun mov pc, lr 1280*4882a593Smuzhiyun 1281*4882a593Smuzhiyun__armv4_mmu_cache_flush: 1282*4882a593Smuzhiyun tst r4, #1 1283*4882a593Smuzhiyun movne pc, lr 1284*4882a593Smuzhiyun mov r2, #64*1024 @ default: 32K dcache size (*2) 1285*4882a593Smuzhiyun mov r11, #32 @ default: 32 byte line size 1286*4882a593Smuzhiyun mrc p15, 0, r3, c0, c0, 1 @ read cache type 1287*4882a593Smuzhiyun teq r3, r9 @ cache ID register present? 1288*4882a593Smuzhiyun beq no_cache_id 1289*4882a593Smuzhiyun mov r1, r3, lsr #18 1290*4882a593Smuzhiyun and r1, r1, #7 1291*4882a593Smuzhiyun mov r2, #1024 1292*4882a593Smuzhiyun mov r2, r2, lsl r1 @ base dcache size *2 1293*4882a593Smuzhiyun tst r3, #1 << 14 @ test M bit 1294*4882a593Smuzhiyun addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 1295*4882a593Smuzhiyun mov r3, r3, lsr #12 1296*4882a593Smuzhiyun and r3, r3, #3 1297*4882a593Smuzhiyun mov r11, #8 1298*4882a593Smuzhiyun mov r11, r11, lsl r3 @ cache line size in bytes 1299*4882a593Smuzhiyunno_cache_id: 1300*4882a593Smuzhiyun mov r1, pc 1301*4882a593Smuzhiyun bic r1, r1, #63 @ align to longest cache line 1302*4882a593Smuzhiyun add r2, r1, r2 1303*4882a593Smuzhiyun1: 1304*4882a593Smuzhiyun ARM( ldr r3, [r1], r11 ) @ s/w flush D cache 1305*4882a593Smuzhiyun THUMB( ldr r3, [r1] ) @ s/w flush D cache 1306*4882a593Smuzhiyun THUMB( add r1, r1, r11 ) 1307*4882a593Smuzhiyun teq r1, r2 1308*4882a593Smuzhiyun bne 1b 1309*4882a593Smuzhiyun 1310*4882a593Smuzhiyun mcr p15, 0, r1, c7, c5, 0 @ flush I cache 1311*4882a593Smuzhiyun mcr p15, 0, r1, c7, c6, 0 @ flush D cache 1312*4882a593Smuzhiyun mcr p15, 0, r1, c7, c10, 4 @ drain WB 1313*4882a593Smuzhiyun mov pc, lr 1314*4882a593Smuzhiyun 1315*4882a593Smuzhiyun__armv3_mmu_cache_flush: 1316*4882a593Smuzhiyun__armv3_mpu_cache_flush: 1317*4882a593Smuzhiyun tst r4, #1 1318*4882a593Smuzhiyun movne pc, lr 1319*4882a593Smuzhiyun mov r1, #0 1320*4882a593Smuzhiyun mcr p15, 0, r1, c7, c0, 0 @ invalidate whole cache v3 1321*4882a593Smuzhiyun mov pc, lr 1322*4882a593Smuzhiyun 1323*4882a593Smuzhiyun/* 1324*4882a593Smuzhiyun * Various debugging routines for printing hex characters and 1325*4882a593Smuzhiyun * memory, which again must be relocatable. 1326*4882a593Smuzhiyun */ 1327*4882a593Smuzhiyun#ifdef DEBUG 1328*4882a593Smuzhiyun .align 2 1329*4882a593Smuzhiyun .type phexbuf,#object 1330*4882a593Smuzhiyunphexbuf: .space 12 1331*4882a593Smuzhiyun .size phexbuf, . - phexbuf 1332*4882a593Smuzhiyun 1333*4882a593Smuzhiyun@ phex corrupts {r0, r1, r2, r3} 1334*4882a593Smuzhiyunphex: adr r3, phexbuf 1335*4882a593Smuzhiyun mov r2, #0 1336*4882a593Smuzhiyun strb r2, [r3, r1] 1337*4882a593Smuzhiyun1: subs r1, r1, #1 1338*4882a593Smuzhiyun movmi r0, r3 1339*4882a593Smuzhiyun bmi puts 1340*4882a593Smuzhiyun and r2, r0, #15 1341*4882a593Smuzhiyun mov r0, r0, lsr #4 1342*4882a593Smuzhiyun cmp r2, #10 1343*4882a593Smuzhiyun addge r2, r2, #7 1344*4882a593Smuzhiyun add r2, r2, #'0' 1345*4882a593Smuzhiyun strb r2, [r3, r1] 1346*4882a593Smuzhiyun b 1b 1347*4882a593Smuzhiyun 1348*4882a593Smuzhiyun@ puts corrupts {r0, r1, r2, r3} 1349*4882a593Smuzhiyunputs: loadsp r3, r2, r1 1350*4882a593Smuzhiyun1: ldrb r2, [r0], #1 1351*4882a593Smuzhiyun teq r2, #0 1352*4882a593Smuzhiyun moveq pc, lr 1353*4882a593Smuzhiyun2: writeb r2, r3, r1 1354*4882a593Smuzhiyun mov r1, #0x00020000 1355*4882a593Smuzhiyun3: subs r1, r1, #1 1356*4882a593Smuzhiyun bne 3b 1357*4882a593Smuzhiyun teq r2, #'\n' 1358*4882a593Smuzhiyun moveq r2, #'\r' 1359*4882a593Smuzhiyun beq 2b 1360*4882a593Smuzhiyun teq r0, #0 1361*4882a593Smuzhiyun bne 1b 1362*4882a593Smuzhiyun mov pc, lr 1363*4882a593Smuzhiyun@ putc corrupts {r0, r1, r2, r3} 1364*4882a593Smuzhiyunputc: 1365*4882a593Smuzhiyun mov r2, r0 1366*4882a593Smuzhiyun loadsp r3, r1, r0 1367*4882a593Smuzhiyun mov r0, #0 1368*4882a593Smuzhiyun b 2b 1369*4882a593Smuzhiyun 1370*4882a593Smuzhiyun@ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr} 1371*4882a593Smuzhiyunmemdump: mov r12, r0 1372*4882a593Smuzhiyun mov r10, lr 1373*4882a593Smuzhiyun mov r11, #0 1374*4882a593Smuzhiyun2: mov r0, r11, lsl #2 1375*4882a593Smuzhiyun add r0, r0, r12 1376*4882a593Smuzhiyun mov r1, #8 1377*4882a593Smuzhiyun bl phex 1378*4882a593Smuzhiyun mov r0, #':' 1379*4882a593Smuzhiyun bl putc 1380*4882a593Smuzhiyun1: mov r0, #' ' 1381*4882a593Smuzhiyun bl putc 1382*4882a593Smuzhiyun ldr r0, [r12, r11, lsl #2] 1383*4882a593Smuzhiyun mov r1, #8 1384*4882a593Smuzhiyun bl phex 1385*4882a593Smuzhiyun and r0, r11, #7 1386*4882a593Smuzhiyun teq r0, #3 1387*4882a593Smuzhiyun moveq r0, #' ' 1388*4882a593Smuzhiyun bleq putc 1389*4882a593Smuzhiyun and r0, r11, #7 1390*4882a593Smuzhiyun add r11, r11, #1 1391*4882a593Smuzhiyun teq r0, #7 1392*4882a593Smuzhiyun bne 1b 1393*4882a593Smuzhiyun mov r0, #'\n' 1394*4882a593Smuzhiyun bl putc 1395*4882a593Smuzhiyun cmp r11, #64 1396*4882a593Smuzhiyun blt 2b 1397*4882a593Smuzhiyun mov pc, r10 1398*4882a593Smuzhiyun#endif 1399*4882a593Smuzhiyun 1400*4882a593Smuzhiyun .ltorg 1401*4882a593Smuzhiyun 1402*4882a593Smuzhiyun#ifdef CONFIG_ARM_VIRT_EXT 1403*4882a593Smuzhiyun.align 5 1404*4882a593Smuzhiyun__hyp_reentry_vectors: 1405*4882a593Smuzhiyun W(b) . @ reset 1406*4882a593Smuzhiyun W(b) . @ undef 1407*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 1408*4882a593Smuzhiyun W(b) __enter_kernel_from_hyp @ hvc from HYP 1409*4882a593Smuzhiyun#else 1410*4882a593Smuzhiyun W(b) . @ svc 1411*4882a593Smuzhiyun#endif 1412*4882a593Smuzhiyun W(b) . @ pabort 1413*4882a593Smuzhiyun W(b) . @ dabort 1414*4882a593Smuzhiyun W(b) __enter_kernel @ hyp 1415*4882a593Smuzhiyun W(b) . @ irq 1416*4882a593Smuzhiyun W(b) . @ fiq 1417*4882a593Smuzhiyun#endif /* CONFIG_ARM_VIRT_EXT */ 1418*4882a593Smuzhiyun 1419*4882a593Smuzhiyun__enter_kernel: 1420*4882a593Smuzhiyun mov r0, #0 @ must be 0 1421*4882a593Smuzhiyun mov r1, r7 @ restore architecture number 1422*4882a593Smuzhiyun mov r2, r8 @ restore atags pointer 1423*4882a593Smuzhiyun ARM( mov pc, r4 ) @ call kernel 1424*4882a593Smuzhiyun M_CLASS( add r4, r4, #1 ) @ enter in Thumb mode for M class 1425*4882a593Smuzhiyun THUMB( bx r4 ) @ entry point is always ARM for A/R classes 1426*4882a593Smuzhiyun 1427*4882a593Smuzhiyunreloc_code_end: 1428*4882a593Smuzhiyun 1429*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 1430*4882a593Smuzhiyun__enter_kernel_from_hyp: 1431*4882a593Smuzhiyun mrc p15, 4, r0, c1, c0, 0 @ read HSCTLR 1432*4882a593Smuzhiyun bic r0, r0, #0x5 @ disable MMU and caches 1433*4882a593Smuzhiyun mcr p15, 4, r0, c1, c0, 0 @ write HSCTLR 1434*4882a593Smuzhiyun isb 1435*4882a593Smuzhiyun b __enter_kernel 1436*4882a593Smuzhiyun 1437*4882a593SmuzhiyunENTRY(efi_enter_kernel) 1438*4882a593Smuzhiyun mov r4, r0 @ preserve image base 1439*4882a593Smuzhiyun mov r8, r1 @ preserve DT pointer 1440*4882a593Smuzhiyun 1441*4882a593Smuzhiyun adr_l r0, call_cache_fn 1442*4882a593Smuzhiyun adr r1, 0f @ clean the region of code we 1443*4882a593Smuzhiyun bl cache_clean_flush @ may run with the MMU off 1444*4882a593Smuzhiyun 1445*4882a593Smuzhiyun#ifdef CONFIG_ARM_VIRT_EXT 1446*4882a593Smuzhiyun @ 1447*4882a593Smuzhiyun @ The EFI spec does not support booting on ARM in HYP mode, 1448*4882a593Smuzhiyun @ since it mandates that the MMU and caches are on, with all 1449*4882a593Smuzhiyun @ 32-bit addressable DRAM mapped 1:1 using short descriptors. 1450*4882a593Smuzhiyun @ 1451*4882a593Smuzhiyun @ While the EDK2 reference implementation adheres to this, 1452*4882a593Smuzhiyun @ U-Boot might decide to enter the EFI stub in HYP mode 1453*4882a593Smuzhiyun @ anyway, with the MMU and caches either on or off. 1454*4882a593Smuzhiyun @ 1455*4882a593Smuzhiyun mrs r0, cpsr @ get the current mode 1456*4882a593Smuzhiyun msr spsr_cxsf, r0 @ record boot mode 1457*4882a593Smuzhiyun and r0, r0, #MODE_MASK @ are we running in HYP mode? 1458*4882a593Smuzhiyun cmp r0, #HYP_MODE 1459*4882a593Smuzhiyun bne .Lefi_svc 1460*4882a593Smuzhiyun 1461*4882a593Smuzhiyun mrc p15, 4, r1, c1, c0, 0 @ read HSCTLR 1462*4882a593Smuzhiyun tst r1, #0x1 @ MMU enabled at HYP? 1463*4882a593Smuzhiyun beq 1f 1464*4882a593Smuzhiyun 1465*4882a593Smuzhiyun @ 1466*4882a593Smuzhiyun @ When running in HYP mode with the caches on, we're better 1467*4882a593Smuzhiyun @ off just carrying on using the cached 1:1 mapping that the 1468*4882a593Smuzhiyun @ firmware provided. Set up the HYP vectors so HVC instructions 1469*4882a593Smuzhiyun @ issued from HYP mode take us to the correct handler code. We 1470*4882a593Smuzhiyun @ will disable the MMU before jumping to the kernel proper. 1471*4882a593Smuzhiyun @ 1472*4882a593Smuzhiyun ARM( bic r1, r1, #(1 << 30) ) @ clear HSCTLR.TE 1473*4882a593Smuzhiyun THUMB( orr r1, r1, #(1 << 30) ) @ set HSCTLR.TE 1474*4882a593Smuzhiyun mcr p15, 4, r1, c1, c0, 0 1475*4882a593Smuzhiyun adr r0, __hyp_reentry_vectors 1476*4882a593Smuzhiyun mcr p15, 4, r0, c12, c0, 0 @ set HYP vector base (HVBAR) 1477*4882a593Smuzhiyun isb 1478*4882a593Smuzhiyun b .Lefi_hyp 1479*4882a593Smuzhiyun 1480*4882a593Smuzhiyun @ 1481*4882a593Smuzhiyun @ When running in HYP mode with the caches off, we need to drop 1482*4882a593Smuzhiyun @ into SVC mode now, and let the decompressor set up its cached 1483*4882a593Smuzhiyun @ 1:1 mapping as usual. 1484*4882a593Smuzhiyun @ 1485*4882a593Smuzhiyun1: mov r9, r4 @ preserve image base 1486*4882a593Smuzhiyun bl __hyp_stub_install @ install HYP stub vectors 1487*4882a593Smuzhiyun safe_svcmode_maskall r1 @ drop to SVC mode 1488*4882a593Smuzhiyun msr spsr_cxsf, r0 @ record boot mode 1489*4882a593Smuzhiyun orr r4, r9, #1 @ restore image base and set LSB 1490*4882a593Smuzhiyun b .Lefi_hyp 1491*4882a593Smuzhiyun.Lefi_svc: 1492*4882a593Smuzhiyun#endif 1493*4882a593Smuzhiyun mrc p15, 0, r0, c1, c0, 0 @ read SCTLR 1494*4882a593Smuzhiyun tst r0, #0x1 @ MMU enabled? 1495*4882a593Smuzhiyun orreq r4, r4, #1 @ set LSB if not 1496*4882a593Smuzhiyun 1497*4882a593Smuzhiyun.Lefi_hyp: 1498*4882a593Smuzhiyun mov r0, r8 @ DT start 1499*4882a593Smuzhiyun add r1, r8, r2 @ DT end 1500*4882a593Smuzhiyun bl cache_clean_flush 1501*4882a593Smuzhiyun 1502*4882a593Smuzhiyun adr r0, 0f @ switch to our stack 1503*4882a593Smuzhiyun ldr sp, [r0] 1504*4882a593Smuzhiyun add sp, sp, r0 1505*4882a593Smuzhiyun 1506*4882a593Smuzhiyun mov r5, #0 @ appended DTB size 1507*4882a593Smuzhiyun mov r7, #0xFFFFFFFF @ machine ID 1508*4882a593Smuzhiyun b wont_overwrite 1509*4882a593SmuzhiyunENDPROC(efi_enter_kernel) 1510*4882a593Smuzhiyun0: .long .L_user_stack_end - . 1511*4882a593Smuzhiyun#endif 1512*4882a593Smuzhiyun 1513*4882a593Smuzhiyun .align 1514*4882a593Smuzhiyun .section ".stack", "aw", %nobits 1515*4882a593Smuzhiyun.L_user_stack: .space 4096 1516*4882a593Smuzhiyun.L_user_stack_end: 1517