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 68ASENTRY_NP(_start) 69 70/* 71 * Move metadata ptr to r12 (ip) 72 */ 73 74 mov ip, r0 75 76 /* Make sure interrupts are disabled. */ 77 mrs r7, cpsr 78 orr r7, r7, #(I32_bit|F32_bit) 79 msr cpsr_c, r7 80 81#if defined (FLASHADDR) && defined(LOADERRAMADDR) 82 /* Check if we're running from flash. */ 83 ldr r7, =FLASHADDR 84 /* 85 * If we're running with MMU disabled, test against the 86 * physical address instead. 87 */ 88 mrc p15, 0, r2, c1, c0, 0 89 ands r2, r2, #CPU_CONTROL_MMU_ENABLE 90 ldreq r8, =PHYSADDR 91 ldrne r8, =LOADERRAMADDR 92 cmp r7, r8 93 bls flash_lower 94 cmp r7, pc 95 bhi from_ram 96 b do_copy 97 98flash_lower: 99 cmp r8, pc 100 bls from_ram 101do_copy: 102 ldr r9, =KERNBASE 103 adr r1, _start 104 ldr r0, Lreal_start 105 ldr r2, Lend 106 sub r2, r2, r0 107 sub r0, r0, r9 108 add r0, r0, r8 109 mov r4, r0 110 bl memcpy 111 ldr r0, Lram_offset 112 add pc, r4, r0 113Lram_offset: .word from_ram-_C_LABEL(_start) 114from_ram: 115 nop 116#endif 117 adr r7, Lunmapped 118 bic r7, r7, #0xf0000000 119 orr r7, r7, #PHYSADDR 120 121 122disable_mmu: 123 /* Disable MMU for a while */ 124 mrc p15, 0, r2, c1, c0, 0 125 bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ 126 CPU_CONTROL_WBUF_ENABLE) 127 bic r2, r2, #(CPU_CONTROL_IC_ENABLE) 128 bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) 129 mcr p15, 0, r2, c1, c0, 0 130 131 nop 132 nop 133 nop 134 mov pc, r7 135Lunmapped: 136#ifdef STARTUP_PAGETABLE_ADDR 137 /* build page table from scratch */ 138 ldr r0, Lstartup_pagetable 139 adr r4, mmu_init_table 140 b 3f 141 1422: 143 str r3, [r0, r2] 144 add r2, r2, #4 145 add r3, r3, #(L1_S_SIZE) 146 adds r1, r1, #-1 147 bhi 2b 1483: 149 ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */ 150 cmp r1, #0 151 adrne r5, 2b 152 bicne r5, r5, #0xf0000000 153 orrne r5, r5, #PHYSADDR 154 movne pc, r5 155 156 mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 157 mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 158 159 /* Set the Domain Access register. Very important! */ 160 mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 161 mcr p15, 0, r0, c3, c0, 0 162 /* Enable MMU */ 163 mrc p15, 0, r0, c1, c0, 0 164 orr r0, r0, #CPU_CONTROL_MMU_ENABLE 165 mcr p15, 0, r0, c1, c0, 0 166 nop 167 nop 168 nop 169 CPWAIT(r0) 170 171#endif 172mmu_done: 173 nop 174 adr r1, .Lstart 175 ldmia r1, {r1, r2, sp} /* Set initial stack and */ 176 sub r2, r2, r1 /* get zero init data */ 177 mov r3, #0 178.L1: 179 str r3, [r1], #0x0004 /* get zero init data */ 180 subs r2, r2, #4 181 bgt .L1 182 ldr pc, .Lvirt_done 183 184virt_done: 185 mov r0, ip /* Load argument: metadata ptr */ 186 187 mov fp, #0 /* trace back starts here */ 188 bl _C_LABEL(initarm) /* Off we go */ 189 190 /* init arm will return the new stack pointer. */ 191 mov sp, r0 192 193 bl _C_LABEL(mi_startup) /* call mi_startup()! */ 194 195 adr r0, .Lmainreturned 196 b _C_LABEL(panic) 197 /* NOTREACHED */ 198#ifdef STARTUP_PAGETABLE_ADDR 199#define MMU_INIT(va,pa,n_sec,attr) \ 200 .word n_sec ; \ 201 .word 4*((va)>>L1_S_SHIFT) ; \ 202 .word (pa)|(attr) ; 203 204Lvirtaddr: 205 .word KERNVIRTADDR 206Lphysaddr: 207 .word KERNPHYSADDR 208Lreal_start: 209 .word _start 210Lend: 211 .word _edata 212Lstartup_pagetable: 213 .word STARTUP_PAGETABLE_ADDR 214mmu_init_table: 215 /* fill all table VA==PA */ 216 /* map SDRAM VA==PA, WT cacheable */ 217 MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 218 /* map VA 0xc0000000..0xc3ffffff to PA */ 219 MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 220 221 .word 0 /* end of table */ 222#endif 223.Lstart: 224 .word _edata 225 .word _end 226 .word svcstk + INIT_ARM_STACK_SIZE 227 228#if defined(FLASHADDR) && defined(LOADERRAMADDR) 229.L_arm_memcpy: 230 .word _C_LABEL(_arm_memcpy) 231#endif 232 233.Lvirt_done: 234 .word virt_done 235.Lmainreturned: 236 .asciz "main() returned" 237 .align 0 238 239 .bss 240svcstk: 241 .space INIT_ARM_STACK_SIZE 242 243 .text 244 .align 0 245 246.Lcpufuncs: 247 .word _C_LABEL(cpufuncs) 248 249ENTRY_NP(cpu_halt) 250 mrs r2, cpsr 251 bic r2, r2, #(PSR_MODE) 252 orr r2, r2, #(PSR_SVC32_MODE) 253 orr r2, r2, #(I32_bit | F32_bit) 254 msr cpsr_all, r2 255 256 ldr r4, .Lcpu_reset_address 257 ldr r4, [r4] 258 259 ldr r0, .Lcpufuncs 260 mov lr, pc 261 ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] 262 mov lr, pc 263 ldr pc, [r0, #CF_L2CACHE_WBINV_ALL] 264 265 /* 266 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's 267 * necessary. 268 */ 269 270 ldr r1, .Lcpu_reset_needs_v4_MMU_disable 271 ldr r1, [r1] 272 cmp r1, #0 273 mov r2, #0 274 275 /* 276 * MMU & IDC off, 32 bit program & data space 277 * Hurl ourselves into the ROM 278 */ 279 mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) 280 mcr 15, 0, r0, c1, c0, 0 281 mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ 282 mov pc, r4 283 284 /* 285 * _cpu_reset_address contains the address to branch to, to complete 286 * the cpu reset after turning the MMU off 287 * This variable is provided by the hardware specific code 288 */ 289.Lcpu_reset_address: 290 .word _C_LABEL(cpu_reset_address) 291 292 /* 293 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the 294 * v4 MMU disable instruction needs executing... it is an illegal instruction 295 * on f.e. ARM6/7 that locks up the computer in an endless illegal 296 * instruction / data-abort / reset loop. 297 */ 298.Lcpu_reset_needs_v4_MMU_disable: 299 .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) 300 301 302/* 303 * setjump + longjmp 304 */ 305ENTRY(setjmp) 306 stmia r0, {r4-r14} 307 mov r0, #0x00000000 308 RET 309 310ENTRY(longjmp) 311 ldmia r0, {r4-r14} 312 mov r0, #0x00000001 313 RET 314 315 .data 316 .global _C_LABEL(esym) 317_C_LABEL(esym): .word _C_LABEL(end) 318 319ENTRY_NP(abort) 320 b _C_LABEL(abort) 321 322ENTRY_NP(sigcode) 323 mov r0, sp 324 swi SYS_sigreturn 325 326 /* Well if that failed we better exit quick ! */ 327 328 swi SYS_exit 329 b . - 8 330 331 .align 0 332 .global _C_LABEL(esigcode) 333 _C_LABEL(esigcode): 334 335 .data 336 .global szsigcode 337szsigcode: 338 .long esigcode-sigcode 339/* End of locore.S */ 340