locore-v4.S revision 266849
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 266849 2014-05-29 16:54:15Z cognet $"); 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 */ 85266271Sgavin mov fp, r3 /* Future expansion */ 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 151261855Sandrew /* Find the delta between VA and PA */ 152261855Sandrew adr r0, Lpagetable 153261855Sandrew ldr r1, [r0] 154261855Sandrew sub r2, r1, r0 155261855Sandrew /* At this point: r2 = VA - PA */ 156261855Sandrew 157261855Sandrew /* 158261855Sandrew * Find the physical address of the table. After these two 159261855Sandrew * instructions: 160261855Sandrew * r1 = va(pagetable) 161261855Sandrew * 162261855Sandrew * r0 = va(pagetable) - (VA - PA) 163261855Sandrew * = va(pagetable) - VA + PA 164261855Sandrew * = pa(pagetable) 165261855Sandrew */ 166261855Sandrew ldr r1, [r0, #4] 167261227Sandrew sub r0, r1, r2 168261227Sandrew 169266849Scognet#ifndef _ARM_ARCH_6 170261606Sandrew /* 171266849Scognet * Some of the older ports (the various XScale, mostly) assume 172266849Scognet * that the memory before the kernel is mapped, and use it for 173266849Scognet * the various stacks, page tables, etc. For those CPUs, map the 174266849Scognet * 64 first MB of RAM, as it used to be. 175266849Scognet */ 176266849Scognet /* 177261606Sandrew * Map PA == VA 178266849Scognet */ 179266849Scognet ldr r5, =PHYSADDR 180266849Scognet mov r1, r5 181266849Scognet mov r2, r5 182266849Scognet /* Map 64MiB, preserved over calls to build_pagetables */ 183266849Scognet mov r3, #64 184266849Scognet bl build_pagetables 185266849Scognet 186266849Scognet /* Create the kernel map to jump to */ 187266849Scognet mov r1, r5 188266849Scognet ldr r2, =(KERNBASE) 189266849Scognet bl build_pagetables 190266849Scognet ldr r5, =(KERNPHYSADDR) 191266849Scognet#else 192266849Scognet /* 193266849Scognet * Map PA == VA 194266849Scognet */ 195261855Sandrew /* Find the start kernels load address */ 196261855Sandrew adr r5, _start 197261855Sandrew ldr r2, =(L1_S_OFFSET) 198261855Sandrew bic r5, r2 199261606Sandrew mov r1, r5 200261606Sandrew mov r2, r5 201261606Sandrew /* Map 64MiB, preserved over calls to build_pagetables */ 202261606Sandrew mov r3, #64 203261606Sandrew bl build_pagetables 204129198Scognet 205261606Sandrew /* Create the kernel map to jump to */ 206261606Sandrew mov r1, r5 207261855Sandrew ldr r2, =(KERNVIRTADDR) 208261606Sandrew bl build_pagetables 209266849Scognet#endif 210261606Sandrew 211261606Sandrew#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 212261606Sandrew /* Create the custom map */ 213261783Simp ldr r1, =SOCDEV_PA 214261783Simp ldr r2, =SOCDEV_VA 215261606Sandrew bl build_pagetables 216261606Sandrew#endif 217129198Scognet 218239268Sgonzo#if defined(SMP) 219239268Sgonzo orr r0, r0, #2 /* Set TTB shared memory flag */ 220239268Sgonzo#endif 221129198Scognet mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 222129198Scognet mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 223129198Scognet 224259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) 225239268Sgonzo mov r0, #0 226239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 227239268Sgonzo#endif 228239268Sgonzo 229129198Scognet /* Set the Domain Access register. Very important! */ 230143681Sjmg mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 231129198Scognet mcr p15, 0, r0, c3, c0, 0 232248961Sian /* 233248961Sian * Enable MMU. 234248961Sian * On armv6 enable extended page tables, and set alignment checking 235248961Sian * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd 236248961Sian * instructions emitted by clang. 237248961Sian */ 238129198Scognet mrc p15, 0, r0, c1, c0, 0 239248961Sian#ifdef _ARM_ARCH_6 240248961Sian orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE) 241256628Sian orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE) 242250928Sgber orr r0, r0, #(CPU_CONTROL_AF_ENABLE) 243239268Sgonzo#endif 244243602Sgonzo orr r0, r0, #(CPU_CONTROL_MMU_ENABLE) 245129198Scognet mcr p15, 0, r0, c1, c0, 0 246153550Scognet nop 247153550Scognet nop 248153550Scognet nop 249129198Scognet CPWAIT(r0) 250129198Scognet 251129198Scognetmmu_done: 252153550Scognet nop 253129198Scognet adr r1, .Lstart 254129198Scognet ldmia r1, {r1, r2, sp} /* Set initial stack and */ 255129198Scognet sub r2, r2, r1 /* get zero init data */ 256129198Scognet mov r3, #0 257129198Scognet.L1: 258150863Scognet str r3, [r1], #0x0004 /* get zero init data */ 259129198Scognet subs r2, r2, #4 260129198Scognet bgt .L1 261153550Scognet ldr pc, .Lvirt_done 262129198Scognet 263142145Scognetvirt_done: 264261663Sandrew mov r1, #28 /* loader info size is 28 bytes also second arg */ 265236524Simp subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 266261855Sandrew mov r0, sp /* loader info pointer is first arg */ 267247608Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 268236524Simp str r1, [r0] /* Store length of loader info */ 269236524Simp str r9, [r0, #4] /* Store r0 from boot loader */ 270236524Simp str r8, [r0, #8] /* Store r1 from boot loader */ 271236524Simp str ip, [r0, #12] /* store r2 from boot loader */ 272236524Simp str fp, [r0, #16] /* store r3 from boot loader */ 273261562Sandrew str r5, [r0, #20] /* store the physical address */ 274261855Sandrew adr r4, Lpagetable /* load the pagetable address */ 275261855Sandrew ldr r5, [r4, #4] 276261663Sandrew str r5, [r0, #24] /* store the pagetable address */ 277175983Sraj mov fp, #0 /* trace back starts here */ 278129198Scognet bl _C_LABEL(initarm) /* Off we go */ 279129198Scognet 280129198Scognet /* init arm will return the new stack pointer. */ 281129198Scognet mov sp, r0 282129198Scognet 283129198Scognet bl _C_LABEL(mi_startup) /* call mi_startup()! */ 284129198Scognet 285129198Scognet adr r0, .Lmainreturned 286130164Sphk b _C_LABEL(panic) 287175983Sraj /* NOTREACHED */ 288261606SandrewEND(btext) 289261606SandrewEND(_start) 290261606Sandrew 291261606Sandrew/* 292261606Sandrew * Builds the page table 293261606Sandrew * r0 - The table base address 294261606Sandrew * r1 - The physical address (trashed) 295261606Sandrew * r2 - The virtual address (trashed) 296261606Sandrew * r3 - The number of 1MiB sections 297261606Sandrew * r4 - Trashed 298261606Sandrew * 299261606Sandrew * Addresses must be 1MiB aligned 300261606Sandrew */ 301261606Sandrewbuild_pagetables: 302261606Sandrew /* Set the required page attributed */ 303261606Sandrew ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 304261606Sandrew#if defined(SMP) 305261606Sandrew orr r4, #(L1_SHARED) 306261606Sandrew#endif 307261606Sandrew orr r1, r4 308261606Sandrew 309261606Sandrew /* Move the virtual address to the correct bit location */ 310261606Sandrew lsr r2, #(L1_S_SHIFT - 2) 311261606Sandrew 312261606Sandrew mov r4, r3 313261606Sandrew1: 314261606Sandrew str r1, [r0, r2] 315261606Sandrew add r2, r2, #4 316261606Sandrew add r1, r1, #(L1_S_SIZE) 317261606Sandrew adds r4, r4, #-1 318261606Sandrew bhi 1b 319261606Sandrew 320261606Sandrew RET 321261606Sandrew 322261855SandrewLpagetable: 323261855Sandrew .word . 324261855Sandrew .word pagetable 325261855Sandrew 326150863ScognetLvirtaddr: 327150863Scognet .word KERNVIRTADDR 328150863ScognetLphysaddr: 329150863Scognet .word KERNPHYSADDR 330166819ScognetLreal_start: 331166819Scognet .word _start 332261855SandrewLend: 333166819Scognet .word _edata 334261855Sandrew 335129198Scognet.Lstart: 336129198Scognet .word _edata 337261227Sandrew .word _ebss 338129198Scognet .word svcstk + INIT_ARM_STACK_SIZE 339129198Scognet 340153550Scognet.Lvirt_done: 341153550Scognet .word virt_done 342239268Sgonzo 343129198Scognet.Lmainreturned: 344129198Scognet .asciz "main() returned" 345129198Scognet .align 0 346129198Scognet 347129198Scognet .bss 348129198Scognetsvcstk: 349129198Scognet .space INIT_ARM_STACK_SIZE 350129198Scognet 351261227Sandrew/* 352261227Sandrew * Memory for the initial pagetable. We are unable to place this in 353261227Sandrew * the bss as this will be cleared after the table is loaded. 354261227Sandrew */ 355261227Sandrew .section ".init_pagetable" 356261227Sandrew .align 14 /* 16KiB aligned */ 357261227Sandrewpagetable: 358261227Sandrew .space L1_TABLE_SIZE 359261227Sandrew 360129198Scognet .text 361129198Scognet .align 0 362129198Scognet 363143681Sjmg.Lcpufuncs: 364129198Scognet .word _C_LABEL(cpufuncs) 365129198Scognet 366239268Sgonzo#if defined(SMP) 367239268Sgonzo 368265705Sian.Lmpvirt_done: 369265705Sian .word mpvirt_done 370265705SianLstartup_pagetable_secondary: 371265705Sian .word temp_pagetable 372265705Sian 373239268SgonzoASENTRY_NP(mpentry) 374239268Sgonzo 375239268Sgonzo /* Make sure interrupts are disabled. */ 376239268Sgonzo mrs r7, cpsr 377239268Sgonzo orr r7, r7, #(I32_bit|F32_bit) 378239268Sgonzo msr cpsr_c, r7 379239268Sgonzo 380265784Sian /* Disable MMU. It should be disabled already, but make sure. */ 381239268Sgonzo mrc p15, 0, r2, c1, c0, 0 382239268Sgonzo bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 383239268Sgonzo CPU_CONTROL_WBUF_ENABLE) 384239268Sgonzo bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 385239268Sgonzo bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 386239268Sgonzo mcr p15, 0, r2, c1, c0, 0 387239268Sgonzo nop 388239268Sgonzo nop 389239268Sgonzo nop 390265784Sian CPWAIT(r0) 391239268Sgonzo 392265784Sian#if defined(ARM_MMU_V6) 393265784Sian bl armv6_idcache_inv_all /* Modifies r0 only */ 394265784Sian#elif defined(ARM_MMU_V7) 395265784Sian bl armv7_idcache_inv_all /* Modifies r0-r3, ip */ 396265784Sian#endif 397265784Sian 398239268Sgonzo ldr r0, Lstartup_pagetable_secondary 399239268Sgonzo bic r0, r0, #0xf0000000 400239268Sgonzo orr r0, r0, #PHYSADDR 401239268Sgonzo ldr r0, [r0] 402262413Sian orr r0, r0, #2 /* Set TTB shared memory flag */ 403239268Sgonzo mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 404239268Sgonzo mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 405239268Sgonzo 406239268Sgonzo mov r0, #0 407239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 408239268Sgonzo 409239268Sgonzo /* Set the Domain Access register. Very important! */ 410239268Sgonzo mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 411239268Sgonzo mcr p15, 0, r0, c3, c0, 0 412239268Sgonzo /* Enable MMU */ 413239268Sgonzo mrc p15, 0, r0, c1, c0, 0 414239268Sgonzo orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 415258845Szbb orr r0, r0, #CPU_CONTROL_AF_ENABLE 416265784Sian orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 417265784Sian CPU_CONTROL_WBUF_ENABLE) 418265784Sian orr r0, r0, #(CPU_CONTROL_IC_ENABLE) 419265784Sian orr r0, r0, #(CPU_CONTROL_BPRD_ENABLE) 420239268Sgonzo mcr p15, 0, r0, c1, c0, 0 421239268Sgonzo nop 422239268Sgonzo nop 423239268Sgonzo nop 424239268Sgonzo CPWAIT(r0) 425239268Sgonzo 426239268Sgonzo adr r1, .Lstart 427239268Sgonzo ldmia r1, {r1, r2, sp} /* Set initial stack and */ 428239268Sgonzo mrc p15, 0, r0, c0, c0, 5 429239268Sgonzo and r0, r0, #15 430239268Sgonzo mov r1, #2048 431239268Sgonzo mul r2, r1, r0 432239268Sgonzo sub sp, sp, r2 433239268Sgonzo str r1, [sp] 434239268Sgonzo ldr pc, .Lmpvirt_done 435239268Sgonzo 436239268Sgonzompvirt_done: 437239268Sgonzo 438239268Sgonzo mov fp, #0 /* trace back starts here */ 439239268Sgonzo bl _C_LABEL(init_secondary) /* Off we go */ 440239268Sgonzo 441239268Sgonzo adr r0, .Lmpreturned 442239268Sgonzo b _C_LABEL(panic) 443239268Sgonzo /* NOTREACHED */ 444239268Sgonzo 445239268Sgonzo.Lmpreturned: 446265705Sian .asciz "init_secondary() returned" 447239268Sgonzo .align 0 448248361SandrewEND(mpentry) 449239268Sgonzo#endif 450239268Sgonzo 451135640ScognetENTRY_NP(cpu_halt) 452129198Scognet mrs r2, cpsr 453129198Scognet bic r2, r2, #(PSR_MODE) 454129198Scognet orr r2, r2, #(PSR_SVC32_MODE) 455129198Scognet orr r2, r2, #(I32_bit | F32_bit) 456261393Sian msr cpsr_fsxc, r2 457129198Scognet 458129198Scognet ldr r4, .Lcpu_reset_address 459129198Scognet ldr r4, [r4] 460129198Scognet 461129198Scognet ldr r0, .Lcpufuncs 462129198Scognet mov lr, pc 463129198Scognet ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 464183839Sraj mov lr, pc 465183839Sraj ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 466129198Scognet 467129198Scognet /* 468129198Scognet * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 469129198Scognet * necessary. 470129198Scognet */ 471129198Scognet 472129198Scognet ldr r1, .Lcpu_reset_needs_v4_MMU_disable 473129198Scognet ldr r1, [r1] 474129198Scognet cmp r1, #0 475129198Scognet mov r2, #0 476129198Scognet 477129198Scognet /* 478175983Sraj * MMU & IDC off, 32 bit program & data space 479129198Scognet * Hurl ourselves into the ROM 480129198Scognet */ 481129198Scognet mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 482129198Scognet mcr 15, 0, r0, c1, c0, 0 483129198Scognet mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 484129198Scognet mov pc, r4 485129198Scognet 486129198Scognet /* 487129198Scognet * _cpu_reset_address contains the address to branch to, to complete 488129198Scognet * the cpu reset after turning the MMU off 489129198Scognet * This variable is provided by the hardware specific code 490129198Scognet */ 491129198Scognet.Lcpu_reset_address: 492129198Scognet .word _C_LABEL(cpu_reset_address) 493129198Scognet 494129198Scognet /* 495129198Scognet * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 496129198Scognet * v4 MMU disable instruction needs executing... it is an illegal instruction 497129198Scognet * on f.e. ARM6/7 that locks up the computer in an endless illegal 498129198Scognet * instruction / data-abort / reset loop. 499129198Scognet */ 500129198Scognet.Lcpu_reset_needs_v4_MMU_disable: 501129198Scognet .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 502248361SandrewEND(cpu_halt) 503129198Scognet 504129198Scognet 505129198Scognet/* 506129198Scognet * setjump + longjmp 507129198Scognet */ 508129198ScognetENTRY(setjmp) 509129198Scognet stmia r0, {r4-r14} 510129198Scognet mov r0, #0x00000000 511137463Scognet RET 512248361SandrewEND(setjmp) 513129198Scognet 514129198ScognetENTRY(longjmp) 515129198Scognet ldmia r0, {r4-r14} 516129198Scognet mov r0, #0x00000001 517137463Scognet RET 518248361SandrewEND(longjmp) 519129198Scognet 520129198Scognet .data 521129198Scognet .global _C_LABEL(esym) 522129198Scognet_C_LABEL(esym): .word _C_LABEL(end) 523129198Scognet 524129198ScognetENTRY_NP(abort) 525129198Scognet b _C_LABEL(abort) 526248361SandrewEND(abort) 527129198Scognet 528135640ScognetENTRY_NP(sigcode) 529135640Scognet mov r0, sp 530262903Sian add r0, r0, #SIGF_UC 531245414Sandrew 532245414Sandrew /* 533245414Sandrew * Call the sigreturn system call. 534245414Sandrew * 535245414Sandrew * We have to load r7 manually rather than using 536245414Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 537245414Sandrew * correct. Using the alternative places esigcode at the address 538245414Sandrew * of the data rather than the address one past the data. 539245414Sandrew */ 540245414Sandrew 541245414Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 542135640Scognet swi SYS_sigreturn 543135640Scognet 544135640Scognet /* Well if that failed we better exit quick ! */ 545135640Scognet 546245414Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 547135640Scognet swi SYS_exit 548135640Scognet 549245414Sandrew /* Branch back to retry SYS_sigreturn */ 550245414Sandrew b . - 16 551245414Sandrew 552245414Sandrew .word SYS_sigreturn 553245414Sandrew .word SYS_exit 554245414Sandrew 555135640Scognet .align 0 556135640Scognet .global _C_LABEL(esigcode) 557135640Scognet _C_LABEL(esigcode): 558143681Sjmg 559135640Scognet .data 560135640Scognet .global szsigcode 561135640Scognetszsigcode: 562135640Scognet .long esigcode-sigcode 563248361SandrewEND(sigcode) 564129198Scognet/* End of locore.S */ 565