1/* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */ 2 3/*- 4 * Copyright (C) 1994-1997 Mark Brinicombe 5 * Copyright (C) 1994 Brini 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Brini. 19 * 4. The name of Brini may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35#include "assym.s" 36#include <sys/syscall.h> 37#include <machine/asm.h> 38#include <machine/armreg.h> 39#include <machine/pte.h> 40__FBSDID("$FreeBSD$"); 41 42/* What size should this really be ? It is only used by initarm() */ 43#define INIT_ARM_STACK_SIZE 2048 44 45/* 46 * This is for kvm_mkdb, and should be the address of the beginning 47 * of the kernel text segment (not necessarily the same as kernbase). 48 */ 49 50 51#define CPWAIT_BRANCH \ 52 sub pc, pc, #4 53 54#define CPWAIT(tmp) \ 55 mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 56 mov tmp, tmp /* wait for it to complete */ ;\ 57 CPWAIT_BRANCH /* branch to next insn */ 58 59 .text 60 .align 0 61.globl kernbase 62.set kernbase,KERNBASE 63.globl physaddr 64.set physaddr,PHYSADDR 65 66ENTRY_NP(btext) 67 68/* 69 * On entry: 70 * r0 - metadata pointer or 0 71 * r1 - if (r0 == 0) then metadata pointer 72 */ 73ASENTRY_NP(_start) 74 75 /* Move metadata ptr to r12 (ip) */ 76 mov ip, r0 77 ldr r0, =0 78 cmp ip, r0 79 bne 1f 80 mov ip, r1 811: 82 /* Make sure interrupts are disabled. */ 83 mrs r7, cpsr 84 orr r7, r7, #(I32_bit|F32_bit) 85 msr cpsr_c, r7 86 87#if defined (FLASHADDR) && defined(LOADERRAMADDR) 88 /* Check if we're running from flash. */ 89 ldr r7, =FLASHADDR 90 /* 91 * If we're running with MMU disabled, test against the 92 * physical address instead. 93 */ 94 mrc p15, 0, r2, c1, c0, 0 95 ands r2, r2, #CPU_CONTROL_MMU_ENABLE 96 ldreq r8, =PHYSADDR 97 ldrne r8, =LOADERRAMADDR 98 cmp r7, r8 99 bls flash_lower 100 cmp r7, pc 101 bhi from_ram 102 b do_copy 103 104flash_lower: 105 cmp r8, pc 106 bls from_ram 107do_copy: 108 ldr r9, =KERNBASE 109 adr r1, _start 110 ldr r0, Lreal_start 111 ldr r2, Lend 112 sub r2, r2, r0 113 sub r0, r0, r9 114 add r0, r0, r8 115 mov r4, r0 116 bl memcpy 117 ldr r0, Lram_offset 118 add pc, r4, r0 119Lram_offset: .word from_ram-_C_LABEL(_start) 120from_ram: 121 nop 122#endif 123 adr r7, Lunmapped 124 bic r7, r7, #0xf0000000 125 orr r7, r7, #PHYSADDR 126 127 128disable_mmu: 129 /* Disable MMU for a while */ 130 mrc p15, 0, r2, c1, c0, 0 131 bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 132 CPU_CONTROL_WBUF_ENABLE) 133 bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 134 bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 135 mcr p15, 0, r2, c1, c0, 0 136 137 nop 138 nop 139 nop 140 mov pc, r7 141Lunmapped: 142#ifdef STARTUP_PAGETABLE_ADDR 143 /* build page table from scratch */ 144 ldr r0, Lstartup_pagetable 145 adr r4, mmu_init_table 146 b 3f 147 1482: 149 str r3, [r0, r2] 150 add r2, r2, #4 151 add r3, r3, #(L1_S_SIZE) 152 adds r1, r1, #-1 153 bhi 2b 1543: 155 ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */ 156 cmp r1, #0 157 adrne r5, 2b 158 bicne r5, r5, #0xf0000000 159 orrne r5, r5, #PHYSADDR 160 movne pc, r5 161 162 mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 163 mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 164 165 /* Set the Domain Access register. Very important! */ 166 mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 167 mcr p15, 0, r0, c3, c0, 0 168 /* Enable MMU */ 169 mrc p15, 0, r0, c1, c0, 0 170 orr r0, r0, #CPU_CONTROL_MMU_ENABLE 171 mcr p15, 0, r0, c1, c0, 0 172 nop 173 nop 174 nop 175 CPWAIT(r0) 176 177#endif 178mmu_done: 179 nop 180 adr r1, .Lstart 181 ldmia r1, {r1, r2, sp} /* Set initial stack and */ 182 sub r2, r2, r1 /* get zero init data */ 183 mov r3, #0 184.L1: 185 str r3, [r1], #0x0004 /* get zero init data */ 186 subs r2, r2, #4 187 bgt .L1 188 ldr pc, .Lvirt_done 189 190virt_done: 191 mov r0, ip /* Load argument: metadata ptr */ 192 193 mov fp, #0 /* trace back starts here */ 194 bl _C_LABEL(initarm) /* Off we go */ 195 196 /* init arm will return the new stack pointer. */ 197 mov sp, r0 198 199 bl _C_LABEL(mi_startup) /* call mi_startup()! */ 200 201 adr r0, .Lmainreturned 202 b _C_LABEL(panic) 203 /* NOTREACHED */ 204#ifdef STARTUP_PAGETABLE_ADDR 205#define MMU_INIT(va,pa,n_sec,attr) \ 206 .word n_sec ; \ 207 .word 4*((va)>>L1_S_SHIFT) ; \ 208 .word (pa)|(attr) ; 209 210Lvirtaddr: 211 .word KERNVIRTADDR 212Lphysaddr: 213 .word KERNPHYSADDR 214Lreal_start: 215 .word _start 216Lend: 217 .word _edata 218Lstartup_pagetable: 219 .word STARTUP_PAGETABLE_ADDR 220mmu_init_table: 221 /* fill all table VA==PA */ 222 /* map SDRAM VA==PA, WT cacheable */ 223 MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 224 /* map VA 0xc0000000..0xc3ffffff to PA */ 225 MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 226 227 .word 0 /* end of table */ 228#endif 229.Lstart: 230 .word _edata 231 .word _end 232 .word svcstk + INIT_ARM_STACK_SIZE 233 234#if defined(FLASHADDR) && defined(LOADERRAMADDR) 235.L_arm_memcpy: 236 .word _C_LABEL(_arm_memcpy) 237#endif 238 239.Lvirt_done: 240 .word virt_done 241.Lmainreturned: 242 .asciz "main() returned" 243 .align 0 244 245 .bss 246svcstk: 247 .space INIT_ARM_STACK_SIZE 248 249 .text 250 .align 0 251 252.Lcpufuncs: 253 .word _C_LABEL(cpufuncs) 254 255ENTRY_NP(cpu_halt) 256 mrs r2, cpsr 257 bic r2, r2, #(PSR_MODE) 258 orr r2, r2, #(PSR_SVC32_MODE) 259 orr r2, r2, #(I32_bit | F32_bit) 260 msr cpsr_all, r2 261 262 ldr r4, .Lcpu_reset_address 263 ldr r4, [r4] 264 265 ldr r0, .Lcpufuncs 266 mov lr, pc 267 ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 268 mov lr, pc 269 ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 270 271 /* 272 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 273 * necessary. 274 */ 275 276 ldr r1, .Lcpu_reset_needs_v4_MMU_disable 277 ldr r1, [r1] 278 cmp r1, #0 279 mov r2, #0 280 281 /* 282 * MMU & IDC off, 32 bit program & data space 283 * Hurl ourselves into the ROM 284 */ 285 mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 286 mcr 15, 0, r0, c1, c0, 0 287 mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 288 mov pc, r4 289 290 /* 291 * _cpu_reset_address contains the address to branch to, to complete 292 * the cpu reset after turning the MMU off 293 * This variable is provided by the hardware specific code 294 */ 295.Lcpu_reset_address: 296 .word _C_LABEL(cpu_reset_address) 297 298 /* 299 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 300 * v4 MMU disable instruction needs executing... it is an illegal instruction 301 * on f.e. ARM6/7 that locks up the computer in an endless illegal 302 * instruction / data-abort / reset loop. 303 */ 304.Lcpu_reset_needs_v4_MMU_disable: 305 .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 306 307 308/* 309 * setjump + longjmp 310 */ 311ENTRY(setjmp) 312 stmia r0, {r4-r14} 313 mov r0, #0x00000000 314 RET 315 316ENTRY(longjmp) 317 ldmia r0, {r4-r14} 318 mov r0, #0x00000001 319 RET 320 321 .data 322 .global _C_LABEL(esym) 323_C_LABEL(esym): .word _C_LABEL(end) 324 325ENTRY_NP(abort) 326 b _C_LABEL(abort) 327 328ENTRY_NP(sigcode) 329 mov r0, sp 330 swi SYS_sigreturn 331 332 /* Well if that failed we better exit quick ! */ 333 334 swi SYS_exit 335 b . - 8 336 337 .align 0 338 .global _C_LABEL(esigcode) 339 _C_LABEL(esigcode): 340 341 .data 342 .global szsigcode 343szsigcode: 344 .long esigcode-sigcode 345/* End of locore.S */ 346