1 /* $NetBSD: locore.s,v 1.174 2025/12/04 02:55:23 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1980, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: locore.s 1.58 91/04/22$ 37 * 38 * @(#)locore.s 7.11 (Berkeley) 5/9/91 39 * 40 * Original (hp300) Author: unknown, maybe Mike Hibler? 41 * Amiga author: Markus Wild 42 * Other contributors: Bryan Ford (kernel reload stuff) 43 */ 44 45 #include "opt_fpu_emulate.h" 46 #include "opt_bb060stupidrom.h" 47 #include "opt_p5ppc68kboard.h" 48 #include "opt_compat_netbsd.h" 49 #include "opt_compat_sunos.h" 50 #include "opt_fpsp.h" 51 #include "opt_kgdb.h" 52 #include "opt_lockdebug.h" 53 #include "opt_lev6_defer.h" 54 #include "opt_m68k_arch.h" 55 56 #include "assym.h" 57 #include <machine/asm.h> 58 #include <machine/trap.h> 59 60 .text 61 GLOBAL(kernel_text) 62 L_base: 63 .long 0x4ef80400+PAGE_SIZE /* jmp jmp0.w */ 64 .fill PAGE_SIZE/4-1,4,0/*xdeadbeef*/ 65 66 #include <amiga/amiga/vectors.s> 67 #include <amiga/amiga/custom.h> 68 69 #ifdef DRACO 70 #include <amiga/amiga/drcustom.h> 71 #endif 72 73 #define CIAAADDR(ar) movl _C_LABEL(CIAAbase),ar 74 #define CIABADDR(ar) movl _C_LABEL(CIABbase),ar 75 #define CUSTOMADDR(ar) movl _C_LABEL(CUSTOMbase),ar 76 #define INTREQRADDR(ar) movl _C_LABEL(INTREQRaddr),ar 77 #define INTREQWADDR(ar) movl _C_LABEL(INTREQWaddr),ar 78 #define INTENAWADDR(ar) movl _C_LABEL(amiga_intena_write),ar 79 #define INTENARADDR(ar) movl _C_LABEL(amiga_intena_read),ar 80 81 .text 82 /* 83 * This is where we wind up if the kernel jumps to location 0. 84 * (i.e. a bogus PC) This is known to immediately follow the vector 85 * table and is hence at 0x400 (see reset vector in vectors.s). 86 */ 87 pea Ljmp0panic 88 jbsr _C_LABEL(panic) 89 /* NOTREACHED */ 90 Ljmp0panic: 91 .asciz "kernel jump to zero" 92 .even 93 94 /* 95 * Do a dump. 96 * Called by auto-restart. 97 */ 98 ENTRY_NOPROFILE(doadump) 99 jbsr _C_LABEL(dumpsys) 100 jbsr _C_LABEL(doboot) 101 /*NOTREACHED*/ 102 103 /* 104 * Trap/interrupt vector routines 105 */ 106 #include <m68k/m68k/trap_subr.s> 107 108 #if defined(M68040) || defined(M68060) 109 ENTRY_NOPROFILE(addrerr4060) 110 clrl %sp@- | stack adjust count 111 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 112 movl %usp,%a0 | save the user SP 113 movl %a0,%sp@(FR_SP) | in the savearea 114 movl %sp@(FR_HW+8),%sp@- 115 clrl %sp@- | dummy code 116 movl #T_ADDRERR,%sp@- | mark address error 117 jra _ASM_LABEL(faultstkadj) | and deal with it 118 #endif 119 120 #if defined(M68060) 121 ENTRY_NOPROFILE(buserr60) 122 clrl %sp@- | stack adjust count 123 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 124 movl %usp,%a0 | save the user SP 125 movl %a0,%sp@(FR_SP) | in the savearea 126 movel %sp@(FR_HW+12),%d0 | FSLW 127 btst #2,%d0 | branch prediction error? 128 jeq Lnobpe 129 movc %cacr,%d2 130 orl #IC60_CABC,%d2 | clear all branch cache entries 131 movc %d2,%cacr 132 movl %d0,%d1 133 addql #1,L60bpe 134 andl #0x7ffd,%d1 135 jeq _ASM_LABEL(faultstkadjnotrap2) 136 Lnobpe: 137 | we need to adjust for misaligned addresses 138 movl %sp@(FR_HW+8),%d1 | grab VA 139 btst #27,%d0 | check for mis-aligned access 140 jeq Lberr3 | no, skip 141 addl #28,%d1 | yes, get into next page 142 | operand case: 3, 143 | instruction case: 4+12+12 144 andl #PG_FRAME,%d1 | and truncate 145 Lberr3: 146 movl %d1,%sp@- 147 movl %d0,%sp@- | code is FSLW now. 148 andw #0x1f80,%d0 149 jeq Lisberr 150 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 151 jra _ASM_LABEL(faultstkadj) | and deal with it 152 #endif 153 #if defined(M68040) 154 ENTRY_NOPROFILE(buserr40) 155 clrl %sp@- | stack adjust count 156 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 157 movl %usp,%a0 | save the user SP 158 movl %a0,%sp@(FR_SP) | in the savearea 159 movl %sp@(FR_HW+20),%d1 | get fault address 160 moveq #0,%d0 161 movw %sp@(FR_HW+12),%d0 | get SSW 162 btst #11,%d0 | check for mis-aligned 163 jeq Lbe1stpg | no skip 164 addl #3,%d1 | get into next page 165 andl #PG_FRAME,%d1 | and truncate 166 Lbe1stpg: 167 movl %d1,%sp@- | pass fault address. 168 movl %d0,%sp@- | pass SSW as code 169 btst #10,%d0 | test ATC 170 jeq Lisberr | it is a bus error 171 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 172 jra _ASM_LABEL(faultstkadj) | and deal with it 173 #endif 174 175 ENTRY_NOPROFILE(buserr) 176 ENTRY_NOPROFILE(addrerr) 177 #if !(defined(M68020) || defined(M68030)) 178 jra _C_LABEL(badtrap) 179 #else 180 clrl %sp@- | stack adjust count 181 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 182 movl %usp,%a0 | save the user SP 183 movl %a0,%sp@(FR_SP) | in the savearea 184 moveq #0,%d0 185 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 186 btst #12,%d0 | RB set? 187 jeq LbeX0 | no, test RC 188 bset #14,%d0 | yes, must set FB 189 movw %d0,%sp@(FR_HW+10) | for hardware too 190 LbeX0: 191 btst #13,%d0 | RC set? 192 jeq LbeX1 | no, skip 193 bset #15,%d0 | yes, must set FC 194 movw %d0,%sp@(FR_HW+10) | for hardware too 195 LbeX1: 196 btst #8,%d0 | data fault? 197 jeq Lbe0 | no, check for hard cases 198 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 199 jra Lbe10 | thats it 200 Lbe0: 201 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 202 jne Lbe4 | yes, go handle 203 movl %sp@(FR_HW+2),%d1 | no, can use save PC 204 btst #14,%d0 | FB set? 205 jeq Lbe3 | no, try FC 206 addql #4,%d1 | yes, adjust address 207 jra Lbe10 | done 208 Lbe3: 209 btst #15,%d0 | FC set? 210 jeq Lbe10 | no, done 211 addql #2,%d1 | yes, adjust address 212 jra Lbe10 | done 213 Lbe4: 214 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 215 btst #15,%d0 | FC set? 216 jeq Lbe10 | no, all done 217 subql #2,%d1 | yes, adjust address 218 Lbe10: 219 movl %d1,%sp@- | push fault VA 220 movl %d0,%sp@- | and padded SSW 221 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 222 andw #0x0FFF,%d0 | clear out frame format 223 cmpw #12,%d0 | address error vector? 224 jeq Lisaerr | yes, go to it 225 movl %d1,%a0 | fault address 226 movl %sp@,%d0 | function code from ssw 227 btst #8,%d0 | data fault? 228 jne Lbe10a 229 movql #1,%d0 | user program access FC 230 | (we dont separate data/program) 231 btst #5,%sp@(FR_HW+8) | supervisor mode? 232 jeq Lbe10a | if no, done 233 movql #5,%d0 | else supervisor program access 234 Lbe10a: 235 ptestr %d0,%a0@,#7 | do a table search 236 pmove %psr,%sp@ | save result 237 movb %sp@,%d1 238 btst #2,%d1 | invalid (incl. limit viol. and berr)? 239 jeq Lmightnotbemerr | no -> wp check 240 btst #7,%d1 | is it MMU table berr? 241 jeq Lismerr | no, must be fast 242 jra Lisberr1 | real bus err needs not be fast. 243 Lmightnotbemerr: 244 btst #3,%d1 | write protect bit set? 245 jeq Lisberr1 | no: must be bus error 246 movl %sp@,%d0 | ssw into low word of d0 247 andw #0xc0,%d0 | Write protect is set on page: 248 cmpw #0x40,%d0 | was it read cycle? 249 jeq Lisberr1 | yes, was not WPE, must be bus err 250 Lismerr: 251 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 252 jra _ASM_LABEL(faultstkadj) | and deal with it 253 Lisaerr: 254 movl #T_ADDRERR,%sp@- | mark address error 255 jra _ASM_LABEL(faultstkadj) | and deal with it 256 Lisberr1: 257 clrw %sp@ | re-clear pad word 258 #endif 259 Lisberr: | also used by M68040/60 260 tstl _C_LABEL(nofault) | device probe? 261 jeq LberrIsProbe | no, handle as usual 262 movl _C_LABEL(nofault),%sp@- | yes, 263 jbsr _C_LABEL(longjmp) | longjmp(nofault) 264 /* NOTREACHED */ 265 LberrIsProbe: 266 movl #T_BUSERR,%sp@- | mark bus error 267 jra _ASM_LABEL(faultstkadj) | and deal with it 268 269 /* 270 * FP exceptions. 271 */ 272 ENTRY_NOPROFILE(fpfline) 273 #if defined(M68040) 274 cmpw #0x202c,%sp@(6) | format type 2? 275 jne _C_LABEL(illinst) | no, not an FP emulation 276 #ifdef FPSP 277 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 278 #endif 279 #endif 280 281 #ifdef FPU_EMULATE 282 ENTRY_NOPROFILE(fpemuli) 283 addql #1,Lfpecnt 284 clrl %sp@- | stack adjust count 285 moveml %d0-%d7/%a0-%a7,%sp@- | save registers 286 movql #T_FPEMULI,%d0 | denote as FP emulation trap 287 jra _ASM_LABEL(fault) | do it 288 #endif 289 290 ENTRY_NOPROFILE(fpunsupp) 291 #if defined(M68040) 292 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 293 jne _C_LABEL(illinst) | no, treat as illinst 294 #ifdef FPSP 295 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 296 #else 297 clrl %sp@- | stack adjust count 298 moveml %d0-%d7/%a0-%a7,%sp@- | save registers 299 movql #T_FPEMULD,%d0 | denote as FP emulation trap 300 jra _ASM_LABEL(fault) | do it 301 #endif 302 #else 303 jra _C_LABEL(illinst) 304 #endif 305 /* 306 * Handles all other FP coprocessor exceptions. 307 * Note that since some FP exceptions generate mid-instruction frames 308 * and may cause signal delivery, we need to test for stack adjustment 309 * after the trap call. 310 */ 311 ENTRY_NOPROFILE(fpfault) 312 #ifdef FPCOPROC 313 clrl %sp@- | stack adjust count 314 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 315 movl %usp,%a0 | and save 316 movl %a0,%sp@(FR_SP) | the user stack pointer 317 clrl %sp@- | no VA arg 318 movl _C_LABEL(curpcb),%a0 | current pcb 319 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 320 fsave %a0@ | save state 321 #if defined(M68020) || defined(M68030) 322 #if defined(M68060) || defined(M68040) 323 movb _C_LABEL(machineid)+3,%d0 324 andb #0x90,%d0 | AMIGA_68060 | AMIGA_68040 325 jne Lfptnull | XXX 326 #endif 327 tstb %a0@ | null state frame? 328 jeq Lfptnull | yes, safe 329 clrw %d0 | no, need to tweak BIU 330 movb %a0@(1),%d0 | get frame size 331 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 332 Lfptnull: 333 #endif 334 fmovem %fpsr,%sp@- | push fpsr as code argument 335 frestore %a0@ | restore state 336 movl #T_FPERR,%sp@- | push type arg 337 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 338 #else 339 jra _C_LABEL(badtrap) | treat as an unexpected trap 340 #endif 341 342 /* 343 * Other exceptions only cause four and six word stack frame and require 344 * no post-trap stack adjustment. 345 */ 346 347 ENTRY_NOPROFILE(badtrap) 348 INTERRUPT_SAVEREG 349 movw %sp@(22),%sp@- | push exception vector info 350 clrw %sp@- 351 movl %sp@(22),%sp@- | and PC 352 jbsr _C_LABEL(straytrap) | report 353 addql #8,%sp | pop args 354 INTERRUPT_RESTOREREG | restore regs 355 jra _ASM_LABEL(rei) | all done 356 357 ENTRY_NOPROFILE(trap0) 358 clrl %sp@- | stack adjust count 359 moveml %d0-%d7/%a0-%a7,%sp@- | save user registers 360 movl %usp,%a0 | save the user SP 361 movl %a0,%sp@(FR_SP) | in the savearea 362 movl %d0,%sp@- | push syscall number 363 jbsr _C_LABEL(syscall) | handle it 364 addql #4,%sp | pop syscall arg 365 movl %sp@(FR_SP),%a0 | grab and restore 366 movl %a0,%usp | user SP 367 moveml %sp@+,%d0-%d7/%a0-%a6 | restore most registers 368 addql #8,%sp | pop SP and stack adjust 369 jra _ASM_LABEL(rei) | all done 370 371 /* 372 * Trap 12 is the entry point for the cachectl "syscall" 373 * cachectl(command, addr, length) 374 * command in d0, addr in a1, length in d1 375 */ 376 ENTRY_NOPROFILE(trap12) 377 movl _C_LABEL(curlwp),%a0 378 movl %a0@(L_PROC),%sp@- | push current proc pointer 379 movl %d1,%sp@- | push length 380 movl %a1,%sp@- | push addr 381 movl %d0,%sp@- | push command 382 jbsr _C_LABEL(cachectl1) | do it 383 lea %sp@(16),%sp | pop args 384 jra _ASM_LABEL(rei) | all done 385 386 /* 387 * Trap 15 is used for: 388 * - KGDB traps 389 * - trace traps for SUN binaries (not fully supported yet) 390 * We just pass it on and let trap() sort it all out 391 */ 392 ENTRY_NOPROFILE(trap15) 393 clrl %sp@- 394 moveml %d0-%d7/%a0-%a7,%sp@- 395 #ifdef KGDB 396 moveq #T_TRAP15,%d0 397 movw %sp@(FR_HW),%d1 | get PSW 398 andw #PSL_S,%d1 | from user mode? 399 jeq _ASM_LABEL(fault) | yes, just a regular fault 400 movl %d0,%sp@- 401 jbsr _C_LABEL(kgdb_trap_glue) | returns if no debugger 402 addl #4,%sp 403 #endif 404 moveq #T_TRAP15,%d0 405 jra _ASM_LABEL(fault) 406 407 /* 408 * Hit a breakpoint (trap 1 or 2) instruction. 409 * Push the code and treat as a normal fault. 410 */ 411 ENTRY_NOPROFILE(trace) 412 clrl %sp@- 413 moveml %d0-%d7/%a0-%a7,%sp@- 414 #ifdef KGDB 415 moveq #T_TRACE,%d0 416 movw %sp@(FR_HW),%d1 | get SSW 417 andw #PSL_S,%d1 | from user mode? 418 jeq _ASM_LABEL(fault) | no, regular fault 419 movl %d0,%sp@- 420 jbsr _C_LABEL(kgdb_trap_glue) | returns if no debugger 421 addl #4,%sp 422 #endif 423 moveq #T_TRACE,%d0 424 jra _ASM_LABEL(fault) 425 426 /* 427 * Interrupt handlers. 428 * 429 * Level 0: Spurious: ignored. 430 * Level 1: builtin-RS232 TBE, softint (not used yet) 431 * Level 2: keyboard (CIA-A) + DMA + SCSI 432 * Level 3: VBL 433 * Level 4: not used 434 * Level 5: builtin-RS232 RBF 435 * Level 6: Clock (CIA-B-Timers), Floppy index pulse 436 * Level 7: Non-maskable: shouldn't be possible. ignore. 437 */ 438 439 /* Provide a generic interrupt dispatcher, only handle hardclock (int6) 440 * and serial RBF (int5) specially, to improve performance 441 */ 442 ENTRY_NOPROFILE(spurintr) 443 addql #1,_C_LABEL(intr_depth) 444 addql #1,_C_LABEL(intrcnt)+0 445 INTERRUPT_SAVEREG 446 CPUINFO_INCREMENT(CI_NINTR) 447 INTERRUPT_RESTOREREG 448 subql #1,_C_LABEL(intr_depth) 449 jra _ASM_LABEL(rei) 450 451 ENTRY_NOPROFILE(lev5intr) 452 addql #1,_C_LABEL(intr_depth) 453 INTERRUPT_SAVEREG 454 #include "ser.h" 455 #if NSER > 0 456 jsr _C_LABEL(ser_fastint) 457 #else 458 INTREQWADDR(%a0) 459 movew #INTF_RBF,%a0@ | clear RBF interrupt in intreq 460 #endif 461 CPUINFO_INCREMENT(CI_NINTR) 462 INTERRUPT_RESTOREREG 463 addql #1,_C_LABEL(intrcnt)+20 464 subql #1,_C_LABEL(intr_depth) 465 jra _ASM_LABEL(rei) 466 467 #ifdef DRACO 468 ENTRY_NOPROFILE(DraCoLev2intr) 469 addql #1,_C_LABEL(intr_depth) 470 INTERRUPT_SAVEREG 471 472 CIAAADDR(%a0) 473 movb %a0@(CIAICR),%d0 | read irc register (clears ints!) 474 jge Ldrintrcommon | CIAA IR not set, go through isr chain 475 movel _C_LABEL(draco_intpen),%a0 476 | andib #4,%a0@ 477 |XXX this would better be 478 bclr #2,%a0@ 479 btst #0,%d0 | timerA interrupt? 480 jeq Ldraciaend 481 482 movl %sp,%sp@- | push pointer to clockframe 483 movw #PSL_HIGHIPL,%sr | hardclock at high IPL 484 jbsr _C_LABEL(hardclock) | call generic clock int routine 485 addql #4,%sp | pop params 486 addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt 487 488 Ldraciaend: 489 CPUINFO_INCREMENT(CI_NINTR) 490 INTERRUPT_RESTOREREG 491 subql #1,_C_LABEL(intr_depth) 492 jra _ASM_LABEL(rei) 493 494 /* XXX on the DraCo rev. 4 or later, lev 1 is vectored here. */ 495 ENTRY_NOPROFILE(DraCoLev1intr) 496 addql #1,_C_LABEL(intr_depth) 497 INTERRUPT_SAVEREG 498 movl _C_LABEL(draco_ioct),%a0 499 btst #5,%a0@(7) 500 jeq Ldrintrcommon 501 btst #4,%a0@(7) | this only happens during autoconfiguration, 502 jeq Ldrintrcommon | so test last. 503 movw #PSL_HIGHIPL,%sr | run clock at high ipl 504 Ldrclockretry: 505 movl %sp,%sp@- | push pointer to clockframe 506 jbsr _C_LABEL(hardclock) 507 addql #4,%sp | pop params 508 addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt 509 510 movl _C_LABEL(draco_ioct),%a0 511 tstb %a0@(9) | latch timer value 512 movw %a0@(11),%d0 | can't use movpw here, might be 68060 513 movb %a0@(13),%d0 514 addw _C_LABEL(amiga_clk_interval)+2,%d0 515 movb %d0,%a0@(13) | low byte: latch write value 516 movw %d0,%a0@(11) | ...and write it into timer 517 tstw %d0 | already positive? 518 jcs Ldrclockretry | we lost more than one tick, call us again. 519 520 clrb %a0@(9) | reset timer irq 521 522 CPUINFO_INCREMENT(CI_NINTR) 523 INTERRUPT_RESTOREREG 524 subql #1,_C_LABEL(intr_depth) 525 jra _ASM_LABEL(rei) | XXXX: shouldn't we call the normal lev1? 526 527 /* XXX on the DraCo, lev 1, 3, 4, 5 and 6 are vectored here by initcpu() */ 528 ENTRY_NOPROFILE(DraCoIntr) 529 addql #1,_C_LABEL(intr_depth) 530 INTERRUPT_SAVEREG 531 Ldrintrcommon: 532 lea _ASM_LABEL(Drintrcnt)-4,%a0 533 movw %sp@(22),%d0 | use vector offset 534 andw #0xfff,%d0 | sans frame type 535 addql #1,%a0@(-0x60,%d0:w) | to increment apropos counter 536 movw %sr,%sp@- | push current SR value 537 clrw %sp@- | padded to longword 538 jbsr _C_LABEL(intrhand) | handle interrupt 539 addql #4,%sp | pop SR 540 CPUINFO_INCREMENT(CI_NINTR) 541 INTERRUPT_RESTOREREG 542 subql #1,_C_LABEL(intr_depth) 543 jra _ASM_LABEL(rei) 544 #endif 545 546 547 ENTRY_NOPROFILE(lev1intr) 548 ENTRY_NOPROFILE(lev2intr) 549 ENTRY_NOPROFILE(lev3intr) 550 #ifndef LEV6_DEFER 551 ENTRY_NOPROFILE(lev4intr) 552 #endif 553 addql #1,_C_LABEL(intr_depth) 554 INTERRUPT_SAVEREG 555 Lintrcommon: 556 lea _C_LABEL(intrcnt),%a0 557 movw %sp@(22),%d0 | use vector offset 558 andw #0xfff,%d0 | sans frame type 559 addql #1,%a0@(-0x60,%d0:w) | to increment apropos counter 560 movw %sr,%sp@- | push current SR value 561 clrw %sp@- | padded to longword 562 jbsr _C_LABEL(intrhand) | handle interrupt 563 addql #4,%sp | pop SR 564 CPUINFO_INCREMENT(CI_NINTR) 565 INTERRUPT_RESTOREREG 566 subql #1,_C_LABEL(intr_depth) 567 jra _ASM_LABEL(rei) 568 569 /* XXX used to be ifndef DRACO; vector will be overwritten by initcpu() */ 570 571 ENTRY_NOPROFILE(lev6intr) 572 #ifdef LEV6_DEFER 573 /* 574 * cause a level 4 interrupt (AUD3) to occur as soon 575 * as we return. Block generation of level 6 ints until 576 * we have dealt with this one. 577 */ 578 addql #1,_C_LABEL(intr_depth) 579 moveml %d0/%a0,%sp@- 580 INTREQRADDR(%a0) 581 movew %a0@,%d0 582 btst #INTB_EXTER,%d0 583 jeq Llev6spur 584 INTREQWADDR(%a0) 585 movew #INTF_SETCLR+INTF_AUD3,%a0@ 586 INTENAWADDR(%a0) 587 movew #INTF_EXTER,%a0@ 588 movew #INTF_SETCLR+INTF_AUD3,%a0@ | make sure THIS one is ok... 589 moveml %sp@+,%d0/%a0 590 subql #1,_C_LABEL(intr_depth) 591 rte 592 Llev6spur: 593 addql #1,_C_LABEL(intrcnt)+36 | count spurious level 6 interrupts 594 moveml %sp@+,%d0/%a0 595 subql #1,_C_LABEL(intr_depth) 596 rte 597 598 ENTRY_NOPROFILE(lev4intr) 599 ENTRY_NOPROFILE(fake_lev6intr) 600 #endif 601 addql #1,_C_LABEL(intr_depth) 602 INTERRUPT_SAVEREG 603 #ifdef LEV6_DEFER 604 /* 605 * check for fake level 6 606 */ 607 INTREQRADDR(%a0) 608 movew %a0@,%d0 609 btst #INTB_EXTER,%d0 610 jeq Lintrcommon | if EXTER not pending, handle normally 611 #endif 612 613 CIABADDR(%a0) 614 movb %a0@(CIAICR),%d0 | read irc register (clears ints!) 615 jge Lchkexter | CIAB IR not set, go through isr chain 616 INTREQWADDR(%a0) 617 #ifndef LEV6_DEFER 618 movew #INTF_EXTER,%a0@ | clear EXTER interrupt in intreq 619 #else 620 movew #INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 in intreq 621 INTENAWADDR(%a0) 622 movew #INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts 623 #endif 624 btst #0,%d0 | timerA interrupt? 625 jeq Ltstciab4 | no 626 movl %d0,%sp@- | push CIAB interrupt flags 627 lea %sp@(4),%a1 | get pointer to clockframe 628 movl %a1,%sp@- | push pointer to clockframe 629 jbsr _C_LABEL(hardclock) | call generic clock int routine 630 addql #4,%sp | pop params 631 addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt 632 movl %sp@+,%d0 | pop interrupt flags 633 Ltstciab4: 634 #include "fd.h" 635 #if NFD > 0 636 btst #4,%d0 | FLG (dskindex) interrupt? 637 jeq Lskipciab | no 638 jbsr _C_LABEL(fdidxintr) | tell floppy driver we got it 639 Lskipciab: 640 #endif 641 | other ciab interrupts? 642 Llev6done: 643 CPUINFO_INCREMENT(CI_NINTR) 644 INTERRUPT_RESTOREREG 645 subql #1,_C_LABEL(intr_depth) 646 jra _ASM_LABEL(rei) | all done [can we do rte here?] 647 Lchkexter: 648 | check to see if EXTER request is really set? 649 movl _C_LABEL(isr_exter),%a0 | get head of EXTER isr chain 650 Lnxtexter: 651 movl %a0,%d0 | test if any more entries 652 jeq Lexterdone | (spurious interrupt?) 653 movl %a0,%sp@- | save isr pointer 654 movl %a0@(ISR_ARG),%sp@- 655 movl %a0@(ISR_INTR),%a0 656 jsr %a0@ | call isr handler 657 addql #4,%sp 658 movl %sp@+,%a0 | restore isr pointer 659 movl %a0@(ISR_FORW),%a0 | get next pointer 660 tstl %d0 | did handler process the int? 661 jeq Lnxtexter | no, try next 662 Lexterdone: 663 INTREQWADDR(%a0) 664 #ifndef LEV6_DEFER 665 movew #INTF_EXTER,%a0@ | clear EXTER interrupt 666 #else 667 movew #INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 interrupt 668 INTENAWADDR(%a0) 669 movew #INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts 670 #endif 671 addql #1,_C_LABEL(intrcnt)+24 | count EXTER interrupts 672 jra Llev6done 673 /* XXX endifndef DRACO used to be here */ 674 675 ENTRY_NOPROFILE(lev7intr) 676 addql #1,_C_LABEL(intrcnt)+28 677 /* 678 * some amiga zorro2 boards seem to generate spurious NMIs. Best 679 * thing to do is to return as quick as possible. That's the 680 * reason why I do RTE here instead of jra rei. 681 */ 682 rte | all done 683 684 685 /* 686 * Emulation of VAX REI instruction. 687 * 688 * This code deals with checking for and servicing ASTs 689 * (profiling, scheduling) and software interrupts (network, softclock). 690 * We check for ASTs first, just like the VAX. To avoid excess overhead 691 * the T_ASTFLT handling code will also check for software interrupts so we 692 * do not have to do it here. After identifying that we need an AST we 693 * drop the IPL to allow device interrupts. 694 * 695 * This code is complicated by the fact that sendsig may have been called 696 * necessitating a stack cleanup. A cleanup should only be needed at this 697 * point for coprocessor mid-instruction frames (type 9), but we also test 698 * for bus error frames (type 10 and 11). 699 */ 700 ASENTRY_NOPROFILE(rei) 701 #ifdef DEBUG 702 tstl _C_LABEL(panicstr) | have we panicked? 703 jne Ldorte | yes, do not make matters worse 704 #endif 705 tstl _C_LABEL(astpending) | AST pending? 706 jeq Ldorte | no, done 707 Lrei1: 708 btst #5,%sp@ | yes, are we returning to user mode? 709 jne Ldorte | no, done 710 movw #PSL_LOWIPL,%sr | lower SPL 711 clrl %sp@- | stack adjust 712 moveml %d0-%d7/%a0-%a7,%sp@- | save all registers 713 movl %usp,%a1 | including 714 movl %a1,%sp@(FR_SP) | the users SP 715 clrl %sp@- | VA == none 716 clrl %sp@- | code == none 717 movl #T_ASTFLT,%sp@- | type == async system trap 718 pea %sp@(12) | fp == address of trap frame 719 jbsr _C_LABEL(trap) | go handle it 720 lea %sp@(16),%sp | pop value args 721 movl %sp@(FR_SP),%a0 | restore user SP 722 movl %a0,%usp | from save area 723 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 724 jne Laststkadj | yes, go to it 725 moveml %sp@+,%d0-%d7/%a0-%a6 | no, restore most user regs 726 addql #8,%sp | toss SP and stack adjust 727 rte | and do real RTE 728 Laststkadj: 729 lea %sp@(FR_HW),%a1 | pointer to HW frame 730 addql #8,%a1 | source pointer 731 movl %a1,%a0 | source 732 addw %d0,%a0 | + hole size = dest pointer 733 movl %a1@-,%a0@- | copy 734 movl %a1@-,%a0@- | 8 bytes 735 movl %a0,%sp@(FR_SP) | new SSP 736 moveml %sp@+,%d0-%d7/%a0-%a6 | restore user registers 737 movl %sp@,%sp | and our SP 738 Ldorte: 739 rte | real return 740 741 /* 742 * Kernel access to the current processes kernel stack is via a fixed 743 * virtual address. It is at the same address as in the users VA space. 744 */ 745 BSS(esym,4) 746 747 748 /* 749 * Initialization 750 * 751 * A5 contains physical load point from boot 752 * exceptions vector thru our table, that's bad.. just hope nothing exceptional 753 * happens till we had time to initialize ourselves.. 754 */ 755 BSS(lowram,4) 756 757 #define RELOC(var, ar) \ 758 lea _C_LABEL(var),ar; \ 759 addl %a5,ar 760 761 #define ASRELOC(var, ar) \ 762 lea _ASM_LABEL(var),ar; \ 763 addl %a5,ar 764 765 .text 766 767 | XXX should be a symbol? 768 | 2: needs a4 = esym 769 | 3: no chipmem requirement 770 | bootinfo data structure 771 772 .word 0 773 .word 0x0003 | loadbsd version required 774 ASENTRY_NOPROFILE(start) 775 lea %pc@(L_base),%a5 | initialize relocation register 776 777 movw #PSL_HIGHIPL,%sr | no interrupts 778 ASRELOC(tmpstk,%a6) 779 movl %a6,%sp | give ourselves a temporary stack 780 781 | save the passed parameters. "prepass" them on the stack for 782 | later catch by start_c() 783 movl %a5,%sp@- | pass loadbase 784 movl %d6,%sp@- | pass boot partition offset 785 movl %a2,%sp@- | pass sync inhibit flags 786 movl %d3,%sp@- | pass AGA mode 787 movl %a4,%sp@- | pass address of _esym 788 movl %d1,%sp@- | pass chipmem-size 789 movl %d0,%sp@- | pass fastmem-size 790 movl %a0,%sp@- | pass fastmem_start 791 movl %d5,%sp@- | pass machine id 792 793 /* 794 * initialize some hw addresses to their physical address 795 * for early running 796 */ 797 #ifdef DRACO 798 /* 799 * this is already dynamically done on DraCo 800 */ 801 cmpb #0x7D,%sp@ 802 jne LisAmiga1 803 | debug code: 804 | we should need about 1 uSec for the loop. 805 | we dont need the AGA mode register. 806 movel #100000,%d3 807 LisDraco0: 808 #ifdef DEBUG_KERNEL_START 809 movb #0,0x200003c8 810 movb #00,0x200003c9 811 movb #40,0x200003c9 812 movb #00,0x200003c9 813 |XXX: 814 movb #0,0x200003c8 815 movb #40,0x200003c9 816 movb #00,0x200003c9 817 movb #00,0x200003c9 818 subql #1,%d3 819 jcc LisDraco0 820 #endif 821 822 RELOC(chipmem_start, %a0) 823 movl #0,%a0@ 824 825 RELOC(CIAAbase, %a0) 826 movl #0x2801001, %a0@ 827 RELOC(CIABbase, %a0) 828 movl #0x2800000, %a0@ 829 830 /* XXXX more to come here; as we need it */ 831 832 jra LisDraco1 833 LisAmiga1: 834 #endif 835 RELOC(chipmem_start, %a0) 836 movl #0x400,%a0@ 837 RELOC(CIAAbase, %a0) 838 movl #0xbfe001,%a0@ 839 RELOC(CIABbase, %a0) 840 movl #0xbfd000,%a0@ 841 RELOC(CUSTOMbase, %a0) 842 movl #0xdff000,%a0@ 843 844 #ifdef DRACO 845 LisDraco1: 846 #endif 847 /* 848 * initialize the timer frequency 849 */ 850 RELOC(eclockfreq, %a0) 851 movl %d4,%a0@ 852 853 movl #AMIGA_68030,%d1 | 68030 Attn flag from exec 854 andl %d5,%d1 855 jeq Ltestfor020 856 RELOC(mmutype, %a0) 857 movl #MMU_68030,%a0@ | assume 020 means 851 858 RELOC(cputype, %a0) 859 movl #CPU_68030,%a0@ 860 jra Lsetcpu040 | skip to init. 861 Ltestfor020: 862 movl #AMIGA_68020,%d1 | 68020 Attn flag from exec 863 andl %d5,%d1 864 jeq Lsetcpu040 865 RELOC(mmutype, %a0) 866 movl #MMU_68851,%a0@ 867 RELOC(cputype, %a0) 868 movl #CPU_68020,%a0@ 869 Lsetcpu040: 870 movl #CACHE_OFF,%d0 | 68020/030 cache 871 movl #AMIGA_68040,%d1 872 andl %d1,%d5 873 jeq Lstartnot040 | it is not 68040 874 RELOC(mmutype, %a0) 875 movl #MMU_68040,%a0@ | same as hp300 for compat 876 RELOC(cputype, %a0) 877 movl #CPU_68040,%a0@ 878 .word 0xf4f8 | cpusha bc - push and invalidate caches 879 movl #CACHE40_OFF,%d0 | 68040 cache disable 880 #ifndef BB060STUPIDROM 881 btst #7,%sp@(3) 882 jeq Lstartnot040 883 movl #CPU_68060,%a0@ | and in the cputype 884 orl #IC60_CABC,%d0 | XXX and clear all 060 branch cache 885 #else 886 movc %d0,%cacr 887 bset #30,%d0 | not allocate data cache bit 888 movc %d0,%cacr | does it stick? 889 movc %cacr,%d0 890 tstl %d0 891 jeq Lstartnot040 892 bset #7,%sp@(3) | note it is '60 family in machineid 893 movl #CPU_68060,%a0@ | and in the cputype 894 orl #IC60_CABC,%d0 | XXX and clear all 060 branch cache 895 .word 0x4e7a,0x1808 | movc pcr,d1 896 swap %d1 897 cmpw #0x430,%d1 898 jne Lstartnot040 | but no FPU 899 bset #6,%sp@(3) | yes, we have FPU, note that 900 swap %d1 901 bclr #1,%d1 | ... and switch it on. 902 .word 0x4e7b,0x1808 | movc d1,pcr 903 #endif 904 Lstartnot040: 905 movc %d0,%cacr | clear and disable on-chip cache(s) 906 movl #_C_LABEL(vectab),%a0 907 movc %a0,%vbr 908 909 /* let the C function initialize everything */ 910 RELOC(start_c, %a0) 911 jbsr %a0@ 912 lea %sp@(4*9),%sp 913 914 #ifdef DRACO 915 RELOC(machineid,%a0) 916 cmpb #0x7d,%a0@ 917 jne LAmiga_enable_MMU 918 919 lea %pc@(0),%a0 920 movl %a0,%d0 921 andl #0xff000000,%d0 922 orl #0x0000c044,%d0 | 16 MB, ro, cache inhibited 923 .word 0x4e7b,0x0004 | movc %d0,%itt0 924 .word 0xf518 | pflusha 925 movl #MMU40_TCR_BITS,%d0 | enable MMU 926 .word 0x4e7b,0x0003 | movc %d0,%tc 927 jmp Lcleanitt0:l 928 Lcleanitt0: 929 movq #0,%d0 930 .word 0x4e7b,0x0004 | movc %d0,%itt0 931 bra LMMUenable_end 932 933 LAmiga_enable_MMU: 934 #endif /* DRACO */ 935 936 /* Copy just the code to enable the MMU into chip memory */ 937 lea LMMUenable_start,%a0 938 movl #LMMUenable_start:l,%a1 939 lea LMMUenable_end,%a2 940 Lcopy_MMU_enabler: 941 movl %a0@+,%a1@+ 942 cmpl %a0,%a2 943 jgt Lcopy_MMU_enabler 944 945 jmp LMMUenable_start:l 946 947 LMMUenable_start: 948 949 /* enable the MMU */ 950 #if defined(M68040) || defined(M68060) 951 RELOC(mmutype, %a0) 952 cmpl #MMU_68040,%a0@ 953 jne Lenable030 954 .word 0xf518 | pflusha 955 movl #MMU40_TCR_BITS,%d0 | enable MMU 956 .word 0x4e7b,0x0003 | movc %d0,%tc 957 jmp LMMUenable_end:l 958 #endif /* M68040 || M68060 */ 959 Lenable030: 960 pflusha 961 lea Ltc,%a0 962 pmove %a0@,%tc 963 jmp LMMUenable_end:l 964 965 Ltc: .long MMU51_TCR_BITS | see pmap.h 966 967 LMMUenable_end: 968 969 lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack 970 jbsr _C_LABEL(start_c_finish) 971 972 /* set kernel stack, user SP */ 973 movl _C_LABEL(lwp0uarea),%a1 | grab lwp0 uarea 974 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 975 movl #USRSTACK-4,%a2 976 movl %a2,%usp | init user SP 977 movl %a2,%a1@(PCB_USP) | and save it 978 clrw %a1@(PCB_FLAGS) | clear flags 979 #ifdef FPCOPROC 980 clrl %a1@(PCB_FPCTX) | ensure null FP context 981 | pea %a1@(PCB_FPCTX) 982 | jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) 983 | addql #4,%sp 984 #endif 985 /* flush TLB and turn on caches */ 986 987 jbsr _C_LABEL(_TBIA) | invalidate TLB 988 movl #CACHE_ON,%d0 989 tstl %d5 990 jeq Lcacheon 991 | is this needed? MLH 992 .word 0xf4f8 | cpusha bc - push & invalidate caches 993 movl #CACHE40_ON,%d0 994 #ifdef M68060 995 cmpl #CPU_68060,_C_LABEL(cputype) 996 jne Lcacheon 997 movl #CACHE60_ON,%d0 998 #endif 999 Lcacheon: 1000 movc %d0,%cacr | clear cache(s) 1001 /* final setup for C code */ 1002 1003 movw #PSL_LOWIPL,%sr | lower SPL 1004 1005 movl %d7,_C_LABEL(boothowto) | save reboot flags 1006 /* 1007 * Create a fake exception frame that returns to user mode, 1008 * make space for the rest of a fake saved register set, and 1009 * pass the first available RAM and a pointer to the register 1010 * set to "main()". "main()" will do an "execve()" using that 1011 * stack frame. 1012 * When "main()" returns, we're running in process 1 and have 1013 * successfully executed the "execve()". We load up the registers from 1014 * that set; the "rte" loads the PC and PSR, which jumps to "init". 1015 */ 1016 clrw %sp@- | vector offset/frame type 1017 clrl %sp@- | PC - filled in by "execve" 1018 movw #PSL_USER,%sp@- | in user mode 1019 clrl %sp@- | stack adjust count 1020 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 1021 lea _C_LABEL(lwp0),%a0 | lwp0 in a0 1022 movl %sp,%a0@(L_MD_REGS) | save frame for lwp0 1023 movl %usp,%a1 1024 movl %a1,%sp@(FR_SP) | save user stack pointer in frame 1025 pea %sp@ | addr of space for D0 1026 1027 jbsr _C_LABEL(main) | main(firstaddr, r0) 1028 addql #4,%sp | pop args 1029 1030 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1031 jne Lnoflush | no, skip 1032 .word 0xf478 | cpusha dc 1033 .word 0xf498 | cinva ic, also clears the 060 btc 1034 Lnoflush: 1035 movl %sp@(FR_SP),%a0 | grab and load 1036 movl %a0,%usp | user SP 1037 moveml %sp@+,%d0-%d7/%a0-%a6 | load most registers (all but SSP) 1038 addql #8,%sp | pop SSP and stack adjust count 1039 rte 1040 1041 /* 1042 * Primitives 1043 */ 1044 1045 /* 1046 * non-local gotos 1047 */ 1048 ENTRY(qsetjmp) 1049 movl %sp@(4),%a0 | savearea pointer 1050 lea %a0@(40),%a0 | skip regs we do not save 1051 movl %a6,%a0@+ | save FP 1052 movl %sp,%a0@+ | save SP 1053 movl %sp@,%a0@ | and return address 1054 moveq #0,%d0 | return 0 1055 rts 1056 1057 /* 1058 * Use common m68k process/lwp switch and context save subroutines. 1059 */ 1060 #include <m68k/m68k/switch_subr.s> 1061 1062 ENTRY(ecacheon) 1063 rts 1064 1065 ENTRY(ecacheoff) 1066 rts 1067 1068 /* 1069 * Check out a virtual address to see if it's okay to write to. 1070 * 1071 * probeva(va, fc) 1072 * 1073 */ 1074 ENTRY(probeva) 1075 movl %sp@(8),%d0 1076 movec %d0,%dfc 1077 movl %sp@(4),%a0 1078 .word 0xf548 | ptestw (a0) 1079 moveq #FC_USERD,%d0 | restore DFC to user space 1080 movc %d0,%dfc 1081 .word 0x4e7a,0x0805 | movec MMUSR,d0 1082 rts 1083 1084 /* 1085 * Handle the nitty-gritty of rebooting the machine. 1086 * 1087 */ 1088 #if defined(P5PPC68KBOARD) 1089 .data 1090 GLOBAL(p5ppc) 1091 .long 0 1092 .text 1093 #endif 1094 1095 ENTRY_NOPROFILE(doboot) 1096 movl #CACHE_OFF,%d0 1097 cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040 1098 jne Ldoboot0 1099 .word 0xf4f8 | cpusha bc - push and invalidate caches 1100 nop 1101 movl #CACHE40_OFF,%d0 1102 Ldoboot0: 1103 movc %d0,%cacr | disable on-chip cache(s) 1104 1105 movw #0x2700,%sr | cut off any interrupts 1106 1107 #if defined(P5PPC68KBOARD) 1108 tstl _C_LABEL(p5ppc) 1109 jne Lp5ppcboot 1110 #endif 1111 #if defined(DRACO) 1112 cmpb #0x7d,_C_LABEL(machineid) 1113 jeq LdbOnDraCo 1114 #endif 1115 1116 | clear first 4k of CHIPMEM 1117 movl _C_LABEL(CHIPMEMADDR),%a0 1118 movl %a0,%a1 1119 movl #1024,%d0 1120 Ldb1: 1121 clrl %a0@+ 1122 dbra %d0,Ldb1 1123 1124 | now, copy the following code over 1125 | lea %a1@(Ldoreboot),%a0 | KVA starts at 0, CHIPMEM is phys 0 1126 | lea %a1@(Ldorebootend),%a1 1127 | lea %pc@(Ldoreboot-.+2),%a0 1128 | addl %a1,%a0 1129 | lea %a0@(128),%a1 1130 | lea %pc@(Ldoreboot-.+2),%a2 1131 lea Ldoreboot,%a2 1132 lea Ldorebootend,%a0 1133 addl %a1,%a0 1134 addl %a2,%a1 1135 exg %a0,%a1 1136 Ldb2: 1137 movel %a2@+,%a0@+ 1138 cmpl %a1,%a0 1139 jle Ldb2 1140 1141 | ok, turn off MMU.. 1142 Ldoreboot: 1143 cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040 1144 jeq Lmmuoff040 1145 lea _ASM_LABEL(zero),%a0 1146 pmove %a0@,%tc | Turn off MMU 1147 lea _ASM_LABEL(nullrp),%a0 1148 pmove %a0@,%crp | Turn off MMU some more 1149 pmove %a0@,%srp | Really, really, turn off MMU 1150 jra Ldoboot1 1151 Lmmuoff040: 1152 movl #0,%d0 1153 .word 0x4e7b,0x0003 | movc d0,TC 1154 .word 0x4e7b,0x0806 | movc d0,URP 1155 .word 0x4e7b,0x0807 | movc d0,SRP 1156 Ldoboot1: 1157 1158 | this weird code is the OFFICIAL way to reboot an Amiga ! .. 1159 lea 0x1000000,%a0 1160 subl %a0@(-0x14),%a0 1161 movl %a0@(4),%a0 1162 subl #2,%a0 1163 cmpw #0x4e70,%a0@ | 68040 kludge: if ROM entry is not 1164 jne Ldoreset | a reset, do the reset here 1165 jmp %a0@ | otherwise, jump to the ROM to reset 1166 | reset needs to be on longword boundary 1167 nop 1168 #ifdef __ELF__ 1169 .align 4 1170 #else 1171 .align 2 1172 #endif 1173 Ldoreset: 1174 | reset unconfigures all memory! 1175 reset 1176 | now rely on prefetch for next jmp 1177 jmp %a0@ 1178 | NOT REACHED 1179 1180 #if defined(P5PPC68KBOARD) 1181 Lp5ppcboot: 1182 | The Linux-Apus boot code does it in a similar way 1183 | For 040 on uncached pages, eieio can be replaced by nothing. 1184 movl _C_LABEL(ZTWOROMADDR),%a0 1185 lea %a0@(0xf60000-0xd80000),%a0 1186 movb #0x60,%a0@(0x20) 1187 movb #0x50,%a0@(0x20) 1188 movb #0x30,%a0@(0x20) 1189 movb #0x40,%a0@(0x18) 1190 movb #0x04,%a0@ 1191 Lwaithere: 1192 jra Lwaithere 1193 #endif 1194 1195 #ifdef DRACO 1196 LdbOnDraCo: 1197 | we use a TTR. We want to boot even if half of us is already dead. 1198 1199 movl _C_LABEL(boot_fphystart), %d0 1200 lea LdoDraCoBoot, %a0 1201 lea %a0@(%d0),%a0 1202 andl #0xFF000000,%d0 1203 orl #0x0000C044,%d0 | enable, supervisor, CI, RO 1204 .word 0x4e7b,0x0004 | movc d0,ITT0 1205 jmp %a0@ 1206 1207 #ifdef __ELF__ 1208 .align 4 1209 #else 1210 .align 2 1211 #endif 1212 LdoDraCoBoot: 1213 | turn off MMU now ... were more ore less guaranteed to run on 040/060: 1214 movl #0,%d0 1215 .word 0x4e7b,0x0003 | movc d0,TC 1216 .word 0x4e7b,0x0806 | movc d0,URP 1217 .word 0x4e7b,0x0807 | movc d0,SRP 1218 .word 0x4e7b,0x0004 | movc d0,ITT0 1219 nop 1220 | map in boot ROM @0: 1221 reset 1222 | and simulate what a reset exception would have done. 1223 movl 4,%a0 1224 movl 0,%a7 1225 jmp %a0@ 1226 | NOT REACHED 1227 #endif 1228 /* 1229 * Reboot directly into a new kernel image. 1230 * kernel_reload(image, image_size, entry, 1231 * fastram_start, fastram_size, chipram_start, esym, eclockfreq) 1232 */ 1233 ENTRY_NOPROFILE(kernel_reload) 1234 lea Lreload_copy,%a0 | cursory validity check of new kernel 1235 movl %a0@,%d0 | to see if the kernel reload code 1236 addl %sp@(4),%a0 | in new image matches running kernel 1237 cmpl %a0@,%d0 1238 jeq Lreload_ok 1239 rts | It doesn't match - can't reload 1240 Lreload_ok: 1241 jsr _C_LABEL(bootsync) 1242 CUSTOMADDR(%a5) 1243 1244 movew #(1<<9),%a5@(0x096) | disable DMA (before clobbering chipmem) 1245 1246 movl #CACHE_OFF,%d0 1247 cmpl #MMU_68040,_C_LABEL(mmutype) 1248 jne Lreload1 1249 .word 0xf4f8 | cpusha bc - push and invalidate caches 1250 nop 1251 movl #CACHE40_OFF,%d0 1252 Lreload1: 1253 movc %d0,%cacr | disable on-chip cache(s) 1254 1255 movw #0x2700,%sr | cut off any interrupts 1256 movel _C_LABEL(boothowto),%d7 | save boothowto 1257 movel _C_LABEL(machineid),%d5 | (and machineid) 1258 1259 movel %sp@(16),%a0 | load memory parameters 1260 movel %sp@(20),%d0 1261 movel %sp@(24),%d1 1262 movel %sp@(28),%a4 | esym 1263 movel %sp@(32),%d4 | eclockfreq 1264 movel %sp@(36),%d3 | AGA mode 1265 movel %sp@(40),%a2 | sync inhibit flags 1266 movel %sp@(44),%d6 | boot partition offset 1267 1268 movel %sp@(12),%a6 | find entrypoint (a6) 1269 1270 movel %sp@(4),%a1 | copy kernel to low chip memory 1271 movel %sp@(8),%d2 1272 movl _C_LABEL(CHIPMEMADDR),%a3 1273 Lreload_copy: 1274 movel %a1@+,%a3@+ 1275 subl #4,%d2 1276 jcc Lreload_copy 1277 1278 | ok, turn off MMU.. 1279 cmpl #MMU_68040,_C_LABEL(mmutype) 1280 jeq Lreload040 1281 lea _ASM_LABEL(zero),%a3 1282 pmove %a3@,%tc | Turn off MMU 1283 lea _ASM_LABEL(nullrp),%a3 1284 pmove %a3@,%crp | Turn off MMU some more 1285 pmove %a3@,%srp | Really, really, turn off MMU 1286 jra Lreload2 1287 Lreload040: 1288 movl #0,%d2 1289 .word 0x4e7b,0x2003 | movc d2,TC 1290 .word 0x4e7b,0x2806 | movc d2,URP 1291 .word 0x4e7b,0x2807 | movc d2,SRP 1292 Lreload2: 1293 1294 moveq #0,%d2 | clear unused registers 1295 subl %a1,%a1 1296 subl %a3,%a3 1297 subl %a5,%a5 1298 jmp %a6@ | start new kernel 1299 1300 1301 | A do-nothing MMU root pointer (includes the following long as well) 1302 1303 ASLOCAL(nullrp) 1304 .long 0x7fff0001 1305 ASLOCAL(zero) 1306 .long 0 1307 Ldorebootend: 1308 1309 #ifdef __ELF__ 1310 .align 4 1311 #else 1312 .align 2 1313 #endif 1314 nop 1315 ENTRY_NOPROFILE(delay) 1316 ENTRY_NOPROFILE(DELAY) 1317 movql #10,%d1 | 2 +2 1318 movl %sp@(4),%d0 | 4 +4 1319 lsll %d1,%d0 | 8 +2 1320 movl _C_LABEL(delaydivisor),%d1 | A +6 1321 Ldelay: | longword aligned again. 1322 subl %d1,%d0 1323 jcc Ldelay 1324 rts 1325 1326 #ifdef M68060 1327 ENTRY_NOPROFILE(intemu60) 1328 addql #1,L60iem 1329 jra _C_LABEL(I_CALL_TOP)+128+0x00 1330 ENTRY_NOPROFILE(fpiemu60) 1331 addql #1,L60fpiem 1332 jra _C_LABEL(FP_CALL_TOP)+128+0x30 1333 ENTRY_NOPROFILE(fpdemu60) 1334 addql #1,L60fpdem 1335 jra _C_LABEL(FP_CALL_TOP)+128+0x38 1336 ENTRY_NOPROFILE(fpeaemu60) 1337 addql #1,L60fpeaem 1338 jra _C_LABEL(FP_CALL_TOP)+128+0x40 1339 #endif 1340 1341 .data 1342 .space PAGE_SIZE 1343 .align 4 1344 ASLOCAL(tmpstk) 1345 1346 GLOBAL(mmutype) 1347 .long MMU_68851 1348 GLOBAL(cputype) 1349 .long CPU_68020 1350 GLOBAL(ectype) 1351 .long EC_NONE 1352 GLOBAL(fputype) 1353 .long FPU_NONE 1354 GLOBAL(delaydivisor) 1355 .long 12 | should be enough for 80 MHz 68060 1356 | will be adapted to other CPUs in 1357 | start_c_cleanup and calibrated 1358 | at clock attach time. 1359 #ifdef DEBUG 1360 ASGLOBAL(fulltflush) 1361 .long 0 1362 ASGLOBAL(fullcflush) 1363 .long 0 1364 ASGLOBAL(timebomb) 1365 .long 0 1366 #endif 1367 /* interrupt counters */ 1368 GLOBAL(intrnames) 1369 .asciz "spur" | spurious interrupt 1370 .asciz "tbe/soft" | serial TBE & software 1371 .asciz "kbd/ports" | keyboard & PORTS 1372 .asciz "vbl" | vertical blank 1373 .asciz "audio" | audio channels 1374 .asciz "rbf" | serial receive 1375 .asciz "exter" | EXTERN 1376 .asciz "nmi" | non-maskable 1377 .asciz "clock" | clock interrupts 1378 .asciz "spur6" | spurious level 6 1379 #ifdef DRACO 1380 .asciz "kbd/soft" | 1: native keyboard, soft ints 1381 .asciz "cia/zbus" | 2: cia, PORTS 1382 .asciz "lclbus" | 3: local bus, e.g. Altais vbl 1383 .asciz "drscsi" | 4: mainboard scsi 1384 .asciz "superio" | 5: superio chip 1385 .asciz "lcl/zbus" | 6: lcl/zorro lev6 1386 .asciz "buserr" | 7: nmi: bus timeout 1387 #endif 1388 #ifdef M68060 1389 .asciz "60intemu" 1390 .asciz "60fpiemu" 1391 .asciz "60fpdemu" 1392 .asciz "60fpeaemu" 1393 .asciz "60bpe" 1394 #endif 1395 #ifdef FPU_EMULATE 1396 .asciz "fpe" 1397 #endif 1398 GLOBAL(eintrnames) 1399 #ifdef __ELF__ 1400 .align 4 1401 #else 1402 .align 2 1403 #endif 1404 GLOBAL(intrcnt) 1405 .long 0,0,0,0,0,0,0,0,0,0 1406 #ifdef DRACO 1407 ASLOCAL(Drintrcnt) 1408 .long 0,0,0,0,0,0,0 1409 #endif 1410 #ifdef M68060 1411 L60iem: .long 0 1412 L60fpiem: .long 0 1413 L60fpdem: .long 0 1414 L60fpeaem: .long 0 1415 L60bpe: .long 0 1416 #endif 1417 #ifdef FPU_EMULATE 1418 Lfpecnt: .long 0 1419 #endif 1420 GLOBAL(eintrcnt) 1421