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