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