locore-v4.S revision 271240
1129198Scognet/* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */ 2129198Scognet 3139735Simp/*- 4239268Sgonzo * Copyright 2011 Semihalf 5129198Scognet * Copyright (C) 1994-1997 Mark Brinicombe 6129198Scognet * Copyright (C) 1994 Brini 7129198Scognet * All rights reserved. 8129198Scognet * 9129198Scognet * Redistribution and use in source and binary forms, with or without 10129198Scognet * modification, are permitted provided that the following conditions 11129198Scognet * are met: 12129198Scognet * 1. Redistributions of source code must retain the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer. 14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer in the 16129198Scognet * documentation and/or other materials provided with the distribution. 17129198Scognet * 3. All advertising materials mentioning features or use of this software 18129198Scognet * must display the following acknowledgement: 19129198Scognet * This product includes software developed by Brini. 20129198Scognet * 4. The name of Brini may not be used to endorse or promote products 21129198Scognet * derived from this software without specific prior written permission. 22129198Scognet * 23129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR 24129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26129198Scognet * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27129198Scognet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28129198Scognet * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29129198Scognet * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30129198Scognet * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31129198Scognet * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32129198Scognet * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33129198Scognet * 34129198Scognet */ 35129198Scognet 36129198Scognet#include "assym.s" 37135640Scognet#include <sys/syscall.h> 38129198Scognet#include <machine/asm.h> 39129198Scognet#include <machine/armreg.h> 40270862Sian#include <machine/cpuconf.h> 41129198Scognet#include <machine/pte.h> 42236524Simp 43129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/locore.S 271240 2014-09-07 21:46:54Z andrew $"); 44129198Scognet 45159849Simp/* What size should this really be ? It is only used by initarm() */ 46239268Sgonzo#define INIT_ARM_STACK_SIZE (2048 * 4) 47129198Scognet 48129198Scognet#define CPWAIT_BRANCH \ 49129198Scognet sub pc, pc, #4 50129198Scognet 51129198Scognet#define CPWAIT(tmp) \ 52129198Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 53129198Scognet mov tmp, tmp /* wait for it to complete */ ;\ 54129198Scognet CPWAIT_BRANCH /* branch to next insn */ 55129198Scognet 56235277Simp/* 57235277Simp * This is for kvm_mkdb, and should be the address of the beginning 58235277Simp * of the kernel text segment (not necessarily the same as kernbase). 59235277Simp */ 60129198Scognet .text 61129198Scognet .align 0 62129198Scognet.globl kernbase 63129198Scognet.set kernbase,KERNBASE 64150863Scognet.globl physaddr 65150863Scognet.set physaddr,PHYSADDR 66129198Scognet 67183878Sraj/* 68236524Simp * On entry for FreeBSD boot ABI: 69236524Simp * r0 - metadata pointer or 0 (boothowto on AT91's boot2) 70218227Smarcel * r1 - if (r0 == 0) then metadata pointer 71236524Simp * On entry for Linux boot ABI: 72236524Simp * r0 - 0 73236524Simp * r1 - machine type (passed as arg2 to initarm) 74236524Simp * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) 75236524Simp * 76236524Simp * For both types of boot we gather up the args, put them in a struct arm_boot_params 77236524Simp * structure and pass that to initarm. 78183878Sraj */ 79269390Sian .globl btext 80269390Sianbtext: 81218227SmarcelASENTRY_NP(_start) 82250253Sian STOP_UNWINDING /* Can't unwind into the bootloader! */ 83250253Sian 84236524Simp mov r9, r0 /* 0 or boot mode from boot2 */ 85236524Simp mov r8, r1 /* Save Machine type */ 86236524Simp mov ip, r2 /* Save meta data */ 87266271Sgavin mov fp, r3 /* Future expansion */ 88183878Sraj 89193846Smarcel /* Make sure interrupts are disabled. */ 90193846Smarcel mrs r7, cpsr 91193846Smarcel orr r7, r7, #(I32_bit|F32_bit) 92193846Smarcel msr cpsr_c, r7 93193846Smarcel 94166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR) 95166819Scognet /* Check if we're running from flash. */ 96166819Scognet ldr r7, =FLASHADDR 97175983Sraj /* 98166819Scognet * If we're running with MMU disabled, test against the 99166819Scognet * physical address instead. 100166819Scognet */ 101166819Scognet mrc p15, 0, r2, c1, c0, 0 102166819Scognet ands r2, r2, #CPU_CONTROL_MMU_ENABLE 103236524Simp ldreq r6, =PHYSADDR 104236524Simp ldrne r6, =LOADERRAMADDR 105236524Simp cmp r7, r6 106166819Scognet bls flash_lower 107166819Scognet cmp r7, pc 108166819Scognet bhi from_ram 109166819Scognet b do_copy 110166819Scognet 111166819Scognetflash_lower: 112236524Simp cmp r6, pc 113166819Scognet bls from_ram 114166819Scognetdo_copy: 115236524Simp ldr r7, =KERNBASE 116175983Sraj adr r1, _start 117166819Scognet ldr r0, Lreal_start 118166819Scognet ldr r2, Lend 119166819Scognet sub r2, r2, r0 120236524Simp sub r0, r0, r7 121236524Simp add r0, r0, r6 122166819Scognet mov r4, r0 123166819Scognet bl memcpy 124166819Scognet ldr r0, Lram_offset 125166819Scognet add pc, r4, r0 126166819ScognetLram_offset: .word from_ram-_C_LABEL(_start) 127166819Scognetfrom_ram: 128166819Scognet nop 129135640Scognet#endif 130143681Sjmg 131166819Scognetdisable_mmu: 132135640Scognet /* Disable MMU for a while */ 133143681Sjmg mrc p15, 0, r2, c1, c0, 0 134153550Scognet bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 135153550Scognet CPU_CONTROL_WBUF_ENABLE) 136153550Scognet bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 137153550Scognet bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 138135640Scognet mcr p15, 0, r2, c1, c0, 0 139129198Scognet 140135640Scognet nop 141135640Scognet nop 142135640Scognet nop 143271240Sandrew CPWAIT(r0) 144271240Sandrew 145135640ScognetLunmapped: 146261227Sandrew /* 147261227Sandrew * Build page table from scratch. 148261227Sandrew */ 149261227Sandrew 150261855Sandrew /* Find the delta between VA and PA */ 151261855Sandrew adr r0, Lpagetable 152271232Sandrew bl translate_va_to_pa 153261855Sandrew 154266849Scognet#ifndef _ARM_ARCH_6 155261606Sandrew /* 156266849Scognet * Some of the older ports (the various XScale, mostly) assume 157266849Scognet * that the memory before the kernel is mapped, and use it for 158266849Scognet * the various stacks, page tables, etc. For those CPUs, map the 159266849Scognet * 64 first MB of RAM, as it used to be. 160266849Scognet */ 161266849Scognet /* 162261606Sandrew * Map PA == VA 163266849Scognet */ 164266849Scognet ldr r5, =PHYSADDR 165266849Scognet mov r1, r5 166266849Scognet mov r2, r5 167266849Scognet /* Map 64MiB, preserved over calls to build_pagetables */ 168266849Scognet mov r3, #64 169266849Scognet bl build_pagetables 170266849Scognet 171266849Scognet /* Create the kernel map to jump to */ 172266849Scognet mov r1, r5 173266849Scognet ldr r2, =(KERNBASE) 174266849Scognet bl build_pagetables 175266849Scognet ldr r5, =(KERNPHYSADDR) 176266849Scognet#else 177266849Scognet /* 178266849Scognet * Map PA == VA 179266849Scognet */ 180261855Sandrew /* Find the start kernels load address */ 181261855Sandrew adr r5, _start 182261855Sandrew ldr r2, =(L1_S_OFFSET) 183261855Sandrew bic r5, r2 184261606Sandrew mov r1, r5 185261606Sandrew mov r2, r5 186261606Sandrew /* Map 64MiB, preserved over calls to build_pagetables */ 187261606Sandrew mov r3, #64 188261606Sandrew bl build_pagetables 189129198Scognet 190261606Sandrew /* Create the kernel map to jump to */ 191261606Sandrew mov r1, r5 192261855Sandrew ldr r2, =(KERNVIRTADDR) 193261606Sandrew bl build_pagetables 194266849Scognet#endif 195261606Sandrew 196261606Sandrew#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 197261606Sandrew /* Create the custom map */ 198261783Simp ldr r1, =SOCDEV_PA 199261783Simp ldr r2, =SOCDEV_VA 200261606Sandrew bl build_pagetables 201261606Sandrew#endif 202129198Scognet 203239268Sgonzo#if defined(SMP) 204239268Sgonzo orr r0, r0, #2 /* Set TTB shared memory flag */ 205239268Sgonzo#endif 206129198Scognet mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 207129198Scognet mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 208129198Scognet 209259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) 210239268Sgonzo mov r0, #0 211239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 212239268Sgonzo#endif 213239268Sgonzo 214129198Scognet /* Set the Domain Access register. Very important! */ 215143681Sjmg mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 216129198Scognet mcr p15, 0, r0, c3, c0, 0 217248961Sian /* 218248961Sian * Enable MMU. 219248961Sian * On armv6 enable extended page tables, and set alignment checking 220248961Sian * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd 221248961Sian * instructions emitted by clang. 222248961Sian */ 223129198Scognet mrc p15, 0, r0, c1, c0, 0 224248961Sian#ifdef _ARM_ARCH_6 225248961Sian orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE) 226256628Sian orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE) 227250928Sgber orr r0, r0, #(CPU_CONTROL_AF_ENABLE) 228239268Sgonzo#endif 229243602Sgonzo orr r0, r0, #(CPU_CONTROL_MMU_ENABLE) 230129198Scognet mcr p15, 0, r0, c1, c0, 0 231153550Scognet nop 232153550Scognet nop 233153550Scognet nop 234129198Scognet CPWAIT(r0) 235129198Scognet 236129198Scognetmmu_done: 237153550Scognet nop 238129198Scognet adr r1, .Lstart 239129198Scognet ldmia r1, {r1, r2, sp} /* Set initial stack and */ 240129198Scognet sub r2, r2, r1 /* get zero init data */ 241129198Scognet mov r3, #0 242129198Scognet.L1: 243150863Scognet str r3, [r1], #0x0004 /* get zero init data */ 244129198Scognet subs r2, r2, #4 245129198Scognet bgt .L1 246153550Scognet ldr pc, .Lvirt_done 247129198Scognet 248142145Scognetvirt_done: 249261663Sandrew mov r1, #28 /* loader info size is 28 bytes also second arg */ 250236524Simp subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 251261855Sandrew mov r0, sp /* loader info pointer is first arg */ 252247608Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 253236524Simp str r1, [r0] /* Store length of loader info */ 254236524Simp str r9, [r0, #4] /* Store r0 from boot loader */ 255236524Simp str r8, [r0, #8] /* Store r1 from boot loader */ 256236524Simp str ip, [r0, #12] /* store r2 from boot loader */ 257236524Simp str fp, [r0, #16] /* store r3 from boot loader */ 258261562Sandrew str r5, [r0, #20] /* store the physical address */ 259261855Sandrew adr r4, Lpagetable /* load the pagetable address */ 260261855Sandrew ldr r5, [r4, #4] 261261663Sandrew str r5, [r0, #24] /* store the pagetable address */ 262175983Sraj mov fp, #0 /* trace back starts here */ 263129198Scognet bl _C_LABEL(initarm) /* Off we go */ 264129198Scognet 265129198Scognet /* init arm will return the new stack pointer. */ 266129198Scognet mov sp, r0 267129198Scognet 268129198Scognet bl _C_LABEL(mi_startup) /* call mi_startup()! */ 269129198Scognet 270129198Scognet adr r0, .Lmainreturned 271130164Sphk b _C_LABEL(panic) 272175983Sraj /* NOTREACHED */ 273261606SandrewEND(_start) 274261606Sandrew 275271232Sandrew#define VA_TO_PA_POINTER(name, table) \ 276271232Sandrewname: ;\ 277271232Sandrew .word . ;\ 278271232Sandrew .word table 279271232Sandrew 280261606Sandrew/* 281271232Sandrew * Returns the physical address of a magic va to pa pointer. 282271232Sandrew * r0 - The pagetable data pointer. This must be built using the 283271232Sandrew * VA_TO_PA_POINTER macro. 284271232Sandrew * e.g. 285271232Sandrew * VA_TO_PA_POINTER(Lpagetable, pagetable) 286271232Sandrew * ... 287271232Sandrew * adr r0, Lpagetable 288271232Sandrew * bl translate_va_to_pa 289271232Sandrew * r0 will now contain the physical address of pagetable 290271232Sandrew * r1, r2 - Trashed 291271232Sandrew */ 292271232Sandrewtranslate_va_to_pa: 293271232Sandrew ldr r1, [r0] 294271232Sandrew sub r2, r1, r0 295271232Sandrew /* At this point: r2 = VA - PA */ 296271232Sandrew 297271232Sandrew /* 298271232Sandrew * Find the physical address of the table. After these two 299271232Sandrew * instructions: 300271232Sandrew * r1 = va(pagetable) 301271232Sandrew * 302271232Sandrew * r0 = va(pagetable) - (VA - PA) 303271232Sandrew * = va(pagetable) - VA + PA 304271232Sandrew * = pa(pagetable) 305271232Sandrew */ 306271232Sandrew ldr r1, [r0, #4] 307271232Sandrew sub r0, r1, r2 308271232Sandrew RET 309271232Sandrew 310271232Sandrew/* 311261606Sandrew * Builds the page table 312261606Sandrew * r0 - The table base address 313261606Sandrew * r1 - The physical address (trashed) 314261606Sandrew * r2 - The virtual address (trashed) 315261606Sandrew * r3 - The number of 1MiB sections 316261606Sandrew * r4 - Trashed 317261606Sandrew * 318261606Sandrew * Addresses must be 1MiB aligned 319261606Sandrew */ 320261606Sandrewbuild_pagetables: 321261606Sandrew /* Set the required page attributed */ 322261606Sandrew ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 323261606Sandrew#if defined(SMP) 324261606Sandrew orr r4, #(L1_SHARED) 325261606Sandrew#endif 326261606Sandrew orr r1, r4 327261606Sandrew 328261606Sandrew /* Move the virtual address to the correct bit location */ 329261606Sandrew lsr r2, #(L1_S_SHIFT - 2) 330261606Sandrew 331261606Sandrew mov r4, r3 332261606Sandrew1: 333261606Sandrew str r1, [r0, r2] 334261606Sandrew add r2, r2, #4 335261606Sandrew add r1, r1, #(L1_S_SIZE) 336261606Sandrew adds r4, r4, #-1 337261606Sandrew bhi 1b 338261606Sandrew 339261606Sandrew RET 340261606Sandrew 341271232SandrewVA_TO_PA_POINTER(Lpagetable, pagetable) 342261855Sandrew 343166819ScognetLreal_start: 344166819Scognet .word _start 345261855SandrewLend: 346166819Scognet .word _edata 347261855Sandrew 348129198Scognet.Lstart: 349129198Scognet .word _edata 350261227Sandrew .word _ebss 351129198Scognet .word svcstk + INIT_ARM_STACK_SIZE 352129198Scognet 353153550Scognet.Lvirt_done: 354153550Scognet .word virt_done 355239268Sgonzo 356129198Scognet.Lmainreturned: 357129198Scognet .asciz "main() returned" 358129198Scognet .align 0 359129198Scognet 360129198Scognet .bss 361129198Scognetsvcstk: 362129198Scognet .space INIT_ARM_STACK_SIZE 363129198Scognet 364261227Sandrew/* 365261227Sandrew * Memory for the initial pagetable. We are unable to place this in 366261227Sandrew * the bss as this will be cleared after the table is loaded. 367261227Sandrew */ 368261227Sandrew .section ".init_pagetable" 369261227Sandrew .align 14 /* 16KiB aligned */ 370261227Sandrewpagetable: 371261227Sandrew .space L1_TABLE_SIZE 372261227Sandrew 373129198Scognet .text 374129198Scognet .align 0 375129198Scognet 376143681Sjmg.Lcpufuncs: 377129198Scognet .word _C_LABEL(cpufuncs) 378129198Scognet 379239268Sgonzo#if defined(SMP) 380239268Sgonzo 381265705Sian.Lmpvirt_done: 382265705Sian .word mpvirt_done 383271232SandrewVA_TO_PA_POINTER(Lstartup_pagetable_secondary, temp_pagetable) 384265705Sian 385239268SgonzoASENTRY_NP(mpentry) 386239268Sgonzo 387239268Sgonzo /* Make sure interrupts are disabled. */ 388239268Sgonzo mrs r7, cpsr 389239268Sgonzo orr r7, r7, #(I32_bit|F32_bit) 390239268Sgonzo msr cpsr_c, r7 391239268Sgonzo 392265784Sian /* Disable MMU. It should be disabled already, but make sure. */ 393239268Sgonzo mrc p15, 0, r2, c1, c0, 0 394239268Sgonzo bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 395239268Sgonzo CPU_CONTROL_WBUF_ENABLE) 396239268Sgonzo bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 397239268Sgonzo bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 398239268Sgonzo mcr p15, 0, r2, c1, c0, 0 399239268Sgonzo nop 400239268Sgonzo nop 401239268Sgonzo nop 402265784Sian CPWAIT(r0) 403239268Sgonzo 404270862Sian#if ARM_MMU_V6 405265784Sian bl armv6_idcache_inv_all /* Modifies r0 only */ 406270862Sian#elif ARM_MMU_V7 407265784Sian bl armv7_idcache_inv_all /* Modifies r0-r3, ip */ 408265784Sian#endif 409265784Sian 410271232Sandrew /* Load the page table physical address */ 411271232Sandrew adr r0, Lstartup_pagetable_secondary 412271232Sandrew bl translate_va_to_pa 413271232Sandrew /* Load the address the secondary page table */ 414239268Sgonzo ldr r0, [r0] 415271232Sandrew 416262413Sian orr r0, r0, #2 /* Set TTB shared memory flag */ 417239268Sgonzo mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 418239268Sgonzo mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 419239268Sgonzo 420239268Sgonzo mov r0, #0 421239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 422239268Sgonzo 423239268Sgonzo /* Set the Domain Access register. Very important! */ 424239268Sgonzo mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 425239268Sgonzo mcr p15, 0, r0, c3, c0, 0 426239268Sgonzo /* Enable MMU */ 427239268Sgonzo mrc p15, 0, r0, c1, c0, 0 428239268Sgonzo orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 429258845Szbb orr r0, r0, #CPU_CONTROL_AF_ENABLE 430265784Sian orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 431265784Sian CPU_CONTROL_WBUF_ENABLE) 432265784Sian orr r0, r0, #(CPU_CONTROL_IC_ENABLE) 433265784Sian orr r0, r0, #(CPU_CONTROL_BPRD_ENABLE) 434239268Sgonzo mcr p15, 0, r0, c1, c0, 0 435239268Sgonzo nop 436239268Sgonzo nop 437239268Sgonzo nop 438239268Sgonzo CPWAIT(r0) 439239268Sgonzo 440239268Sgonzo adr r1, .Lstart 441239268Sgonzo ldmia r1, {r1, r2, sp} /* Set initial stack and */ 442239268Sgonzo mrc p15, 0, r0, c0, c0, 5 443239268Sgonzo and r0, r0, #15 444239268Sgonzo mov r1, #2048 445239268Sgonzo mul r2, r1, r0 446239268Sgonzo sub sp, sp, r2 447239268Sgonzo str r1, [sp] 448239268Sgonzo ldr pc, .Lmpvirt_done 449239268Sgonzo 450239268Sgonzompvirt_done: 451239268Sgonzo 452239268Sgonzo mov fp, #0 /* trace back starts here */ 453239268Sgonzo bl _C_LABEL(init_secondary) /* Off we go */ 454239268Sgonzo 455239268Sgonzo adr r0, .Lmpreturned 456239268Sgonzo b _C_LABEL(panic) 457239268Sgonzo /* NOTREACHED */ 458239268Sgonzo 459239268Sgonzo.Lmpreturned: 460265705Sian .asciz "init_secondary() returned" 461239268Sgonzo .align 0 462248361SandrewEND(mpentry) 463239268Sgonzo#endif 464239268Sgonzo 465135640ScognetENTRY_NP(cpu_halt) 466129198Scognet mrs r2, cpsr 467129198Scognet bic r2, r2, #(PSR_MODE) 468129198Scognet orr r2, r2, #(PSR_SVC32_MODE) 469129198Scognet orr r2, r2, #(I32_bit | F32_bit) 470261393Sian msr cpsr_fsxc, r2 471129198Scognet 472129198Scognet ldr r4, .Lcpu_reset_address 473129198Scognet ldr r4, [r4] 474129198Scognet 475129198Scognet ldr r0, .Lcpufuncs 476129198Scognet mov lr, pc 477129198Scognet ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 478183839Sraj mov lr, pc 479183839Sraj ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 480129198Scognet 481129198Scognet /* 482129198Scognet * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 483129198Scognet * necessary. 484129198Scognet */ 485129198Scognet 486129198Scognet ldr r1, .Lcpu_reset_needs_v4_MMU_disable 487129198Scognet ldr r1, [r1] 488129198Scognet cmp r1, #0 489129198Scognet mov r2, #0 490129198Scognet 491129198Scognet /* 492175983Sraj * MMU & IDC off, 32 bit program & data space 493129198Scognet * Hurl ourselves into the ROM 494129198Scognet */ 495129198Scognet mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 496129198Scognet mcr 15, 0, r0, c1, c0, 0 497129198Scognet mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 498129198Scognet mov pc, r4 499129198Scognet 500129198Scognet /* 501129198Scognet * _cpu_reset_address contains the address to branch to, to complete 502129198Scognet * the cpu reset after turning the MMU off 503129198Scognet * This variable is provided by the hardware specific code 504129198Scognet */ 505129198Scognet.Lcpu_reset_address: 506129198Scognet .word _C_LABEL(cpu_reset_address) 507129198Scognet 508129198Scognet /* 509129198Scognet * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 510129198Scognet * v4 MMU disable instruction needs executing... it is an illegal instruction 511129198Scognet * on f.e. ARM6/7 that locks up the computer in an endless illegal 512129198Scognet * instruction / data-abort / reset loop. 513129198Scognet */ 514129198Scognet.Lcpu_reset_needs_v4_MMU_disable: 515129198Scognet .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 516248361SandrewEND(cpu_halt) 517129198Scognet 518129198Scognet 519129198Scognet/* 520129198Scognet * setjump + longjmp 521129198Scognet */ 522129198ScognetENTRY(setjmp) 523129198Scognet stmia r0, {r4-r14} 524129198Scognet mov r0, #0x00000000 525137463Scognet RET 526248361SandrewEND(setjmp) 527129198Scognet 528129198ScognetENTRY(longjmp) 529129198Scognet ldmia r0, {r4-r14} 530129198Scognet mov r0, #0x00000001 531137463Scognet RET 532248361SandrewEND(longjmp) 533129198Scognet 534129198Scognet .data 535129198Scognet .global _C_LABEL(esym) 536129198Scognet_C_LABEL(esym): .word _C_LABEL(end) 537129198Scognet 538129198ScognetENTRY_NP(abort) 539129198Scognet b _C_LABEL(abort) 540248361SandrewEND(abort) 541129198Scognet 542135640ScognetENTRY_NP(sigcode) 543135640Scognet mov r0, sp 544262903Sian add r0, r0, #SIGF_UC 545245414Sandrew 546245414Sandrew /* 547245414Sandrew * Call the sigreturn system call. 548245414Sandrew * 549245414Sandrew * We have to load r7 manually rather than using 550245414Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 551245414Sandrew * correct. Using the alternative places esigcode at the address 552245414Sandrew * of the data rather than the address one past the data. 553245414Sandrew */ 554245414Sandrew 555245414Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 556135640Scognet swi SYS_sigreturn 557135640Scognet 558135640Scognet /* Well if that failed we better exit quick ! */ 559135640Scognet 560245414Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 561135640Scognet swi SYS_exit 562135640Scognet 563245414Sandrew /* Branch back to retry SYS_sigreturn */ 564245414Sandrew b . - 16 565269390SianEND(sigcode) 566245414Sandrew .word SYS_sigreturn 567245414Sandrew .word SYS_exit 568245414Sandrew 569135640Scognet .align 0 570135640Scognet .global _C_LABEL(esigcode) 571135640Scognet _C_LABEL(esigcode): 572143681Sjmg 573135640Scognet .data 574135640Scognet .global szsigcode 575135640Scognetszsigcode: 576135640Scognet .long esigcode-sigcode 577269390Sian 578129198Scognet/* End of locore.S */ 579