locore-v4.S revision 270862
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 270862 2014-08-30 22:21:57Z ian $"); 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 130135640Scognet adr r7, Lunmapped 131190602Scognet bic r7, r7, #0xf0000000 132153616Scognet orr r7, r7, #PHYSADDR 133143681Sjmg 134175983Sraj 135166819Scognetdisable_mmu: 136135640Scognet /* Disable MMU for a while */ 137143681Sjmg mrc p15, 0, r2, c1, c0, 0 138153550Scognet bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 139153550Scognet CPU_CONTROL_WBUF_ENABLE) 140153550Scognet bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 141153550Scognet bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 142135640Scognet mcr p15, 0, r2, c1, c0, 0 143129198Scognet 144135640Scognet nop 145135640Scognet nop 146135640Scognet nop 147135640Scognet mov pc, r7 148135640ScognetLunmapped: 149261227Sandrew /* 150261227Sandrew * Build page table from scratch. 151261227Sandrew */ 152261227Sandrew 153261855Sandrew /* Find the delta between VA and PA */ 154261855Sandrew adr r0, Lpagetable 155261855Sandrew ldr r1, [r0] 156261855Sandrew sub r2, r1, r0 157261855Sandrew /* At this point: r2 = VA - PA */ 158261855Sandrew 159261855Sandrew /* 160261855Sandrew * Find the physical address of the table. After these two 161261855Sandrew * instructions: 162261855Sandrew * r1 = va(pagetable) 163261855Sandrew * 164261855Sandrew * r0 = va(pagetable) - (VA - PA) 165261855Sandrew * = va(pagetable) - VA + PA 166261855Sandrew * = pa(pagetable) 167261855Sandrew */ 168261855Sandrew ldr r1, [r0, #4] 169261227Sandrew sub r0, r1, r2 170261227Sandrew 171266849Scognet#ifndef _ARM_ARCH_6 172261606Sandrew /* 173266849Scognet * Some of the older ports (the various XScale, mostly) assume 174266849Scognet * that the memory before the kernel is mapped, and use it for 175266849Scognet * the various stacks, page tables, etc. For those CPUs, map the 176266849Scognet * 64 first MB of RAM, as it used to be. 177266849Scognet */ 178266849Scognet /* 179261606Sandrew * Map PA == VA 180266849Scognet */ 181266849Scognet ldr r5, =PHYSADDR 182266849Scognet mov r1, r5 183266849Scognet mov r2, r5 184266849Scognet /* Map 64MiB, preserved over calls to build_pagetables */ 185266849Scognet mov r3, #64 186266849Scognet bl build_pagetables 187266849Scognet 188266849Scognet /* Create the kernel map to jump to */ 189266849Scognet mov r1, r5 190266849Scognet ldr r2, =(KERNBASE) 191266849Scognet bl build_pagetables 192266849Scognet ldr r5, =(KERNPHYSADDR) 193266849Scognet#else 194266849Scognet /* 195266849Scognet * Map PA == VA 196266849Scognet */ 197261855Sandrew /* Find the start kernels load address */ 198261855Sandrew adr r5, _start 199261855Sandrew ldr r2, =(L1_S_OFFSET) 200261855Sandrew bic r5, r2 201261606Sandrew mov r1, r5 202261606Sandrew mov r2, r5 203261606Sandrew /* Map 64MiB, preserved over calls to build_pagetables */ 204261606Sandrew mov r3, #64 205261606Sandrew bl build_pagetables 206129198Scognet 207261606Sandrew /* Create the kernel map to jump to */ 208261606Sandrew mov r1, r5 209261855Sandrew ldr r2, =(KERNVIRTADDR) 210261606Sandrew bl build_pagetables 211266849Scognet#endif 212261606Sandrew 213261606Sandrew#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 214261606Sandrew /* Create the custom map */ 215261783Simp ldr r1, =SOCDEV_PA 216261783Simp ldr r2, =SOCDEV_VA 217261606Sandrew bl build_pagetables 218261606Sandrew#endif 219129198Scognet 220239268Sgonzo#if defined(SMP) 221239268Sgonzo orr r0, r0, #2 /* Set TTB shared memory flag */ 222239268Sgonzo#endif 223129198Scognet mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 224129198Scognet mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 225129198Scognet 226259640Sganbold#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) 227239268Sgonzo mov r0, #0 228239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 229239268Sgonzo#endif 230239268Sgonzo 231129198Scognet /* Set the Domain Access register. Very important! */ 232143681Sjmg mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 233129198Scognet mcr p15, 0, r0, c3, c0, 0 234248961Sian /* 235248961Sian * Enable MMU. 236248961Sian * On armv6 enable extended page tables, and set alignment checking 237248961Sian * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd 238248961Sian * instructions emitted by clang. 239248961Sian */ 240129198Scognet mrc p15, 0, r0, c1, c0, 0 241248961Sian#ifdef _ARM_ARCH_6 242248961Sian orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE) 243256628Sian orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE) 244250928Sgber orr r0, r0, #(CPU_CONTROL_AF_ENABLE) 245239268Sgonzo#endif 246243602Sgonzo orr r0, r0, #(CPU_CONTROL_MMU_ENABLE) 247129198Scognet mcr p15, 0, r0, c1, c0, 0 248153550Scognet nop 249153550Scognet nop 250153550Scognet nop 251129198Scognet CPWAIT(r0) 252129198Scognet 253129198Scognetmmu_done: 254153550Scognet nop 255129198Scognet adr r1, .Lstart 256129198Scognet ldmia r1, {r1, r2, sp} /* Set initial stack and */ 257129198Scognet sub r2, r2, r1 /* get zero init data */ 258129198Scognet mov r3, #0 259129198Scognet.L1: 260150863Scognet str r3, [r1], #0x0004 /* get zero init data */ 261129198Scognet subs r2, r2, #4 262129198Scognet bgt .L1 263153550Scognet ldr pc, .Lvirt_done 264129198Scognet 265142145Scognetvirt_done: 266261663Sandrew mov r1, #28 /* loader info size is 28 bytes also second arg */ 267236524Simp subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 268261855Sandrew mov r0, sp /* loader info pointer is first arg */ 269247608Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 270236524Simp str r1, [r0] /* Store length of loader info */ 271236524Simp str r9, [r0, #4] /* Store r0 from boot loader */ 272236524Simp str r8, [r0, #8] /* Store r1 from boot loader */ 273236524Simp str ip, [r0, #12] /* store r2 from boot loader */ 274236524Simp str fp, [r0, #16] /* store r3 from boot loader */ 275261562Sandrew str r5, [r0, #20] /* store the physical address */ 276261855Sandrew adr r4, Lpagetable /* load the pagetable address */ 277261855Sandrew ldr r5, [r4, #4] 278261663Sandrew str r5, [r0, #24] /* store the pagetable address */ 279175983Sraj mov fp, #0 /* trace back starts here */ 280129198Scognet bl _C_LABEL(initarm) /* Off we go */ 281129198Scognet 282129198Scognet /* init arm will return the new stack pointer. */ 283129198Scognet mov sp, r0 284129198Scognet 285129198Scognet bl _C_LABEL(mi_startup) /* call mi_startup()! */ 286129198Scognet 287129198Scognet adr r0, .Lmainreturned 288130164Sphk b _C_LABEL(panic) 289175983Sraj /* NOTREACHED */ 290261606SandrewEND(_start) 291261606Sandrew 292261606Sandrew/* 293261606Sandrew * Builds the page table 294261606Sandrew * r0 - The table base address 295261606Sandrew * r1 - The physical address (trashed) 296261606Sandrew * r2 - The virtual address (trashed) 297261606Sandrew * r3 - The number of 1MiB sections 298261606Sandrew * r4 - Trashed 299261606Sandrew * 300261606Sandrew * Addresses must be 1MiB aligned 301261606Sandrew */ 302261606Sandrewbuild_pagetables: 303261606Sandrew /* Set the required page attributed */ 304261606Sandrew ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 305261606Sandrew#if defined(SMP) 306261606Sandrew orr r4, #(L1_SHARED) 307261606Sandrew#endif 308261606Sandrew orr r1, r4 309261606Sandrew 310261606Sandrew /* Move the virtual address to the correct bit location */ 311261606Sandrew lsr r2, #(L1_S_SHIFT - 2) 312261606Sandrew 313261606Sandrew mov r4, r3 314261606Sandrew1: 315261606Sandrew str r1, [r0, r2] 316261606Sandrew add r2, r2, #4 317261606Sandrew add r1, r1, #(L1_S_SIZE) 318261606Sandrew adds r4, r4, #-1 319261606Sandrew bhi 1b 320261606Sandrew 321261606Sandrew RET 322261606Sandrew 323261855SandrewLpagetable: 324261855Sandrew .word . 325261855Sandrew .word pagetable 326261855Sandrew 327150863ScognetLvirtaddr: 328150863Scognet .word KERNVIRTADDR 329150863ScognetLphysaddr: 330150863Scognet .word KERNPHYSADDR 331166819ScognetLreal_start: 332166819Scognet .word _start 333261855SandrewLend: 334166819Scognet .word _edata 335261855Sandrew 336129198Scognet.Lstart: 337129198Scognet .word _edata 338261227Sandrew .word _ebss 339129198Scognet .word svcstk + INIT_ARM_STACK_SIZE 340129198Scognet 341153550Scognet.Lvirt_done: 342153550Scognet .word virt_done 343239268Sgonzo 344129198Scognet.Lmainreturned: 345129198Scognet .asciz "main() returned" 346129198Scognet .align 0 347129198Scognet 348129198Scognet .bss 349129198Scognetsvcstk: 350129198Scognet .space INIT_ARM_STACK_SIZE 351129198Scognet 352261227Sandrew/* 353261227Sandrew * Memory for the initial pagetable. We are unable to place this in 354261227Sandrew * the bss as this will be cleared after the table is loaded. 355261227Sandrew */ 356261227Sandrew .section ".init_pagetable" 357261227Sandrew .align 14 /* 16KiB aligned */ 358261227Sandrewpagetable: 359261227Sandrew .space L1_TABLE_SIZE 360261227Sandrew 361129198Scognet .text 362129198Scognet .align 0 363129198Scognet 364143681Sjmg.Lcpufuncs: 365129198Scognet .word _C_LABEL(cpufuncs) 366129198Scognet 367239268Sgonzo#if defined(SMP) 368239268Sgonzo 369265705Sian.Lmpvirt_done: 370265705Sian .word mpvirt_done 371265705SianLstartup_pagetable_secondary: 372265705Sian .word temp_pagetable 373265705Sian 374239268SgonzoASENTRY_NP(mpentry) 375239268Sgonzo 376239268Sgonzo /* Make sure interrupts are disabled. */ 377239268Sgonzo mrs r7, cpsr 378239268Sgonzo orr r7, r7, #(I32_bit|F32_bit) 379239268Sgonzo msr cpsr_c, r7 380239268Sgonzo 381265784Sian /* Disable MMU. It should be disabled already, but make sure. */ 382239268Sgonzo mrc p15, 0, r2, c1, c0, 0 383239268Sgonzo bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 384239268Sgonzo CPU_CONTROL_WBUF_ENABLE) 385239268Sgonzo bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 386239268Sgonzo bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 387239268Sgonzo mcr p15, 0, r2, c1, c0, 0 388239268Sgonzo nop 389239268Sgonzo nop 390239268Sgonzo nop 391265784Sian CPWAIT(r0) 392239268Sgonzo 393270862Sian#if ARM_MMU_V6 394265784Sian bl armv6_idcache_inv_all /* Modifies r0 only */ 395270862Sian#elif ARM_MMU_V7 396265784Sian bl armv7_idcache_inv_all /* Modifies r0-r3, ip */ 397265784Sian#endif 398265784Sian 399239268Sgonzo ldr r0, Lstartup_pagetable_secondary 400239268Sgonzo bic r0, r0, #0xf0000000 401239268Sgonzo orr r0, r0, #PHYSADDR 402239268Sgonzo ldr r0, [r0] 403262413Sian orr r0, r0, #2 /* Set TTB shared memory flag */ 404239268Sgonzo mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 405239268Sgonzo mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 406239268Sgonzo 407239268Sgonzo mov r0, #0 408239268Sgonzo mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ 409239268Sgonzo 410239268Sgonzo /* Set the Domain Access register. Very important! */ 411239268Sgonzo mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 412239268Sgonzo mcr p15, 0, r0, c3, c0, 0 413239268Sgonzo /* Enable MMU */ 414239268Sgonzo mrc p15, 0, r0, c1, c0, 0 415239268Sgonzo orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 416258845Szbb orr r0, r0, #CPU_CONTROL_AF_ENABLE 417265784Sian orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 418265784Sian CPU_CONTROL_WBUF_ENABLE) 419265784Sian orr r0, r0, #(CPU_CONTROL_IC_ENABLE) 420265784Sian orr r0, r0, #(CPU_CONTROL_BPRD_ENABLE) 421239268Sgonzo mcr p15, 0, r0, c1, c0, 0 422239268Sgonzo nop 423239268Sgonzo nop 424239268Sgonzo nop 425239268Sgonzo CPWAIT(r0) 426239268Sgonzo 427239268Sgonzo adr r1, .Lstart 428239268Sgonzo ldmia r1, {r1, r2, sp} /* Set initial stack and */ 429239268Sgonzo mrc p15, 0, r0, c0, c0, 5 430239268Sgonzo and r0, r0, #15 431239268Sgonzo mov r1, #2048 432239268Sgonzo mul r2, r1, r0 433239268Sgonzo sub sp, sp, r2 434239268Sgonzo str r1, [sp] 435239268Sgonzo ldr pc, .Lmpvirt_done 436239268Sgonzo 437239268Sgonzompvirt_done: 438239268Sgonzo 439239268Sgonzo mov fp, #0 /* trace back starts here */ 440239268Sgonzo bl _C_LABEL(init_secondary) /* Off we go */ 441239268Sgonzo 442239268Sgonzo adr r0, .Lmpreturned 443239268Sgonzo b _C_LABEL(panic) 444239268Sgonzo /* NOTREACHED */ 445239268Sgonzo 446239268Sgonzo.Lmpreturned: 447265705Sian .asciz "init_secondary() returned" 448239268Sgonzo .align 0 449248361SandrewEND(mpentry) 450239268Sgonzo#endif 451239268Sgonzo 452135640ScognetENTRY_NP(cpu_halt) 453129198Scognet mrs r2, cpsr 454129198Scognet bic r2, r2, #(PSR_MODE) 455129198Scognet orr r2, r2, #(PSR_SVC32_MODE) 456129198Scognet orr r2, r2, #(I32_bit | F32_bit) 457261393Sian msr cpsr_fsxc, r2 458129198Scognet 459129198Scognet ldr r4, .Lcpu_reset_address 460129198Scognet ldr r4, [r4] 461129198Scognet 462129198Scognet ldr r0, .Lcpufuncs 463129198Scognet mov lr, pc 464129198Scognet ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 465183839Sraj mov lr, pc 466183839Sraj ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 467129198Scognet 468129198Scognet /* 469129198Scognet * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 470129198Scognet * necessary. 471129198Scognet */ 472129198Scognet 473129198Scognet ldr r1, .Lcpu_reset_needs_v4_MMU_disable 474129198Scognet ldr r1, [r1] 475129198Scognet cmp r1, #0 476129198Scognet mov r2, #0 477129198Scognet 478129198Scognet /* 479175983Sraj * MMU & IDC off, 32 bit program & data space 480129198Scognet * Hurl ourselves into the ROM 481129198Scognet */ 482129198Scognet mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 483129198Scognet mcr 15, 0, r0, c1, c0, 0 484129198Scognet mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 485129198Scognet mov pc, r4 486129198Scognet 487129198Scognet /* 488129198Scognet * _cpu_reset_address contains the address to branch to, to complete 489129198Scognet * the cpu reset after turning the MMU off 490129198Scognet * This variable is provided by the hardware specific code 491129198Scognet */ 492129198Scognet.Lcpu_reset_address: 493129198Scognet .word _C_LABEL(cpu_reset_address) 494129198Scognet 495129198Scognet /* 496129198Scognet * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 497129198Scognet * v4 MMU disable instruction needs executing... it is an illegal instruction 498129198Scognet * on f.e. ARM6/7 that locks up the computer in an endless illegal 499129198Scognet * instruction / data-abort / reset loop. 500129198Scognet */ 501129198Scognet.Lcpu_reset_needs_v4_MMU_disable: 502129198Scognet .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 503248361SandrewEND(cpu_halt) 504129198Scognet 505129198Scognet 506129198Scognet/* 507129198Scognet * setjump + longjmp 508129198Scognet */ 509129198ScognetENTRY(setjmp) 510129198Scognet stmia r0, {r4-r14} 511129198Scognet mov r0, #0x00000000 512137463Scognet RET 513248361SandrewEND(setjmp) 514129198Scognet 515129198ScognetENTRY(longjmp) 516129198Scognet ldmia r0, {r4-r14} 517129198Scognet mov r0, #0x00000001 518137463Scognet RET 519248361SandrewEND(longjmp) 520129198Scognet 521129198Scognet .data 522129198Scognet .global _C_LABEL(esym) 523129198Scognet_C_LABEL(esym): .word _C_LABEL(end) 524129198Scognet 525129198ScognetENTRY_NP(abort) 526129198Scognet b _C_LABEL(abort) 527248361SandrewEND(abort) 528129198Scognet 529135640ScognetENTRY_NP(sigcode) 530135640Scognet mov r0, sp 531262903Sian add r0, r0, #SIGF_UC 532245414Sandrew 533245414Sandrew /* 534245414Sandrew * Call the sigreturn system call. 535245414Sandrew * 536245414Sandrew * We have to load r7 manually rather than using 537245414Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 538245414Sandrew * correct. Using the alternative places esigcode at the address 539245414Sandrew * of the data rather than the address one past the data. 540245414Sandrew */ 541245414Sandrew 542245414Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 543135640Scognet swi SYS_sigreturn 544135640Scognet 545135640Scognet /* Well if that failed we better exit quick ! */ 546135640Scognet 547245414Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 548135640Scognet swi SYS_exit 549135640Scognet 550245414Sandrew /* Branch back to retry SYS_sigreturn */ 551245414Sandrew b . - 16 552269390SianEND(sigcode) 553245414Sandrew .word SYS_sigreturn 554245414Sandrew .word SYS_exit 555245414Sandrew 556135640Scognet .align 0 557135640Scognet .global _C_LABEL(esigcode) 558135640Scognet _C_LABEL(esigcode): 559143681Sjmg 560135640Scognet .data 561135640Scognet .global szsigcode 562135640Scognetszsigcode: 563135640Scognet .long esigcode-sigcode 564269390Sian 565129198Scognet/* End of locore.S */ 566