locore-v4.S revision 175983
1129198Scognet/* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (C) 1994-1997 Mark Brinicombe 5129198Scognet * Copyright (C) 1994 Brini 6129198Scognet * All rights reserved. 7129198Scognet * 8129198Scognet * Redistribution and use in source and binary forms, with or without 9129198Scognet * modification, are permitted provided that the following conditions 10129198Scognet * are met: 11129198Scognet * 1. Redistributions of source code must retain the above copyright 12129198Scognet * notice, this list of conditions and the following disclaimer. 13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 14129198Scognet * notice, this list of conditions and the following disclaimer in the 15129198Scognet * documentation and/or other materials provided with the distribution. 16129198Scognet * 3. All advertising materials mentioning features or use of this software 17129198Scognet * must display the following acknowledgement: 18129198Scognet * This product includes software developed by Brini. 19129198Scognet * 4. The name of Brini may not be used to endorse or promote products 20129198Scognet * derived from this software without specific prior written permission. 21129198Scognet * 22129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR 23129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25129198Scognet * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26129198Scognet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27129198Scognet * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28129198Scognet * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29129198Scognet * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30129198Scognet * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31129198Scognet * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32129198Scognet * 33129198Scognet */ 34129198Scognet 35129198Scognet#include "assym.s" 36135640Scognet#include <sys/syscall.h> 37129198Scognet#include <machine/asm.h> 38129198Scognet#include <machine/armreg.h> 39129198Scognet#include <machine/pte.h> 40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/locore.S 175983 2008-02-05 10:23:42Z raj $"); 41129198Scognet 42159849Simp/* What size should this really be ? It is only used by initarm() */ 43129198Scognet#define INIT_ARM_STACK_SIZE 2048 44129198Scognet 45129198Scognet/* 46129198Scognet * This is for kvm_mkdb, and should be the address of the beginning 47129198Scognet * of the kernel text segment (not necessarily the same as kernbase). 48129198Scognet */ 49129198Scognet 50129198Scognet 51129198Scognet#define CPWAIT_BRANCH \ 52129198Scognet sub pc, pc, #4 53129198Scognet 54129198Scognet#define CPWAIT(tmp) \ 55129198Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 56129198Scognet mov tmp, tmp /* wait for it to complete */ ;\ 57129198Scognet CPWAIT_BRANCH /* branch to next insn */ 58129198Scognet 59129198Scognet .text 60129198Scognet .align 0 61129198Scognet.globl kernbase 62129198Scognet.set kernbase,KERNBASE 63150863Scognet.globl physaddr 64150863Scognet.set physaddr,PHYSADDR 65129198Scognet 66129198ScognetENTRY_NP(btext) 67129198Scognet 68129198ScognetASENTRY_NP(_start) 69166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR) 70166819Scognet /* Check if we're running from flash. */ 71166819Scognet ldr r7, =FLASHADDR 72175983Sraj /* 73166819Scognet * If we're running with MMU disabled, test against the 74166819Scognet * physical address instead. 75166819Scognet */ 76166819Scognet mrc p15, 0, r2, c1, c0, 0 77166819Scognet ands r2, r2, #CPU_CONTROL_MMU_ENABLE 78166819Scognet ldreq r8, =PHYSADDR 79166819Scognet ldrne r8, =LOADERRAMADDR 80166819Scognet cmp r7, r8 81166819Scognet bls flash_lower 82166819Scognet cmp r7, pc 83166819Scognet bhi from_ram 84166819Scognet b do_copy 85166819Scognet 86166819Scognetflash_lower: 87166819Scognet cmp r8, pc 88166819Scognet bls from_ram 89166819Scognetdo_copy: 90166819Scognet ldr r9, =KERNBASE 91175983Sraj adr r1, _start 92166819Scognet ldr r0, Lreal_start 93166819Scognet ldr r2, Lend 94166819Scognet sub r2, r2, r0 95166819Scognet sub r0, r0, r9 96166819Scognet add r0, r0, r8 97166819Scognet mov r4, r0 98166819Scognet bl memcpy 99166819Scognet ldr r0, Lram_offset 100166819Scognet add pc, r4, r0 101166819ScognetLram_offset: .word from_ram-_C_LABEL(_start) 102166819Scognetfrom_ram: 103166819Scognet nop 104135640Scognet#endif 105135640Scognet adr r7, Lunmapped 106153616Scognet bic r7, r7, #0xff000000 107153616Scognet orr r7, r7, #PHYSADDR 108143681Sjmg 109175983Sraj 110166819Scognetdisable_mmu: 111135640Scognet /* Disable MMU for a while */ 112143681Sjmg mrc p15, 0, r2, c1, c0, 0 113153550Scognet bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 114153550Scognet CPU_CONTROL_WBUF_ENABLE) 115153550Scognet bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 116153550Scognet bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 117135640Scognet mcr p15, 0, r2, c1, c0, 0 118129198Scognet 119135640Scognet nop 120135640Scognet nop 121135640Scognet nop 122135640Scognet mov pc, r7 123135640ScognetLunmapped: 124135640Scognet#ifdef STARTUP_PAGETABLE_ADDR 125129198Scognet /* build page table from scratch */ 126129198Scognet ldr r0, Lstartup_pagetable 127129198Scognet adr r4, mmu_init_table 128129198Scognet b 3f 129129198Scognet 130129198Scognet2: 131129198Scognet str r3, [r0, r2] 132129198Scognet add r2, r2, #4 133129198Scognet add r3, r3, #(L1_S_SIZE) 134129198Scognet adds r1, r1, #-1 135129198Scognet bhi 2b 136143681Sjmg3: 137172356Scognet ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */ 138129198Scognet cmp r1, #0 139140683Scognet adrne r5, 2b 140140683Scognet bicne r5, r5, #0xff000000 141140683Scognet orrne r5, r5, #PHYSADDR 142140683Scognet movne pc, r5 143129198Scognet 144129198Scognet mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 145129198Scognet mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 146129198Scognet 147129198Scognet /* Set the Domain Access register. Very important! */ 148143681Sjmg mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 149129198Scognet mcr p15, 0, r0, c3, c0, 0 150129198Scognet /* Enable MMU */ 151129198Scognet mrc p15, 0, r0, c1, c0, 0 152129198Scognet orr r0, r0, #CPU_CONTROL_MMU_ENABLE 153129198Scognet mcr p15, 0, r0, c1, c0, 0 154153550Scognet nop 155153550Scognet nop 156153550Scognet nop 157129198Scognet CPWAIT(r0) 158129198Scognet 159153550Scognet#endif 160129198Scognetmmu_done: 161153550Scognet nop 162129198Scognet adr r1, .Lstart 163129198Scognet ldmia r1, {r1, r2, sp} /* Set initial stack and */ 164129198Scognet sub r2, r2, r1 /* get zero init data */ 165129198Scognet mov r3, #0 166129198Scognet.L1: 167150863Scognet str r3, [r1], #0x0004 /* get zero init data */ 168129198Scognet subs r2, r2, #4 169129198Scognet bgt .L1 170153550Scognet ldr pc, .Lvirt_done 171129198Scognet 172142145Scognetvirt_done: 173175983Sraj mov fp, #0 /* trace back starts here */ 174129198Scognet bl _C_LABEL(initarm) /* Off we go */ 175129198Scognet 176129198Scognet /* init arm will return the new stack pointer. */ 177129198Scognet mov sp, r0 178129198Scognet 179129198Scognet bl _C_LABEL(mi_startup) /* call mi_startup()! */ 180129198Scognet 181129198Scognet adr r0, .Lmainreturned 182130164Sphk b _C_LABEL(panic) 183175983Sraj /* NOTREACHED */ 184129198Scognet#ifdef STARTUP_PAGETABLE_ADDR 185129198Scognet#define MMU_INIT(va,pa,n_sec,attr) \ 186129198Scognet .word n_sec ; \ 187129198Scognet .word 4*((va)>>L1_S_SHIFT) ; \ 188129198Scognet .word (pa)|(attr) ; 189129198Scognet 190150863ScognetLvirtaddr: 191150863Scognet .word KERNVIRTADDR 192150863ScognetLphysaddr: 193150863Scognet .word KERNPHYSADDR 194166819ScognetLreal_start: 195166819Scognet .word _start 196166819ScognetLend: 197166819Scognet .word _edata 198129198ScognetLstartup_pagetable: 199129198Scognet .word STARTUP_PAGETABLE_ADDR 200143681Sjmgmmu_init_table: 201129198Scognet /* fill all table VA==PA */ 202129198Scognet /* map SDRAM VA==PA, WT cacheable */ 203135640Scognet MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 204135640Scognet /* map VA 0xc0000000..0xc3ffffff to PA */ 205135640Scognet MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 206129198Scognet 207129198Scognet .word 0 /* end of table */ 208129198Scognet#endif 209129198Scognet.Lstart: 210129198Scognet .word _edata 211129198Scognet .word _end 212129198Scognet .word svcstk + INIT_ARM_STACK_SIZE 213129198Scognet 214166819Scognet#if defined(FLASHADDR) && defined(LOADERRAMADDR) 215166819Scognet.L_arm_memcpy: 216166819Scognet .word _C_LABEL(_arm_memcpy) 217166819Scognet#endif 218166819Scognet 219153550Scognet.Lvirt_done: 220153550Scognet .word virt_done 221129198Scognet.Lmainreturned: 222129198Scognet .asciz "main() returned" 223129198Scognet .align 0 224129198Scognet 225129198Scognet .bss 226129198Scognetsvcstk: 227129198Scognet .space INIT_ARM_STACK_SIZE 228129198Scognet 229129198Scognet .text 230129198Scognet .align 0 231129198Scognet 232143681Sjmg.Lcpufuncs: 233129198Scognet .word _C_LABEL(cpufuncs) 234129198Scognet 235135640ScognetENTRY_NP(cpu_halt) 236129198Scognet mrs r2, cpsr 237129198Scognet bic r2, r2, #(PSR_MODE) 238129198Scognet orr r2, r2, #(PSR_SVC32_MODE) 239129198Scognet orr r2, r2, #(I32_bit | F32_bit) 240129198Scognet msr cpsr_all, r2 241129198Scognet 242129198Scognet ldr r4, .Lcpu_reset_address 243129198Scognet ldr r4, [r4] 244129198Scognet 245129198Scognet ldr r0, .Lcpufuncs 246129198Scognet mov lr, pc 247129198Scognet ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 248129198Scognet 249129198Scognet /* 250129198Scognet * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 251129198Scognet * necessary. 252129198Scognet */ 253129198Scognet 254129198Scognet ldr r1, .Lcpu_reset_needs_v4_MMU_disable 255129198Scognet ldr r1, [r1] 256129198Scognet cmp r1, #0 257129198Scognet mov r2, #0 258129198Scognet 259129198Scognet /* 260175983Sraj * MMU & IDC off, 32 bit program & data space 261129198Scognet * Hurl ourselves into the ROM 262129198Scognet */ 263129198Scognet mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 264129198Scognet mcr 15, 0, r0, c1, c0, 0 265129198Scognet mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 266129198Scognet mov pc, r4 267129198Scognet 268129198Scognet /* 269129198Scognet * _cpu_reset_address contains the address to branch to, to complete 270129198Scognet * the cpu reset after turning the MMU off 271129198Scognet * This variable is provided by the hardware specific code 272129198Scognet */ 273129198Scognet.Lcpu_reset_address: 274129198Scognet .word _C_LABEL(cpu_reset_address) 275129198Scognet 276129198Scognet /* 277129198Scognet * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 278129198Scognet * v4 MMU disable instruction needs executing... it is an illegal instruction 279129198Scognet * on f.e. ARM6/7 that locks up the computer in an endless illegal 280129198Scognet * instruction / data-abort / reset loop. 281129198Scognet */ 282129198Scognet.Lcpu_reset_needs_v4_MMU_disable: 283129198Scognet .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 284129198Scognet 285129198Scognet 286129198Scognet#ifdef IPKDB 287129198Scognet/* 288129198Scognet * Execute(inst, psr, args, sp) 289129198Scognet * 290129198Scognet * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making 291129198Scognet * available stack at SP for next undefined instruction trap. 292129198Scognet * 293129198Scognet * Move the instruction onto the stack and jump to it. 294129198Scognet */ 295129198ScognetENTRY_NP(Execute) 296129198Scognet mov ip, sp 297129198Scognet stmfd sp!, {r2, r4-r7, fp, ip, lr, pc} 298129198Scognet sub fp, ip, #4 299129198Scognet mov ip, r3 300129198Scognet ldr r7, .Lreturn 301129198Scognet stmfd sp!, {r0, r7} 302129198Scognet adr r7, #.LExec 303129198Scognet mov r5, r1 304129198Scognet mrs r4, cpsr 305129198Scognet ldmia r2, {r0-r3} 306129198Scognet mov r6, sp 307129198Scognet mov sp, ip 308129198Scognet msr cpsr_all, r5 309129198Scognet mov pc, r6 310129198Scognet.LExec: 311129198Scognet mrs r5, cpsr 312129198Scognet/* XXX Cannot switch thus easily back from user mode */ 313129198Scognet msr cpsr_all, r4 314129198Scognet add sp, r6, #8 315129198Scognet ldmfd sp!, {r6} 316129198Scognet stmia r6, {r0-r3} 317129198Scognet mov r0, r5 318129198Scognet ldmdb fp, {r4-r7, fp, sp, pc} 319129198Scognet.Lreturn: 320129198Scognet mov pc, r7 321129198Scognet#endif 322129198Scognet 323129198Scognet/* 324129198Scognet * setjump + longjmp 325129198Scognet */ 326129198ScognetENTRY(setjmp) 327129198Scognet stmia r0, {r4-r14} 328129198Scognet mov r0, #0x00000000 329137463Scognet RET 330129198Scognet 331129198ScognetENTRY(longjmp) 332129198Scognet ldmia r0, {r4-r14} 333129198Scognet mov r0, #0x00000001 334137463Scognet RET 335129198Scognet 336129198Scognet .data 337129198Scognet .global _C_LABEL(esym) 338129198Scognet_C_LABEL(esym): .word _C_LABEL(end) 339129198Scognet 340129198ScognetENTRY_NP(abort) 341129198Scognet b _C_LABEL(abort) 342129198Scognet 343135640ScognetENTRY_NP(sigcode) 344135640Scognet mov r0, sp 345135640Scognet swi SYS_sigreturn 346135640Scognet 347135640Scognet /* Well if that failed we better exit quick ! */ 348135640Scognet 349135640Scognet swi SYS_exit 350135640Scognet b . - 8 351135640Scognet 352135640Scognet .align 0 353135640Scognet .global _C_LABEL(esigcode) 354135640Scognet _C_LABEL(esigcode): 355143681Sjmg 356135640Scognet .data 357135640Scognet .global szsigcode 358135640Scognetszsigcode: 359135640Scognet .long esigcode-sigcode 360129198Scognet/* End of locore.S */ 361