locore-v4.S revision 261393
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> 40129198Scognet#include <machine/pte.h> 41236524Simp 42129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/locore.S 261393 2014-02-02 00:48:15Z ian $"); 43129198Scognet 44159849Simp/* What size should this really be ? It is only used by initarm() */ 45239268Sgonzo#define INIT_ARM_STACK_SIZE (2048 * 4) 46129198Scognet 47129198Scognet#define CPWAIT_BRANCH \ 48129198Scognet sub pc, pc, #4 49129198Scognet 50129198Scognet#define CPWAIT(tmp) \ 51129198Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 52129198Scognet mov tmp, tmp /* wait for it to complete */ ;\ 53129198Scognet CPWAIT_BRANCH /* branch to next insn */ 54129198Scognet 55235277Simp/* 56235277Simp * This is for kvm_mkdb, and should be the address of the beginning 57235277Simp * of the kernel text segment (not necessarily the same as kernbase). 58235277Simp */ 59129198Scognet .text 60129198Scognet .align 0 61129198Scognet.globl kernbase 62129198Scognet.set kernbase,KERNBASE 63150863Scognet.globl physaddr 64150863Scognet.set physaddr,PHYSADDR 65129198Scognet 66183878Sraj/* 67236524Simp * On entry for FreeBSD boot ABI: 68236524Simp * r0 - metadata pointer or 0 (boothowto on AT91's boot2) 69218227Smarcel * r1 - if (r0 == 0) then metadata pointer 70236524Simp * On entry for Linux boot ABI: 71236524Simp * r0 - 0 72236524Simp * r1 - machine type (passed as arg2 to initarm) 73236524Simp * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) 74236524Simp * 75236524Simp * For both types of boot we gather up the args, put them in a struct arm_boot_params 76236524Simp * structure and pass that to initarm. 77183878Sraj */ 78236524SimpENTRY_NP(btext) 79218227SmarcelASENTRY_NP(_start) 80250253Sian STOP_UNWINDING /* Can't unwind into the bootloader! */ 81250253Sian 82236524Simp mov r9, r0 /* 0 or boot mode from boot2 */ 83236524Simp mov r8, r1 /* Save Machine type */ 84236524Simp mov ip, r2 /* Save meta data */ 85236524Simp mov fp, r3 /* Future expantion */ 86183878Sraj 87193846Smarcel /* Make sure interrupts are disabled. */ 88193846Smarcel mrs r7, cpsr 89193846Smarcel orr r7, r7, #(I32_bit|F32_bit) 90193846Smarcel msr cpsr_c, r7 91193846Smarcel 92166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR) 93166819Scognet /* Check if we're running from flash. */ 94166819Scognet ldr r7, =FLASHADDR 95175983Sraj /* 96166819Scognet * If we're running with MMU disabled, test against the 97166819Scognet * physical address instead. 98166819Scognet */ 99166819Scognet mrc p15, 0, r2, c1, c0, 0 100166819Scognet ands r2, r2, #CPU_CONTROL_MMU_ENABLE 101236524Simp ldreq r6, =PHYSADDR 102236524Simp ldrne r6, =LOADERRAMADDR 103236524Simp cmp r7, r6 104166819Scognet bls flash_lower 105166819Scognet cmp r7, pc 106166819Scognet bhi from_ram 107166819Scognet b do_copy 108166819Scognet 109166819Scognetflash_lower: 110236524Simp cmp r6, pc 111166819Scognet bls from_ram 112166819Scognetdo_copy: 113236524Simp ldr r7, =KERNBASE 114175983Sraj adr r1, _start 115166819Scognet ldr r0, Lreal_start 116166819Scognet ldr r2, Lend 117166819Scognet sub r2, r2, r0 118236524Simp sub r0, r0, r7 119236524Simp add r0, r0, r6 120166819Scognet mov r4, r0 121166819Scognet bl memcpy 122166819Scognet ldr r0, Lram_offset 123166819Scognet add pc, r4, r0 124166819ScognetLram_offset: .word from_ram-_C_LABEL(_start) 125166819Scognetfrom_ram: 126166819Scognet nop 127135640Scognet#endif 128135640Scognet adr r7, Lunmapped 129190602Scognet bic r7, r7, #0xf0000000 130153616Scognet orr r7, r7, #PHYSADDR 131143681Sjmg 132175983Sraj 133166819Scognetdisable_mmu: 134135640Scognet /* Disable MMU for a while */ 135143681Sjmg mrc p15, 0, r2, c1, c0, 0 136153550Scognet bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 137153550Scognet CPU_CONTROL_WBUF_ENABLE) 138153550Scognet bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 139153550Scognet bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 140135640Scognet mcr p15, 0, r2, c1, c0, 0 141129198Scognet 142135640Scognet nop 143135640Scognet nop 144135640Scognet nop 145135640Scognet mov pc, r7 146135640ScognetLunmapped: 147261227Sandrew /* 148261227Sandrew * Build page table from scratch. 149261227Sandrew */ 150261227Sandrew 151261227Sandrew /* Load the page tables physical address */ 152261227Sandrew ldr r1, Lstartup_pagetable 153261227Sandrew ldr r2, =(KERNVIRTADDR - KERNPHYSADDR) 154261227Sandrew sub r0, r1, r2 155261227Sandrew 156129198Scognet adr r4, mmu_init_table 157129198Scognet b 3f 158129198Scognet 159129198Scognet2: 160129198Scognet str r3, [r0, r2] 161129198Scognet add r2, r2, #4 162129198Scognet add r3, r3, #(L1_S_SIZE) 163129198Scognet adds r1, r1, #-1 164129198Scognet bhi 2b 165143681Sjmg3: 166172356Scognet ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */ 167129198Scognet cmp r1, #0 168140683Scognet adrne r5, 2b 169190602Scognet bicne r5, r5, #0xf0000000 170140683Scognet orrne r5, r5, #PHYSADDR 171140683Scognet movne pc, r5 172129198Scognet 173239268Sgonzo#if defined(SMP) 174239268Sgonzo orr r0, r0, #2 /* Set TTB shared memory flag */ 175239268Sgonzo#endif 176129198Scognet mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 177129198Scognet mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 178129198Scognet 179259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) 180239268Sgonzo mov r0, #0 181239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 182239268Sgonzo#endif 183239268Sgonzo 184129198Scognet /* Set the Domain Access register. Very important! */ 185143681Sjmg mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 186129198Scognet mcr p15, 0, r0, c3, c0, 0 187248961Sian /* 188248961Sian * Enable MMU. 189248961Sian * On armv6 enable extended page tables, and set alignment checking 190248961Sian * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd 191248961Sian * instructions emitted by clang. 192248961Sian */ 193129198Scognet mrc p15, 0, r0, c1, c0, 0 194248961Sian#ifdef _ARM_ARCH_6 195248961Sian orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE) 196256628Sian orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE) 197250928Sgber orr r0, r0, #(CPU_CONTROL_AF_ENABLE) 198239268Sgonzo#endif 199243602Sgonzo orr r0, r0, #(CPU_CONTROL_MMU_ENABLE) 200129198Scognet mcr p15, 0, r0, c1, c0, 0 201153550Scognet nop 202153550Scognet nop 203153550Scognet nop 204129198Scognet CPWAIT(r0) 205129198Scognet 206129198Scognetmmu_done: 207153550Scognet nop 208129198Scognet adr r1, .Lstart 209129198Scognet ldmia r1, {r1, r2, sp} /* Set initial stack and */ 210129198Scognet sub r2, r2, r1 /* get zero init data */ 211129198Scognet mov r3, #0 212129198Scognet.L1: 213150863Scognet str r3, [r1], #0x0004 /* get zero init data */ 214129198Scognet subs r2, r2, #4 215129198Scognet bgt .L1 216153550Scognet ldr pc, .Lvirt_done 217129198Scognet 218142145Scognetvirt_done: 219236524Simp mov r1, #20 /* loader info size is 20 bytes also second arg */ 220236524Simp subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 221247608Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 222236524Simp mov r0, sp /* loader info pointer is first arg */ 223236524Simp str r1, [r0] /* Store length of loader info */ 224236524Simp str r9, [r0, #4] /* Store r0 from boot loader */ 225236524Simp str r8, [r0, #8] /* Store r1 from boot loader */ 226236524Simp str ip, [r0, #12] /* store r2 from boot loader */ 227236524Simp str fp, [r0, #16] /* store r3 from boot loader */ 228175983Sraj mov fp, #0 /* trace back starts here */ 229129198Scognet bl _C_LABEL(initarm) /* Off we go */ 230129198Scognet 231129198Scognet /* init arm will return the new stack pointer. */ 232129198Scognet mov sp, r0 233129198Scognet 234129198Scognet bl _C_LABEL(mi_startup) /* call mi_startup()! */ 235129198Scognet 236129198Scognet adr r0, .Lmainreturned 237130164Sphk b _C_LABEL(panic) 238175983Sraj /* NOTREACHED */ 239129198Scognet#define MMU_INIT(va,pa,n_sec,attr) \ 240129198Scognet .word n_sec ; \ 241129198Scognet .word 4*((va)>>L1_S_SHIFT) ; \ 242129198Scognet .word (pa)|(attr) ; 243129198Scognet 244150863ScognetLvirtaddr: 245150863Scognet .word KERNVIRTADDR 246150863ScognetLphysaddr: 247150863Scognet .word KERNPHYSADDR 248166819ScognetLreal_start: 249166819Scognet .word _start 250166819ScognetLend: 251166819Scognet .word _edata 252129198ScognetLstartup_pagetable: 253261227Sandrew .word pagetable 254239268Sgonzo#ifdef SMP 255239268SgonzoLstartup_pagetable_secondary: 256239268Sgonzo .word temp_pagetable 257239268Sgonzo#endif 258248361SandrewEND(btext) 259248361SandrewEND(_start) 260248361Sandrew 261143681Sjmgmmu_init_table: 262129198Scognet /* fill all table VA==PA */ 263129198Scognet /* map SDRAM VA==PA, WT cacheable */ 264239268Sgonzo#if !defined(SMP) 265261039Simp MMU_INIT(PHYSADDR, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 266135640Scognet /* map VA 0xc0000000..0xc3ffffff to PA */ 267135640Scognet MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 268261336Simp#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 269261039Simp /* Map in 0x04000000 worth of the SoC's devices for bootstrap debugging */ 270261336Simp MMU_INIT(SOCDEV_VA, SOCDEV_PA, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 271261039Simp#endif 272239268Sgonzo#else 273239268Sgonzo MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) 274239268Sgonzo /* map VA 0xc0000000..0xc3ffffff to PA */ 275239268Sgonzo MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) 276239268Sgonzo MMU_INIT(0x48000000, 0x48000000, 1, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) 277250293Sgber#endif /* SMP */ 278129198Scognet .word 0 /* end of table */ 279129198Scognet.Lstart: 280129198Scognet .word _edata 281261227Sandrew .word _ebss 282129198Scognet .word svcstk + INIT_ARM_STACK_SIZE 283129198Scognet 284153550Scognet.Lvirt_done: 285153550Scognet .word virt_done 286239268Sgonzo#if defined(SMP) 287239268Sgonzo.Lmpvirt_done: 288239268Sgonzo .word mpvirt_done 289239268Sgonzo#endif 290239268Sgonzo 291129198Scognet.Lmainreturned: 292129198Scognet .asciz "main() returned" 293129198Scognet .align 0 294129198Scognet 295129198Scognet .bss 296129198Scognetsvcstk: 297129198Scognet .space INIT_ARM_STACK_SIZE 298129198Scognet 299261227Sandrew/* 300261227Sandrew * Memory for the initial pagetable. We are unable to place this in 301261227Sandrew * the bss as this will be cleared after the table is loaded. 302261227Sandrew */ 303261227Sandrew .section ".init_pagetable" 304261227Sandrew .align 14 /* 16KiB aligned */ 305261227Sandrewpagetable: 306261227Sandrew .space L1_TABLE_SIZE 307261227Sandrew 308129198Scognet .text 309129198Scognet .align 0 310129198Scognet 311143681Sjmg.Lcpufuncs: 312129198Scognet .word _C_LABEL(cpufuncs) 313129198Scognet 314239268Sgonzo#if defined(SMP) 315239268SgonzoLsramaddr: 316239268Sgonzo .word 0xffff0080 317239268Sgonzo 318239268Sgonzo#if 0 319239268Sgonzo#define AP_DEBUG(tmp) \ 320239268Sgonzo mrc p15, 0, r1, c0, c0, 5; \ 321239268Sgonzo ldr r0, Lsramaddr; \ 322239268Sgonzo add r0, r1, lsl #2; \ 323239268Sgonzo mov r1, tmp; \ 324239268Sgonzo str r1, [r0], #0x0000; 325239268Sgonzo#else 326239268Sgonzo#define AP_DEBUG(tmp) 327239268Sgonzo#endif 328239268Sgonzo 329239268Sgonzo 330239268SgonzoASENTRY_NP(mptramp) 331239268Sgonzo mov r0, #0 332239268Sgonzo mcr p15, 0, r0, c7, c7, 0 333239268Sgonzo 334239268Sgonzo AP_DEBUG(#1) 335239268Sgonzo 336261393Sian mrs r3, cpsr 337239268Sgonzo bic r3, r3, #(PSR_MODE) 338239268Sgonzo orr r3, r3, #(PSR_SVC32_MODE) 339261393Sian msr cpsr_fsxc, r3 340239268Sgonzo 341239268Sgonzo mrc p15, 0, r0, c0, c0, 5 342239268Sgonzo and r0, #0x0f /* Get CPU ID */ 343239268Sgonzo 344239268Sgonzo /* Read boot address for CPU */ 345239268Sgonzo mov r1, #0x100 346239268Sgonzo mul r2, r0, r1 347239268Sgonzo ldr r1, Lpmureg 348239268Sgonzo add r0, r2, r1 349239268Sgonzo ldr r1, [r0], #0x00 350239268Sgonzo 351239268Sgonzo mov pc, r1 352239268Sgonzo 353239268SgonzoLpmureg: 354239268Sgonzo .word 0xd0022124 355248361SandrewEND(mptramp) 356239268Sgonzo 357239268SgonzoASENTRY_NP(mpentry) 358239268Sgonzo 359239268Sgonzo AP_DEBUG(#2) 360239268Sgonzo 361239268Sgonzo /* Make sure interrupts are disabled. */ 362239268Sgonzo mrs r7, cpsr 363239268Sgonzo orr r7, r7, #(I32_bit|F32_bit) 364239268Sgonzo msr cpsr_c, r7 365239268Sgonzo 366239268Sgonzo 367239268Sgonzo adr r7, Ltag 368239268Sgonzo bic r7, r7, #0xf0000000 369239268Sgonzo orr r7, r7, #PHYSADDR 370239268Sgonzo 371239268Sgonzo /* Disable MMU for a while */ 372239268Sgonzo mrc p15, 0, r2, c1, c0, 0 373239268Sgonzo bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 374239268Sgonzo CPU_CONTROL_WBUF_ENABLE) 375239268Sgonzo bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 376239268Sgonzo bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 377239268Sgonzo mcr p15, 0, r2, c1, c0, 0 378239268Sgonzo 379239268Sgonzo nop 380239268Sgonzo nop 381239268Sgonzo nop 382239268Sgonzo 383239268Sgonzo AP_DEBUG(#3) 384239268Sgonzo 385239268SgonzoLtag: 386239268Sgonzo ldr r0, Lstartup_pagetable_secondary 387239268Sgonzo bic r0, r0, #0xf0000000 388239268Sgonzo orr r0, r0, #PHYSADDR 389239268Sgonzo ldr r0, [r0] 390239268Sgonzo#if defined(SMP) 391239268Sgonzo orr r0, r0, #0 /* Set TTB shared memory flag */ 392239268Sgonzo#endif 393239268Sgonzo mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 394239268Sgonzo mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 395239268Sgonzo 396259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA) || defined(CPU_KRAIT) 397239268Sgonzo mov r0, #0 398239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 399239268Sgonzo#endif 400239268Sgonzo 401239268Sgonzo AP_DEBUG(#4) 402239268Sgonzo 403239268Sgonzo /* Set the Domain Access register. Very important! */ 404239268Sgonzo mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 405239268Sgonzo mcr p15, 0, r0, c3, c0, 0 406239268Sgonzo /* Enable MMU */ 407239268Sgonzo mrc p15, 0, r0, c1, c0, 0 408259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA) || defined(CPU_KRAIT) 409239268Sgonzo orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 410258845Szbb orr r0, r0, #CPU_CONTROL_AF_ENABLE 411239268Sgonzo#endif 412239268Sgonzo orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE) 413239268Sgonzo mcr p15, 0, r0, c1, c0, 0 414239268Sgonzo nop 415239268Sgonzo nop 416239268Sgonzo nop 417239268Sgonzo CPWAIT(r0) 418239268Sgonzo 419239268Sgonzo adr r1, .Lstart 420239268Sgonzo ldmia r1, {r1, r2, sp} /* Set initial stack and */ 421239268Sgonzo mrc p15, 0, r0, c0, c0, 5 422239268Sgonzo and r0, r0, #15 423239268Sgonzo mov r1, #2048 424239268Sgonzo mul r2, r1, r0 425239268Sgonzo sub sp, sp, r2 426239268Sgonzo str r1, [sp] 427239268Sgonzo ldr pc, .Lmpvirt_done 428239268Sgonzo 429239268Sgonzompvirt_done: 430239268Sgonzo 431239268Sgonzo mov fp, #0 /* trace back starts here */ 432239268Sgonzo bl _C_LABEL(init_secondary) /* Off we go */ 433239268Sgonzo 434239268Sgonzo adr r0, .Lmpreturned 435239268Sgonzo b _C_LABEL(panic) 436239268Sgonzo /* NOTREACHED */ 437239268Sgonzo 438239268Sgonzo.Lmpreturned: 439239268Sgonzo .asciz "main() returned" 440239268Sgonzo .align 0 441248361SandrewEND(mpentry) 442239268Sgonzo#endif 443239268Sgonzo 444135640ScognetENTRY_NP(cpu_halt) 445129198Scognet mrs r2, cpsr 446129198Scognet bic r2, r2, #(PSR_MODE) 447129198Scognet orr r2, r2, #(PSR_SVC32_MODE) 448129198Scognet orr r2, r2, #(I32_bit | F32_bit) 449261393Sian msr cpsr_fsxc, r2 450129198Scognet 451129198Scognet ldr r4, .Lcpu_reset_address 452129198Scognet ldr r4, [r4] 453129198Scognet 454129198Scognet ldr r0, .Lcpufuncs 455129198Scognet mov lr, pc 456129198Scognet ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 457183839Sraj mov lr, pc 458183839Sraj ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 459129198Scognet 460129198Scognet /* 461129198Scognet * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 462129198Scognet * necessary. 463129198Scognet */ 464129198Scognet 465129198Scognet ldr r1, .Lcpu_reset_needs_v4_MMU_disable 466129198Scognet ldr r1, [r1] 467129198Scognet cmp r1, #0 468129198Scognet mov r2, #0 469129198Scognet 470129198Scognet /* 471175983Sraj * MMU & IDC off, 32 bit program & data space 472129198Scognet * Hurl ourselves into the ROM 473129198Scognet */ 474129198Scognet mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 475129198Scognet mcr 15, 0, r0, c1, c0, 0 476129198Scognet mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 477129198Scognet mov pc, r4 478129198Scognet 479129198Scognet /* 480129198Scognet * _cpu_reset_address contains the address to branch to, to complete 481129198Scognet * the cpu reset after turning the MMU off 482129198Scognet * This variable is provided by the hardware specific code 483129198Scognet */ 484129198Scognet.Lcpu_reset_address: 485129198Scognet .word _C_LABEL(cpu_reset_address) 486129198Scognet 487129198Scognet /* 488129198Scognet * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 489129198Scognet * v4 MMU disable instruction needs executing... it is an illegal instruction 490129198Scognet * on f.e. ARM6/7 that locks up the computer in an endless illegal 491129198Scognet * instruction / data-abort / reset loop. 492129198Scognet */ 493129198Scognet.Lcpu_reset_needs_v4_MMU_disable: 494129198Scognet .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 495248361SandrewEND(cpu_halt) 496129198Scognet 497129198Scognet 498129198Scognet/* 499129198Scognet * setjump + longjmp 500129198Scognet */ 501129198ScognetENTRY(setjmp) 502129198Scognet stmia r0, {r4-r14} 503129198Scognet mov r0, #0x00000000 504137463Scognet RET 505248361SandrewEND(setjmp) 506129198Scognet 507129198ScognetENTRY(longjmp) 508129198Scognet ldmia r0, {r4-r14} 509129198Scognet mov r0, #0x00000001 510137463Scognet RET 511248361SandrewEND(longjmp) 512129198Scognet 513129198Scognet .data 514129198Scognet .global _C_LABEL(esym) 515129198Scognet_C_LABEL(esym): .word _C_LABEL(end) 516129198Scognet 517129198ScognetENTRY_NP(abort) 518129198Scognet b _C_LABEL(abort) 519248361SandrewEND(abort) 520129198Scognet 521135640ScognetENTRY_NP(sigcode) 522135640Scognet mov r0, sp 523245414Sandrew 524245414Sandrew /* 525245414Sandrew * Call the sigreturn system call. 526245414Sandrew * 527245414Sandrew * We have to load r7 manually rather than using 528245414Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 529245414Sandrew * correct. Using the alternative places esigcode at the address 530245414Sandrew * of the data rather than the address one past the data. 531245414Sandrew */ 532245414Sandrew 533245414Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 534135640Scognet swi SYS_sigreturn 535135640Scognet 536135640Scognet /* Well if that failed we better exit quick ! */ 537135640Scognet 538245414Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 539135640Scognet swi SYS_exit 540135640Scognet 541245414Sandrew /* Branch back to retry SYS_sigreturn */ 542245414Sandrew b . - 16 543245414Sandrew 544245414Sandrew .word SYS_sigreturn 545245414Sandrew .word SYS_exit 546245414Sandrew 547135640Scognet .align 0 548135640Scognet .global _C_LABEL(esigcode) 549135640Scognet _C_LABEL(esigcode): 550143681Sjmg 551135640Scognet .data 552135640Scognet .global szsigcode 553135640Scognetszsigcode: 554135640Scognet .long esigcode-sigcode 555248361SandrewEND(sigcode) 556129198Scognet/* End of locore.S */ 557