1276396Sian/*- 2276396Sian * Copyright 2004-2014 Olivier Houchard <cognet@FreeBSD.org> 3276396Sian * Copyright 2012-2014 Ian Lepore <ian@FreeBSD.org> 4276396Sian * Copyright 2013-2014 Andrew Turner <andrew@FreeBSD.org> 5276396Sian * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com> 6276396Sian * Copyright 2014 Michal Meloun <meloun@miracle.cz> 7276396Sian * All rights reserved. 8276396Sian * 9276396Sian * Redistribution and use in source and binary forms, with or without 10276396Sian * modification, are permitted provided that the following conditions 11276396Sian * are met: 12276396Sian * 1. Redistributions of source code must retain the above copyright 13276396Sian * notice, this list of conditions and the following disclaimer. 14276396Sian * 2. Redistributions in binary form must reproduce the above copyright 15276396Sian * notice, this list of conditions and the following disclaimer in the 16276396Sian * documentation and/or other materials provided with the distribution. 17276396Sian * 18276396Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19276396Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20276396Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21276396Sian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22276396Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23276396Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24276396Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25276396Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26276396Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27276396Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28276396Sian * SUCH DAMAGE. 29276396Sian */ 30276396Sian 31276396Sian#include "assym.s" 32276396Sian#include <sys/syscall.h> 33276396Sian#include <machine/asm.h> 34276396Sian#include <machine/asmacros.h> 35276396Sian#include <machine/armreg.h> 36276396Sian#include <machine/sysreg.h> 37295801Sskra#include <machine/pte-v6.h> 38276396Sian 39276396Sian__FBSDID("$FreeBSD: stable/11/sys/arm/arm/locore-v6.S 327667 2018-01-07 02:57:35Z ian $"); 40276396Sian 41327667Sian/* We map 64MB of kernel unless overridden in assym.s by the kernel option. */ 42327667Sian#ifndef LOCORE_MAP_MB 43327667Sian#define LOCORE_MAP_MB 64 44327667Sian#endif 45276396Sian 46287127Szbb#if __ARM_ARCH >= 7 47287127Szbb#if defined(__ARM_ARCH_7VE__) || defined(__clang__) 48287127Szbb/* 49287127Szbb * HYP support is in bintuils >= 2.21 and gcc >= 4.9 defines __ARM_ARCH_7VE__ 50287127Szbb * when enabled. llvm >= 3.6 supports it too. 51287127Szbb */ 52287127Szbb.arch_extension virt 53287127Szbb#define MSR_ELR_HYP(regnum) msr elr_hyp, lr 54287127Szbb#define ERET eret 55287127Szbb#else 56287127Szbb#define MSR_ELR_HYP(regnum) .word (0xe12ef300 | regnum) 57287127Szbb#define ERET .word 0xe160006e 58287127Szbb#endif 59287127Szbb#endif /* __ARM_ARCH >= 7 */ 60287127Szbb 61276396Sian/* A small statically-allocated stack used only during initarm() and AP startup. */ 62276396Sian#define INIT_ARM_STACK_SIZE 2048 63276396Sian 64276396Sian .text 65276596Sian .align 2 66276396Sian 67287127Szbb#if __ARM_ARCH >= 7 68287322Sandrew#define LEAVE_HYP \ 69287322Sandrew /* Leave HYP mode */ ;\ 70287322Sandrew mrs r0, cpsr ;\ 71287322Sandrew and r0, r0, #(PSR_MODE) /* Mode is in the low 5 bits of CPSR */ ;\ 72287322Sandrew teq r0, #(PSR_HYP32_MODE) /* Hyp Mode? */ ;\ 73287322Sandrew bne 1f ;\ 74287322Sandrew /* Ensure that IRQ, FIQ and Aborts will be disabled after eret */ ;\ 75290167Sgonzo mrs r0, cpsr ;\ 76290167Sgonzo bic r0, r0, #(PSR_MODE) ;\ 77290167Sgonzo orr r0, r0, #(PSR_SVC32_MODE) ;\ 78287322Sandrew orr r0, r0, #(PSR_I | PSR_F | PSR_A) ;\ 79290167Sgonzo msr spsr_cxsf, r0 ;\ 80287322Sandrew /* Exit hypervisor mode */ ;\ 81287322Sandrew adr lr, 1f ;\ 82287322Sandrew MSR_ELR_HYP(14) ;\ 83287322Sandrew ERET ;\ 84287127Szbb1: 85287127Szbb#else 86287322Sandrew#define LEAVE_HYP 87287127Szbb#endif /* __ARM_ARCH >= 7 */ 88287127Szbb 89276396Sian/* 90282024Sandrew * On entry for FreeBSD boot ABI: 91282024Sandrew * r0 - metadata pointer or 0 (boothowto on AT91's boot2) 92282024Sandrew * r1 - if (r0 == 0) then metadata pointer 93282024Sandrew * On entry for Linux boot ABI: 94276396Sian * r0 - 0 95276396Sian * r1 - machine type (passed as arg2 to initarm) 96282024Sandrew * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) 97276396Sian * 98276396Sian * For both types of boot we gather up the args, put them in a struct arm_boot_params 99276396Sian * structure and pass that to initarm. 100276396Sian */ 101276396Sian .globl btext 102276396Sianbtext: 103276396SianASENTRY_NP(_start) 104282024Sandrew STOP_UNWINDING /* Can't unwind into the bootloader! */ 105276396Sian 106282024Sandrew /* Make sure interrupts are disabled. */ 107276396Sian cpsid ifa 108276396Sian 109282024Sandrew mov r8, r0 /* 0 or boot mode from boot2 */ 110282024Sandrew mov r9, r1 /* Save Machine type */ 111282024Sandrew mov r10, r2 /* Save meta data */ 112276396Sian mov r11, r3 /* Future expansion */ 113276396Sian 114287127Szbb LEAVE_HYP 115287127Szbb 116282024Sandrew /* 117276396Sian * Check whether data cache is enabled. If it is, then we know 118276396Sian * current tags are valid (not power-on garbage values) and there 119276396Sian * might be dirty lines that need cleaning. Disable cache to prevent 120276396Sian * new lines being allocated, then call wbinv_poc_all to clean it. 121276396Sian */ 122276396Sian mrc CP15_SCTLR(r7) 123276396Sian tst r7, #CPU_CONTROL_DC_ENABLE 124276445Sian blne dcache_wbinv_poc_all 125276396Sian 126276445Sian /* ! Do not write to memory between wbinv and disabling cache ! */ 127276445Sian 128276396Sian /* 129276396Sian * Now there are no dirty lines, but there may still be lines marked 130276396Sian * valid. Disable all caches and the MMU, and invalidate everything 131276396Sian * before setting up new page tables and re-enabling the mmu. 132276396Sian */ 133282025Sandrew1: 134276445Sian bic r7, #CPU_CONTROL_DC_ENABLE 135300701Sian bic r7, #CPU_CONTROL_AFLT_ENABLE 136276396Sian bic r7, #CPU_CONTROL_MMU_ENABLE 137276396Sian bic r7, #CPU_CONTROL_IC_ENABLE 138276396Sian bic r7, #CPU_CONTROL_BPRD_ENABLE 139276396Sian bic r7, #CPU_CONTROL_SW_ENABLE 140295256Smmel orr r7, #CPU_CONTROL_UNAL_ENABLE 141276396Sian orr r7, #CPU_CONTROL_VECRELOC 142276396Sian mcr CP15_SCTLR(r7) 143290647Smmel DSB 144276396Sian ISB 145276396Sian bl dcache_inv_poc_all 146276396Sian mcr CP15_ICIALLU 147290647Smmel DSB 148276396Sian ISB 149276396Sian 150276396Sian /* 151276396Sian * Build page table from scratch. 152276396Sian */ 153276396Sian 154292891Sian /* 155292891Sian * Figure out the physical address we're loaded at by assuming this 156292891Sian * entry point code is in the first L1 section and so if we clear the 157292891Sian * offset bits of the pc that will give us the section-aligned load 158292891Sian * address, which remains in r5 throughout all the following code. 159292891Sian */ 160292891Sian ldr r2, =(L1_S_OFFSET) 161292891Sian bic r5, pc, r2 162292891Sian 163292891Sian /* Find the delta between VA and PA, result stays in r0 throughout. */ 164276396Sian adr r0, Lpagetable 165276396Sian bl translate_va_to_pa 166276396Sian 167292891Sian /* 168292891Sian * First map the entire 4GB address space as VA=PA. It's mapped as 169292891Sian * normal (cached) memory because it's for things like accessing the 170292891Sian * parameters passed in from the bootloader, which might be at any 171292891Sian * physical address, different for every platform. 172276396Sian */ 173292891Sian mov r1, #0 174292891Sian mov r2, #0 175292891Sian mov r3, #4096 176276396Sian bl build_pagetables 177276396Sian 178292891Sian /* 179327667Sian * Next we map the kernel starting at the physical load address, mapped 180327667Sian * to the VA the kernel is linked for. The default size we map is 64MiB 181327667Sian * but it can be overridden with a kernel option. 182292891Sian */ 183276396Sian mov r1, r5 184276396Sian ldr r2, =(KERNVIRTADDR) 185327667Sian ldr r3, =(LOCORE_MAP_MB) 186276396Sian bl build_pagetables 187276396Sian 188292891Sian /* Create a device mapping for early_printf if specified. */ 189276396Sian#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 190276396Sian ldr r1, =SOCDEV_PA 191276396Sian ldr r2, =SOCDEV_VA 192290647Smmel mov r3, #1 193292891Sian bl build_device_pagetables 194276396Sian#endif 195276396Sian bl init_mmu 196276396Sian 197292891Sian /* Transition the PC from physical to virtual addressing. */ 198276396Sian ldr pc, =1f 199276396Sian1: 200276396Sian 201282024Sandrew /* Setup stack, clear BSS */ 202276396Sian ldr r1, =.Lstart 203276396Sian ldmia r1, {r1, r2, sp} /* Set initial stack and */ 204276396Sian add sp, sp, #INIT_ARM_STACK_SIZE 205282024Sandrew sub r2, r2, r1 /* get zero init data */ 206276396Sian mov r3, #0 207276396Sian2: 208276396Sian str r3, [r1], #0x0004 /* get zero init data */ 209282024Sandrew subs r2, r2, #4 210276396Sian bgt 2b 211276396Sian 212282024Sandrew mov r1, #28 /* loader info size is 28 bytes also second arg */ 213282024Sandrew subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 214282024Sandrew mov r0, sp /* loader info pointer is first arg */ 215282024Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 216282024Sandrew str r1, [r0] /* Store length of loader info */ 217276396Sian str r8, [r0, #4] /* Store r0 from boot loader */ 218276396Sian str r9, [r0, #8] /* Store r1 from boot loader */ 219276396Sian str r10, [r0, #12] /* store r2 from boot loader */ 220276396Sian str r11, [r0, #16] /* store r3 from boot loader */ 221276396Sian str r5, [r0, #20] /* store the physical address */ 222282024Sandrew adr r4, Lpagetable /* load the pagetable address */ 223276396Sian ldr r5, [r4, #4] 224276396Sian str r5, [r0, #24] /* store the pagetable address */ 225276396Sian mov fp, #0 /* trace back starts here */ 226276396Sian bl _C_LABEL(initarm) /* Off we go */ 227276396Sian 228282024Sandrew /* init arm will return the new stack pointer. */ 229276396Sian mov sp, r0 230276396Sian 231282024Sandrew bl _C_LABEL(mi_startup) /* call mi_startup()! */ 232276396Sian 233276396Sian ldr r0, =.Lmainreturned 234276396Sian b _C_LABEL(panic) 235276396Sian /* NOTREACHED */ 236276396SianEND(_start) 237276396Sian 238276396Sian#define VA_TO_PA_POINTER(name, table) \ 239276396Sianname: ;\ 240276396Sian .word . ;\ 241276396Sian .word table 242276396Sian 243276396Sian/* 244276396Sian * Returns the physical address of a magic va to pa pointer. 245276396Sian * r0 - The pagetable data pointer. This must be built using the 246276396Sian * VA_TO_PA_POINTER macro. 247276396Sian * e.g. 248276396Sian * VA_TO_PA_POINTER(Lpagetable, pagetable) 249276396Sian * ... 250276396Sian * adr r0, Lpagetable 251276396Sian * bl translate_va_to_pa 252276396Sian * r0 will now contain the physical address of pagetable 253276396Sian * r1, r2 - Trashed 254276396Sian */ 255276396Siantranslate_va_to_pa: 256276396Sian ldr r1, [r0] 257276396Sian sub r2, r1, r0 258276396Sian /* At this point: r2 = VA - PA */ 259276396Sian 260276396Sian /* 261276396Sian * Find the physical address of the table. After these two 262276396Sian * instructions: 263276396Sian * r1 = va(pagetable) 264276396Sian * 265276396Sian * r0 = va(pagetable) - (VA - PA) 266276396Sian * = va(pagetable) - VA + PA 267276396Sian * = pa(pagetable) 268276396Sian */ 269276396Sian ldr r1, [r0, #4] 270276396Sian sub r0, r1, r2 271276396Sian mov pc, lr 272276396Sian 273276396Sian/* 274282024Sandrew * Init MMU 275282024Sandrew * r0 - the table base address 276276396Sian */ 277276396Sian 278276396SianASENTRY_NP(init_mmu) 279276396Sian 280276396Sian /* Setup TLB and MMU registers */ 281276396Sian mcr CP15_TTBR0(r0) /* Set TTB */ 282276396Sian mov r0, #0 283276396Sian mcr CP15_CONTEXTIDR(r0) /* Set ASID to 0 */ 284276396Sian 285276396Sian /* Set the Domain Access register */ 286295703Sskra mov r0, #DOMAIN_CLIENT /* Only domain #0 is used */ 287276396Sian mcr CP15_DACR(r0) 288276396Sian 289276396Sian /* 290276396Sian * Set TEX remap registers 291276396Sian * - All is set to uncacheable memory 292276396Sian */ 293276396Sian ldr r0, =0xAAAAA 294284452Sandrew mcr CP15_PRRR(r0) 295276396Sian mov r0, #0 296276396Sian mcr CP15_NMRR(r0) 297276396Sian mcr CP15_TLBIALL /* Flush TLB */ 298276396Sian DSB 299276396Sian ISB 300276396Sian 301276396Sian /* Enable MMU */ 302276396Sian mrc CP15_SCTLR(r0) 303276396Sian orr r0, r0, #CPU_CONTROL_MMU_ENABLE 304276396Sian orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 305276396Sian orr r0, r0, #CPU_CONTROL_TR_ENABLE 306276396Sian orr r0, r0, #CPU_CONTROL_AF_ENABLE 307276396Sian mcr CP15_SCTLR(r0) 308276396Sian DSB 309276396Sian ISB 310276396Sian mcr CP15_TLBIALL /* Flush TLB */ 311276396Sian mcr CP15_BPIALL /* Flush Branch predictor */ 312290647Smmel DSB 313276396Sian ISB 314290647Smmel 315276396Sian mov pc, lr 316276396SianEND(init_mmu) 317276396Sian 318276396Sian 319276396Sian/* 320282024Sandrew * Init SMP coherent mode, enable caching and switch to final MMU table. 321282024Sandrew * Called with disabled caches 322282024Sandrew * r0 - The table base address 323282024Sandrew * r1 - clear bits for aux register 324282024Sandrew * r2 - set bits for aux register 325276396Sian */ 326276396SianASENTRY_NP(reinit_mmu) 327276396Sian push {r4-r11, lr} 328276396Sian mov r4, r0 329276396Sian mov r5, r1 330276396Sian mov r6, r2 331276396Sian 332276396Sian /* !! Be very paranoid here !! */ 333276396Sian /* !! We cannot write single bit here !! */ 334276396Sian 335276396Sian#if 0 /* XXX writeback shouldn't be necessary */ 336276396Sian /* Write back and invalidate all integrated caches */ 337276396Sian bl dcache_wbinv_poc_all 338276396Sian#else 339276396Sian bl dcache_inv_pou_all 340276396Sian#endif 341276396Sian mcr CP15_ICIALLU 342290647Smmel DSB 343276396Sian ISB 344276396Sian 345276396Sian /* Set auxiliary register */ 346276396Sian mrc CP15_ACTLR(r7) 347276396Sian bic r8, r7, r5 /* Mask bits */ 348276396Sian eor r8, r8, r6 /* Set bits */ 349276396Sian teq r7, r8 350276396Sian mcrne CP15_ACTLR(r8) 351290647Smmel DSB 352276396Sian ISB 353276396Sian 354276396Sian /* Enable caches. */ 355276396Sian mrc CP15_SCTLR(r7) 356276396Sian orr r7, #CPU_CONTROL_DC_ENABLE 357276396Sian orr r7, #CPU_CONTROL_IC_ENABLE 358276396Sian orr r7, #CPU_CONTROL_BPRD_ENABLE 359276396Sian mcr CP15_SCTLR(r7) 360276396Sian DSB 361276396Sian 362276396Sian mcr CP15_TTBR0(r4) /* Set new TTB */ 363276396Sian DSB 364276396Sian ISB 365276396Sian 366290647Smmel mcr CP15_TLBIALL /* Flush TLB */ 367290647Smmel mcr CP15_BPIALL /* Flush Branch predictor */ 368276396Sian DSB 369276396Sian ISB 370276396Sian 371276396Sian#if 0 /* XXX writeback shouldn't be necessary */ 372276396Sian /* Write back and invalidate all integrated caches */ 373276396Sian bl dcache_wbinv_poc_all 374276396Sian#else 375276396Sian bl dcache_inv_pou_all 376276396Sian#endif 377276396Sian mcr CP15_ICIALLU 378290647Smmel DSB 379276396Sian ISB 380276396Sian 381276396Sian pop {r4-r11, pc} 382276396SianEND(reinit_mmu) 383276396Sian 384276396Sian 385276396Sian/* 386276396Sian * Builds the page table 387282024Sandrew * r0 - The table base address 388282024Sandrew * r1 - The physical address (trashed) 389282024Sandrew * r2 - The virtual address (trashed) 390282024Sandrew * r3 - The number of 1MiB sections 391282024Sandrew * r4 - Trashed 392276396Sian * 393276396Sian * Addresses must be 1MiB aligned 394276396Sian */ 395292891Sianbuild_device_pagetables: 396292891Sian ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 397292891Sian b 1f 398276470Sianbuild_pagetables: 399276396Sian /* Set the required page attributed */ 400276396Sian ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 401292891Sian1: 402276396Sian orr r1, r4 403276396Sian 404282024Sandrew /* Move the virtual address to the correct bit location */ 405276396Sian lsr r2, #(PTE1_SHIFT - 2) 406276396Sian 407276396Sian mov r4, r3 408292891Sian2: 409276396Sian str r1, [r0, r2] 410282024Sandrew add r2, r2, #4 411282024Sandrew add r1, r1, #(PTE1_SIZE) 412282024Sandrew adds r4, r4, #-1 413292891Sian bhi 2b 414276396Sian 415276396Sian mov pc, lr 416276396Sian 417276396SianVA_TO_PA_POINTER(Lpagetable, boot_pt1) 418276396Sian 419276396Sian 420276396Sian.Lstart: 421277305Sian .word _edata /* Note that these three items are */ 422277305Sian .word _ebss /* loaded with a single ldmia and */ 423277305Sian .word svcstk /* must remain in order together. */ 424276396Sian 425276396Sian.Lmainreturned: 426282024Sandrew .asciz "main() returned" 427276596Sian .align 2 428276396Sian 429276396Sian .bss 430276396Siansvcstk: 431276396Sian .space INIT_ARM_STACK_SIZE * MAXCPU 432276396Sian 433276396Sian/* 434282024Sandrew * Memory for the initial pagetable. We are unable to place this in 435282024Sandrew * the bss as this will be cleared after the table is loaded. 436276396Sian */ 437321049Semaste .section ".init_pagetable", "aw", %nobits 438276396Sian .align 14 /* 16KiB aligned */ 439276396Sian .globl boot_pt1 440276396Sianboot_pt1: 441276396Sian .space L1_TABLE_SIZE 442276396Sian 443276396Sian .text 444276596Sian .align 2 445276396Sian 446276396Sian#if defined(SMP) 447276396Sian 448276396SianASENTRY_NP(mpentry) 449282024Sandrew /* Make sure interrupts are disabled. */ 450276396Sian cpsid ifa 451276396Sian 452287127Szbb LEAVE_HYP 453287127Szbb 454276396Sian /* Setup core, disable all caches. */ 455276396Sian mrc CP15_SCTLR(r0) 456276396Sian bic r0, #CPU_CONTROL_MMU_ENABLE 457300701Sian bic r0, #CPU_CONTROL_AFLT_ENABLE 458276396Sian bic r0, #CPU_CONTROL_DC_ENABLE 459276396Sian bic r0, #CPU_CONTROL_IC_ENABLE 460276396Sian bic r0, #CPU_CONTROL_BPRD_ENABLE 461276396Sian bic r0, #CPU_CONTROL_SW_ENABLE 462295256Smmel orr r0, #CPU_CONTROL_UNAL_ENABLE 463276396Sian orr r0, #CPU_CONTROL_VECRELOC 464276396Sian mcr CP15_SCTLR(r0) 465290647Smmel DSB 466276396Sian ISB 467276396Sian 468276396Sian /* Invalidate L1 cache I+D cache */ 469276396Sian bl dcache_inv_pou_all 470276396Sian mcr CP15_ICIALLU 471290647Smmel DSB 472276396Sian ISB 473276396Sian 474282024Sandrew /* Find the delta between VA and PA */ 475276396Sian adr r0, Lpagetable 476276396Sian bl translate_va_to_pa 477282025Sandrew 478276396Sian bl init_mmu 479276396Sian 480277305Sian adr r1, .Lstart+8 /* Get initstack pointer from */ 481277305Sian ldr sp, [r1] /* startup data. */ 482277305Sian mrc CP15_MPIDR(r0) /* Get processor id number. */ 483277305Sian and r0, r0, #0x0f 484276396Sian mov r1, #INIT_ARM_STACK_SIZE 485277305Sian mul r2, r1, r0 /* Point sp to initstack */ 486277305Sian add sp, sp, r2 /* area for this processor. */ 487276396Sian 488282024Sandrew /* Switch to virtual addresses. */ 489276396Sian ldr pc, =1f 490276396Sian1: 491276396Sian mov fp, #0 /* trace back starts here */ 492277305Sian bl _C_LABEL(init_secondary)/* Off we go, cpu id in r0. */ 493276396Sian 494276396Sian adr r0, .Lmpreturned 495276396Sian b _C_LABEL(panic) 496276396Sian /* NOTREACHED */ 497276596SianEND(mpentry) 498276396Sian 499276396Sian.Lmpreturned: 500276396Sian .asciz "init_secondary() returned" 501276596Sian .align 2 502276396Sian#endif 503276396Sian 504276396SianENTRY_NP(cpu_halt) 505276396Sian 506276396Sian /* XXX re-implement !!! */ 507276396Sian cpsid ifa 508276396Sian bl dcache_wbinv_poc_all 509276396Sian 510276396Sian ldr r4, .Lcpu_reset_address 511276396Sian ldr r4, [r4] 512276396Sian teq r4, #0 513276396Sian movne pc, r4 514282025Sandrew1: 515276519Sian WFI 516276396Sian b 1b 517276396Sian 518276396Sian /* 519276396Sian * _cpu_reset_address contains the address to branch to, to complete 520276396Sian * the cpu reset after turning the MMU off 521282024Sandrew * This variable is provided by the hardware specific code 522276396Sian */ 523276396Sian.Lcpu_reset_address: 524276396Sian .word _C_LABEL(cpu_reset_address) 525276396SianEND(cpu_halt) 526276396Sian 527276396Sian 528276396Sian/* 529276396Sian * setjump + longjmp 530276396Sian */ 531276396SianENTRY(setjmp) 532276396Sian stmia r0, {r4-r14} 533276396Sian mov r0, #0x00000000 534276396Sian RET 535276396SianEND(setjmp) 536276396Sian 537276396SianENTRY(longjmp) 538276396Sian ldmia r0, {r4-r14} 539276396Sian mov r0, #0x00000001 540276396Sian RET 541276396SianEND(longjmp) 542276396Sian 543276396Sian .data 544276396Sian .global _C_LABEL(esym) 545276396Sian_C_LABEL(esym): .word _C_LABEL(end) 546276396Sian 547276396SianENTRY_NP(abort) 548276396Sian b _C_LABEL(abort) 549276396SianEND(abort) 550276396Sian 551276396SianENTRY_NP(sigcode) 552276396Sian mov r0, sp 553282024Sandrew add r0, r0, #SIGF_UC 554276396Sian 555276396Sian /* 556282024Sandrew * Call the sigreturn system call. 557276396Sian * 558276396Sian * We have to load r7 manually rather than using 559282024Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 560276396Sian * correct. Using the alternative places esigcode at the address 561282024Sandrew * of the data rather than the address one past the data. 562276396Sian */ 563276396Sian 564282024Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 565276396Sian swi SYS_sigreturn 566276396Sian 567282024Sandrew /* Well if that failed we better exit quick ! */ 568276396Sian 569282024Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 570276396Sian swi SYS_exit 571276396Sian 572282024Sandrew /* Branch back to retry SYS_sigreturn */ 573276396Sian b . - 16 574276470SianEND(sigcode) 575276396Sian .word SYS_sigreturn 576276396Sian .word SYS_exit 577276396Sian 578276596Sian .align 2 579282024Sandrew .global _C_LABEL(esigcode) 580276396Sian _C_LABEL(esigcode): 581276396Sian 582276396Sian .data 583282024Sandrew .global szsigcode 584276396Sianszsigcode: 585276396Sian .long esigcode-sigcode 586276470Sian 587276396Sian/* End of locore.S */ 588