1/* $NetBSD: locore.S,v 1.44 2002/03/09 23:35:57 chs Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 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 TooLs GmbH. 19 * 4. The name of TooLs GmbH 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 TOOLS GMBH ``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 TOOLS GMBH 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#include "opt_ddb.h" 35#include "opt_kgdb.h" 36#include "opt_ipkdb.h" 37#include "opt_lockdebug.h" 38#include "opt_multiprocessor.h" 39#include "assym.h" 40 41#include <sys/syscall.h> 42 43#include <machine/param.h> 44#include <machine/pmap.h> 45#include <machine/psl.h> 46#include <machine/trap.h> 47#include <machine/asm.h> 48#ifndef OLDPMAP 49#include <machine/vmparam.h> 50#endif 51 52#include <powerpc/spr.h> 53/* 54 * Some instructions gas doesn't understand (yet?) 55 */ 56#define bdneq bdnzf 2, 57 58#if defined(MULTIPROCESSOR) 59/* 60 * Get varios per-cpu values. 61 */ 62#if 1 63#define GET_CPUINFO(r) \ 64 mfsprg r,0 65#else 66#define GET_CPUINFO(r) \ 67 mfspr r,SPR_PIR; /* r = cpu_number() */ \ 68 mulli r,r,CI_SIZE; \ 69 addis r,r,_C_LABEL(cpu_info)@ha; \ 70 addi r,r,_C_LABEL(cpu_info)@l; 71#endif 72#endif 73 74#define INTSTK 8192 /* 8K interrupt stack */ 75#define SPILLSTK 4096 /* 4K spill stack */ 76 77/* 78 * Globals 79 */ 80 .data 81GLOBAL(esym) 82 .long 0 /* end of symbol table */ 83GLOBAL(proc0paddr) 84 .long 0 /* proc0 p_addr */ 85 86GLOBAL(intrnames) 87 .asciz "irq0", "irq1", "irq2", "irq3" 88 .asciz "irq4", "irq5", "irq6", "irq7" 89 .asciz "irq8", "irq9", "irq10", "irq11" 90 .asciz "irq12", "irq13", "irq14", "irq15" 91 .asciz "irq16", "irq17", "irq18", "irq19" 92 .asciz "irq20", "irq21", "irq22", "irq23" 93 .asciz "irq24", "irq25", "irq26", "irq27" 94 .asciz "irq28", "irq29", "irq30", "irq31" 95 .asciz "irq32", "irq33", "irq34", "irq35" 96 .asciz "irq36", "irq37", "irq38", "irq39" 97 .asciz "irq40", "irq41", "irq42", "irq43" 98 .asciz "irq44", "irq45", "irq46", "irq47" 99 .asciz "irq48", "irq49", "irq50", "irq51" 100 .asciz "irq52", "irq53", "irq54", "irq55" 101 .asciz "irq56", "irq57", "irq58", "irq59" 102 .asciz "irq60", "irq61", "irq62", "irq63" 103 .asciz "clock", "softclock", "softnet", "softserial" 104GLOBAL(eintrnames) 105 .align 4 106GLOBAL(intrcnt) 107 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 108 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 109 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 110 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 111 .long 0,0,0,0 112GLOBAL(eintrcnt) 113 114GLOBAL(ofmsr) 115 .long 0,0,0,0,0 /* msr & sprg[0-3] used in Open Firmware */ 116 117/* 118 * File-scope for locore.S 119 */ 120#if !defined(MULTIPROCESSOR) 121idle_u: 122 .long 0 /* fake uarea during idle after exit */ 123#endif 124openfirmware_entry: 125 .long 0 /* openfirmware entry point */ 126srsave: 127 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 128 129/* 130 * This symbol is here for the benefit of kvm_mkdb, and is supposed to 131 * mark the start of kernel text. 132 */ 133 .text 134 .globl _C_LABEL(kernel_text) 135_C_LABEL(kernel_text): 136 137/* 138 * Startup entry. Note, this must be the first thing in the text 139 * segment! 140 */ 141 .text 142 .globl __start 143__start: 144#ifdef FIRMWORKSBUGS 145 mfmsr 0 146 andi. 0,0,PSL_IR|PSL_DR 147 beq 1f 148 149 bl _C_LABEL(ofwr_init) 1501: 151#endif 152 mfmsr 0 153 lis 9,ofmsr@ha 154 stw 0,ofmsr@l(9) 155 mfsprg 0,0 156 stw 0,ofmsr+4@l(9) 157 mfsprg 0,1 158 stw 0,ofmsr+8@l(9) 159 mfsprg 0,2 160 stw 0,ofmsr+12@l(9) 161 mfsprg 0,3 162 stw 0,ofmsr+16@l(9) 163 164 li 0,0 165 mtmsr 0 /* Disable FPU/MMU/exceptions */ 166 isync 167 168/* compute end of kernel memory */ 169 lis 8,_C_LABEL(end)@ha 170 addi 8,8,_C_LABEL(end)@l 171#ifdef DDB 172 /* skip symbol table */ 173 cmpwi 6,0 174 beq 1f 175 add 9,6,7 /* r9 = args + l */ 176 lwz 9,-8(9) /* esym */ 177 cmpwi 9,0 178 beq 1f 179 mr 8,9 1801: 181#endif 182 li 9,PGOFSET 183 add 8,8,9 184 andc 8,8,9 185 lis 9,_C_LABEL(OF_buf)@ha 186 stw 8,_C_LABEL(OF_buf)@l(9) 187 addi 8,8,NBPG 188#if defined(MULTIPROCESSOR) 189 lis 9,_C_LABEL(cpu_info)@ha 190 addi 9,9,_C_LABEL(cpu_info)@l 191 addi 8,8,INTSTK 192 stw 8,CI_INTSTK(9) 193 addi 8,8,SPILLSTK 194 stw 8,CI_SPILLSTK(9) 195 stw 8,CI_IDLE_PCB(9) 196#else 197 lis 9,idle_u@ha 198 stw 8,idle_u@l(9) 199#endif 200 addi 8,8,USPACE /* space for idle_u */ 201 lis 9,_C_LABEL(proc0paddr)@ha 202 stw 8,_C_LABEL(proc0paddr)@l(9) 203 addi 1,8,USPACE-FRAMELEN /* stackpointer for proc0 */ 204 mr 4,1 /* end of mem reserved for kernel */ 205 xor 0,0,0 206 stwu 0,-16(1) /* end of stack chain */ 207 208 lis 8,openfirmware_entry@ha 209 stw 5,openfirmware_entry@l(8) /* save client interface handler */ 210 lis 3,__start@ha 211 addi 3,3,__start@l 212 mr 5,6 /* args string */ 213 bl _C_LABEL(initppc) 214 bl _C_LABEL(main) 215 b _C_LABEL(OF_exit) 216 217/* 218 * OpenFirmware entry point 219 */ 220ENTRY(openfirmware) 221 mflr 0 /* save return address */ 222 stw 0,4(1) 223 stwu 1,-16(1) /* setup stack frame */ 224 225 mfmsr 4 /* save msr */ 226 stw 4,8(1) 227 228 lis 4,openfirmware_entry@ha /* get firmware entry point */ 229 lwz 4,openfirmware_entry@l(4) 230 mtlr 4 231 232 li 0,0 /* clear battable translations */ 233 mtdbatu 2,0 234 mtdbatu 3,0 235 mtibatu 2,0 236 mtibatu 3,0 237 238 lis 4,srsave@ha /* save old SR */ 239 addi 4,4,srsave@l 240 li 5,0 2411: mfsrin 0,5 242 stw 0,0(4) 243 addi 4,4,4 244 addis 5,5,0x10000000@h 245 cmpwi 5,0 246 bne 1b 247 248 lis 4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */ 249 addi 4,4,_C_LABEL(ofw_pmap)@l 250 lwz 0,PM_KERNELSR(4) 251 cmpwi 0,0 /* pm_sr[KERNEL_SR] == 0? */ 252 beq 2f /* then skip (not initialized yet) */ 253 li 5,0 2541: lwz 0,0(4) 255 mtsrin 0,5 256 addi 4,4,4 257 addis 5,5,0x10000000@h 258 cmpwi 5,0 259 bne 1b 2602: 261 lis 4,ofmsr@ha /* Open Firmware msr + sprg[0-3] */ 262 lwz 5,ofmsr+4@l(4) 263 mtsprg 0,5 264 lwz 5,ofmsr+8@l(4) 265 mtsprg 1,5 266 lwz 5,ofmsr+12@l(4) 267 mtsprg 2,5 268 lwz 5,ofmsr+16@l(4) 269 mtsprg 3,5 270 lwz 5,ofmsr@l(4) 271 mtmsr 5 272 isync 273 274 blrl /* call Open Firmware */ 275 276 lis 4,srsave@ha /* restore saved SR */ 277 addi 4,4,srsave@l 278 li 5,0 2791: lwz 0,0(4) 280 mtsrin 0,5 281 addi 4,4,4 282 addis 5,5,0x10000000@h 283 cmpwi 5,0 284 bne 1b 285 286 lwz 4,8(1) /* restore msr */ 287 mtmsr 4 288 isync 289 290 lwz 1,0(1) /* and return */ 291 lwz 0,4(1) 292 mtlr 0 293 blr 294 295/* 296 * Switch to/from OpenFirmware real mode stack 297 * 298 * Note: has to be called as the very first thing in OpenFirmware interface 299 * routines. 300 * E.g.: 301 * int 302 * OF_xxx(arg1, arg2) 303 * type arg1, arg2; 304 * { 305 * static struct { 306 * char *name; 307 * int nargs; 308 * int nreturns; 309 * char *method; 310 * int arg1; 311 * int arg2; 312 * int ret; 313 * } args = { 314 * "xxx", 315 * 2, 316 * 1, 317 * }; 318 * 319 * ofw_stack(); 320 * args.arg1 = arg1; 321 * args.arg2 = arg2; 322 * if (openfirmware(&args) < 0) 323 * return -1; 324 * return args.ret; 325 * } 326 */ 327 328 .local firmstk 329 .comm firmstk,NBPG,8 330 331ENTRY(ofw_stack) 332 mfmsr 8 /* turn off interrupts */ 333 andi. 0,8,~(PSL_EE|PSL_RI)@l 334 mtmsr 0 335 stw 8,4(1) /* abuse return address slot */ 336 337 lwz 5,0(1) /* get length of stack frame */ 338 subf 5,1,5 339 340 lis 7,firmstk+NBPG-8@ha 341 addi 7,7,firmstk+NBPG-8@l 342 lis 6,ofw_back@ha 343 addi 6,6,ofw_back@l 344 subf 4,5,7 /* make room for stack frame on 345 new stack */ 346 stw 6,-4(7) /* setup return pointer */ 347 stwu 1,-8(7) 348 349 stw 7,-8(4) 350 351 addi 3,1,8 352 addi 1,4,-8 353 subi 5,5,8 354 355 b _C_LABEL(ofbcopy) /* and copy it */ 356 357ofw_back: 358 lwz 1,0(1) /* get callers original stack pointer */ 359 360 lwz 0,4(1) /* get saved msr from abused slot */ 361 mtmsr 0 362 363 lwz 1,0(1) /* return */ 364 lwz 0,4(1) 365 mtlr 0 366 blr 367 368#if defined(MULTIPROCESSOR) 369 .globl _C_LABEL(cpu_spinup_trampoline) 370_C_LABEL(cpu_spinup_trampoline): 371 li 0,0 372 mtmsr 0 373 isync 374 375 lis 3,_C_LABEL(cpu_hatch_stack)@ha 376 lwz 1,_C_LABEL(cpu_hatch_stack)@l(3) 377 378 bl _C_LABEL(cpu_hatch) 379 bl _C_LABEL(sched_lock_idle) 380 li 30,0 381 b _ASM_LABEL(Idle) 382#endif 383 384/* 385 * Pull in common switch and setfault code. 386 */ 387#include <powerpc/powerpc/locore_subr.S> 388 389/* 390 * Pull in common trap vector code. 391 */ 392#if defined(MULTIPROCESSOR) 393#include <powerpc/powerpc/trap_subr_mp.S> 394#else 395#include <powerpc/powerpc/trap_subr.S> 396#endif 397