1 /* $NetBSD: locore.s,v 1.172 2024/01/19 18:18:53 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 /* initialize source/destination control registers for movs */ 910 moveq #FC_USERD,%d0 | user space 911 movc %d0,%sfc | as source 912 movc %d0,%dfc | and destination of transfers 913 914 /* let the C function initialize everything */ 915 RELOC(start_c, %a0) 916 jbsr %a0@ 917 lea %sp@(4*9),%sp 918 919 #ifdef DRACO 920 RELOC(machineid,%a0) 921 cmpb #0x7d,%a0@ 922 jne LAmiga_enable_MMU 923 924 lea %pc@(0),%a0 925 movl %a0,%d0 926 andl #0xff000000,%d0 927 orl #0x0000c044,%d0 | 16 MB, ro, cache inhibited 928 .word 0x4e7b,0x0004 | movc %d0,%itt0 929 .word 0xf518 | pflusha 930 movl #MMU40_TCR_BITS,%d0 | enable MMU 931 .word 0x4e7b,0x0003 | movc %d0,%tc 932 jmp Lcleanitt0:l 933 Lcleanitt0: 934 movq #0,%d0 935 .word 0x4e7b,0x0004 | movc %d0,%itt0 936 bra LMMUenable_end 937 938 LAmiga_enable_MMU: 939 #endif /* DRACO */ 940 941 /* Copy just the code to enable the MMU into chip memory */ 942 lea LMMUenable_start,%a0 943 movl #LMMUenable_start:l,%a1 944 lea LMMUenable_end,%a2 945 Lcopy_MMU_enabler: 946 movl %a0@+,%a1@+ 947 cmpl %a0,%a2 948 jgt Lcopy_MMU_enabler 949 950 jmp LMMUenable_start:l 951 952 LMMUenable_start: 953 954 /* enable the MMU */ 955 #if defined(M68040) || defined(M68060) 956 RELOC(mmutype, %a0) 957 cmpl #MMU_68040,%a0@ 958 jne Lenable030 959 .word 0xf518 | pflusha 960 movl #MMU40_TCR_BITS,%d0 | enable MMU 961 .word 0x4e7b,0x0003 | movc %d0,%tc 962 jmp LMMUenable_end:l 963 #endif /* M68040 || M68060 */ 964 Lenable030: 965 pflusha 966 lea Ltc,%a0 967 pmove %a0@,%tc 968 jmp LMMUenable_end:l 969 970 Ltc: .long MMU51_TCR_BITS | see pmap.h 971 972 LMMUenable_end: 973 974 lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack 975 jbsr _C_LABEL(start_c_finish) 976 977 /* set kernel stack, user SP */ 978 movl _C_LABEL(lwp0uarea),%a1 | grab lwp0 uarea 979 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 980 movl #USRSTACK-4,%a2 981 movl %a2,%usp | init user SP 982 movl %a2,%a1@(PCB_USP) | and save it 983 clrw %a1@(PCB_FLAGS) | clear flags 984 #ifdef FPCOPROC 985 clrl %a1@(PCB_FPCTX) | ensure null FP context 986 |WRONG! movl %a1,%sp@- 987 | pea %a1@(PCB_FPCTX) 988 | jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) 989 | addql #4,%sp 990 #endif 991 /* flush TLB and turn on caches */ 992 993 jbsr _C_LABEL(_TBIA) | invalidate TLB 994 movl #CACHE_ON,%d0 995 tstl %d5 996 jeq Lcacheon 997 | is this needed? MLH 998 .word 0xf4f8 | cpusha bc - push & invalidate caches 999 movl #CACHE40_ON,%d0 1000 #ifdef M68060 1001 cmpl #CPU_68060,_C_LABEL(cputype) 1002 jne Lcacheon 1003 movl #CACHE60_ON,%d0 1004 #endif 1005 Lcacheon: 1006 movc %d0,%cacr | clear cache(s) 1007 /* final setup for C code */ 1008 1009 movw #PSL_LOWIPL,%sr | lower SPL 1010 1011 movl %d7,_C_LABEL(boothowto) | save reboot flags 1012 /* 1013 * Create a fake exception frame that returns to user mode, 1014 * make space for the rest of a fake saved register set, and 1015 * pass the first available RAM and a pointer to the register 1016 * set to "main()". "main()" will do an "execve()" using that 1017 * stack frame. 1018 * When "main()" returns, we're running in process 1 and have 1019 * successfully executed the "execve()". We load up the registers from 1020 * that set; the "rte" loads the PC and PSR, which jumps to "init". 1021 */ 1022 clrw %sp@- | vector offset/frame type 1023 clrl %sp@- | PC - filled in by "execve" 1024 movw #PSL_USER,%sp@- | in user mode 1025 clrl %sp@- | stack adjust count 1026 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 1027 lea _C_LABEL(lwp0),%a0 | lwp0 in a0 1028 movl %sp,%a0@(L_MD_REGS) | save frame for lwp0 1029 movl %usp,%a1 1030 movl %a1,%sp@(FR_SP) | save user stack pointer in frame 1031 pea %sp@ | addr of space for D0 1032 1033 jbsr _C_LABEL(main) | main(firstaddr, r0) 1034 addql #4,%sp | pop args 1035 1036 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1037 jne Lnoflush | no, skip 1038 .word 0xf478 | cpusha dc 1039 .word 0xf498 | cinva ic, also clears the 060 btc 1040 Lnoflush: 1041 movl %sp@(FR_SP),%a0 | grab and load 1042 movl %a0,%usp | user SP 1043 moveml %sp@+,%d0-%d7/%a0-%a6 | load most registers (all but SSP) 1044 addql #8,%sp | pop SSP and stack adjust count 1045 rte 1046 1047 /* 1048 * Primitives 1049 */ 1050 1051 /* 1052 * non-local gotos 1053 */ 1054 ENTRY(qsetjmp) 1055 movl %sp@(4),%a0 | savearea pointer 1056 lea %a0@(40),%a0 | skip regs we do not save 1057 movl %a6,%a0@+ | save FP 1058 movl %sp,%a0@+ | save SP 1059 movl %sp@,%a0@ | and return address 1060 moveq #0,%d0 | return 0 1061 rts 1062 1063 /* 1064 * Use common m68k process/lwp switch and context save subroutines. 1065 */ 1066 #include <m68k/m68k/switch_subr.s> 1067 1068 ENTRY(ecacheon) 1069 rts 1070 1071 ENTRY(ecacheoff) 1072 rts 1073 1074 /* 1075 * Check out a virtual address to see if it's okay to write to. 1076 * 1077 * probeva(va, fc) 1078 * 1079 */ 1080 ENTRY(probeva) 1081 movl %sp@(8),%d0 1082 movec %d0,%dfc 1083 movl %sp@(4),%a0 1084 .word 0xf548 | ptestw (a0) 1085 moveq #FC_USERD,%d0 | restore DFC to user space 1086 movc %d0,%dfc 1087 .word 0x4e7a,0x0805 | movec MMUSR,d0 1088 rts 1089 1090 /* 1091 * Handle the nitty-gritty of rebooting the machine. 1092 * 1093 */ 1094 #if defined(P5PPC68KBOARD) 1095 .data 1096 GLOBAL(p5ppc) 1097 .long 0 1098 .text 1099 #endif 1100 1101 ENTRY_NOPROFILE(doboot) 1102 movl #CACHE_OFF,%d0 1103 cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040 1104 jne Ldoboot0 1105 .word 0xf4f8 | cpusha bc - push and invalidate caches 1106 nop 1107 movl #CACHE40_OFF,%d0 1108 Ldoboot0: 1109 movc %d0,%cacr | disable on-chip cache(s) 1110 1111 movw #0x2700,%sr | cut off any interrupts 1112 1113 #if defined(P5PPC68KBOARD) 1114 tstl _C_LABEL(p5ppc) 1115 jne Lp5ppcboot 1116 #endif 1117 #if defined(DRACO) 1118 cmpb #0x7d,_C_LABEL(machineid) 1119 jeq LdbOnDraCo 1120 #endif 1121 1122 | clear first 4k of CHIPMEM 1123 movl _C_LABEL(CHIPMEMADDR),%a0 1124 movl %a0,%a1 1125 movl #1024,%d0 1126 Ldb1: 1127 clrl %a0@+ 1128 dbra %d0,Ldb1 1129 1130 | now, copy the following code over 1131 | lea %a1@(Ldoreboot),%a0 | KVA starts at 0, CHIPMEM is phys 0 1132 | lea %a1@(Ldorebootend),%a1 1133 | lea %pc@(Ldoreboot-.+2),%a0 1134 | addl %a1,%a0 1135 | lea %a0@(128),%a1 1136 | lea %pc@(Ldoreboot-.+2),%a2 1137 lea Ldoreboot,%a2 1138 lea Ldorebootend,%a0 1139 addl %a1,%a0 1140 addl %a2,%a1 1141 exg %a0,%a1 1142 Ldb2: 1143 movel %a2@+,%a0@+ 1144 cmpl %a1,%a0 1145 jle Ldb2 1146 1147 | ok, turn off MMU.. 1148 Ldoreboot: 1149 cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040 1150 jeq Lmmuoff040 1151 lea _ASM_LABEL(zero),%a0 1152 pmove %a0@,%tc | Turn off MMU 1153 lea _ASM_LABEL(nullrp),%a0 1154 pmove %a0@,%crp | Turn off MMU some more 1155 pmove %a0@,%srp | Really, really, turn off MMU 1156 jra Ldoboot1 1157 Lmmuoff040: 1158 movl #0,%d0 1159 .word 0x4e7b,0x0003 | movc d0,TC 1160 .word 0x4e7b,0x0806 | movc d0,URP 1161 .word 0x4e7b,0x0807 | movc d0,SRP 1162 Ldoboot1: 1163 1164 | this weird code is the OFFICIAL way to reboot an Amiga ! .. 1165 lea 0x1000000,%a0 1166 subl %a0@(-0x14),%a0 1167 movl %a0@(4),%a0 1168 subl #2,%a0 1169 cmpw #0x4e70,%a0@ | 68040 kludge: if ROM entry is not 1170 jne Ldoreset | a reset, do the reset here 1171 jmp %a0@ | otherwise, jump to the ROM to reset 1172 | reset needs to be on longword boundary 1173 nop 1174 #ifdef __ELF__ 1175 .align 4 1176 #else 1177 .align 2 1178 #endif 1179 Ldoreset: 1180 | reset unconfigures all memory! 1181 reset 1182 | now rely on prefetch for next jmp 1183 jmp %a0@ 1184 | NOT REACHED 1185 1186 #if defined(P5PPC68KBOARD) 1187 Lp5ppcboot: 1188 | The Linux-Apus boot code does it in a similar way 1189 | For 040 on uncached pages, eieio can be replaced by nothing. 1190 movl _C_LABEL(ZTWOROMADDR),%a0 1191 lea %a0@(0xf60000-0xd80000),%a0 1192 movb #0x60,%a0@(0x20) 1193 movb #0x50,%a0@(0x20) 1194 movb #0x30,%a0@(0x20) 1195 movb #0x40,%a0@(0x18) 1196 movb #0x04,%a0@ 1197 Lwaithere: 1198 jra Lwaithere 1199 #endif 1200 1201 #ifdef DRACO 1202 LdbOnDraCo: 1203 | we use a TTR. We want to boot even if half of us is already dead. 1204 1205 movl _C_LABEL(boot_fphystart), %d0 1206 lea LdoDraCoBoot, %a0 1207 lea %a0@(%d0),%a0 1208 andl #0xFF000000,%d0 1209 orl #0x0000C044,%d0 | enable, supervisor, CI, RO 1210 .word 0x4e7b,0x0004 | movc d0,ITT0 1211 jmp %a0@ 1212 1213 #ifdef __ELF__ 1214 .align 4 1215 #else 1216 .align 2 1217 #endif 1218 LdoDraCoBoot: 1219 | turn off MMU now ... were more ore less guaranteed to run on 040/060: 1220 movl #0,%d0 1221 .word 0x4e7b,0x0003 | movc d0,TC 1222 .word 0x4e7b,0x0806 | movc d0,URP 1223 .word 0x4e7b,0x0807 | movc d0,SRP 1224 .word 0x4e7b,0x0004 | movc d0,ITT0 1225 nop 1226 | map in boot ROM @0: 1227 reset 1228 | and simulate what a reset exception would have done. 1229 movl 4,%a0 1230 movl 0,%a7 1231 jmp %a0@ 1232 | NOT REACHED 1233 #endif 1234 /* 1235 * Reboot directly into a new kernel image. 1236 * kernel_reload(image, image_size, entry, 1237 * fastram_start, fastram_size, chipram_start, esym, eclockfreq) 1238 */ 1239 ENTRY_NOPROFILE(kernel_reload) 1240 lea Lreload_copy,%a0 | cursory validity check of new kernel 1241 movl %a0@,%d0 | to see if the kernel reload code 1242 addl %sp@(4),%a0 | in new image matches running kernel 1243 cmpl %a0@,%d0 1244 jeq Lreload_ok 1245 rts | It doesn't match - can't reload 1246 Lreload_ok: 1247 jsr _C_LABEL(bootsync) 1248 CUSTOMADDR(%a5) 1249 1250 movew #(1<<9),%a5@(0x096) | disable DMA (before clobbering chipmem) 1251 1252 movl #CACHE_OFF,%d0 1253 cmpl #MMU_68040,_C_LABEL(mmutype) 1254 jne Lreload1 1255 .word 0xf4f8 | cpusha bc - push and invalidate caches 1256 nop 1257 movl #CACHE40_OFF,%d0 1258 Lreload1: 1259 movc %d0,%cacr | disable on-chip cache(s) 1260 1261 movw #0x2700,%sr | cut off any interrupts 1262 movel _C_LABEL(boothowto),%d7 | save boothowto 1263 movel _C_LABEL(machineid),%d5 | (and machineid) 1264 1265 movel %sp@(16),%a0 | load memory parameters 1266 movel %sp@(20),%d0 1267 movel %sp@(24),%d1 1268 movel %sp@(28),%a4 | esym 1269 movel %sp@(32),%d4 | eclockfreq 1270 movel %sp@(36),%d3 | AGA mode 1271 movel %sp@(40),%a2 | sync inhibit flags 1272 movel %sp@(44),%d6 | boot partition offset 1273 1274 movel %sp@(12),%a6 | find entrypoint (a6) 1275 1276 movel %sp@(4),%a1 | copy kernel to low chip memory 1277 movel %sp@(8),%d2 1278 movl _C_LABEL(CHIPMEMADDR),%a3 1279 Lreload_copy: 1280 movel %a1@+,%a3@+ 1281 subl #4,%d2 1282 jcc Lreload_copy 1283 1284 | ok, turn off MMU.. 1285 cmpl #MMU_68040,_C_LABEL(mmutype) 1286 jeq Lreload040 1287 lea _ASM_LABEL(zero),%a3 1288 pmove %a3@,%tc | Turn off MMU 1289 lea _ASM_LABEL(nullrp),%a3 1290 pmove %a3@,%crp | Turn off MMU some more 1291 pmove %a3@,%srp | Really, really, turn off MMU 1292 jra Lreload2 1293 Lreload040: 1294 movl #0,%d2 1295 .word 0x4e7b,0x2003 | movc d2,TC 1296 .word 0x4e7b,0x2806 | movc d2,URP 1297 .word 0x4e7b,0x2807 | movc d2,SRP 1298 Lreload2: 1299 1300 moveq #0,%d2 | clear unused registers 1301 subl %a1,%a1 1302 subl %a3,%a3 1303 subl %a5,%a5 1304 jmp %a6@ | start new kernel 1305 1306 1307 | A do-nothing MMU root pointer (includes the following long as well) 1308 1309 ASLOCAL(nullrp) 1310 .long 0x7fff0001 1311 ASLOCAL(zero) 1312 .long 0 1313 Ldorebootend: 1314 1315 #ifdef __ELF__ 1316 .align 4 1317 #else 1318 .align 2 1319 #endif 1320 nop 1321 ENTRY_NOPROFILE(delay) 1322 ENTRY_NOPROFILE(DELAY) 1323 movql #10,%d1 | 2 +2 1324 movl %sp@(4),%d0 | 4 +4 1325 lsll %d1,%d0 | 8 +2 1326 movl _C_LABEL(delaydivisor),%d1 | A +6 1327 Ldelay: | longword aligned again. 1328 subl %d1,%d0 1329 jcc Ldelay 1330 rts 1331 1332 #ifdef M68060 1333 ENTRY_NOPROFILE(intemu60) 1334 addql #1,L60iem 1335 jra _C_LABEL(I_CALL_TOP)+128+0x00 1336 ENTRY_NOPROFILE(fpiemu60) 1337 addql #1,L60fpiem 1338 jra _C_LABEL(FP_CALL_TOP)+128+0x30 1339 ENTRY_NOPROFILE(fpdemu60) 1340 addql #1,L60fpdem 1341 jra _C_LABEL(FP_CALL_TOP)+128+0x38 1342 ENTRY_NOPROFILE(fpeaemu60) 1343 addql #1,L60fpeaem 1344 jra _C_LABEL(FP_CALL_TOP)+128+0x40 1345 #endif 1346 1347 .data 1348 .space PAGE_SIZE 1349 .align 4 1350 ASLOCAL(tmpstk) 1351 1352 GLOBAL(mmutype) 1353 .long MMU_68851 1354 GLOBAL(cputype) 1355 .long CPU_68020 1356 GLOBAL(ectype) 1357 .long EC_NONE 1358 GLOBAL(fputype) 1359 .long FPU_NONE 1360 GLOBAL(delaydivisor) 1361 .long 12 | should be enough for 80 MHz 68060 1362 | will be adapted to other CPUs in 1363 | start_c_cleanup and calibrated 1364 | at clock attach time. 1365 #ifdef DEBUG 1366 ASGLOBAL(fulltflush) 1367 .long 0 1368 ASGLOBAL(fullcflush) 1369 .long 0 1370 ASGLOBAL(timebomb) 1371 .long 0 1372 #endif 1373 /* interrupt counters */ 1374 GLOBAL(intrnames) 1375 .asciz "spur" | spurious interrupt 1376 .asciz "tbe/soft" | serial TBE & software 1377 .asciz "kbd/ports" | keyboard & PORTS 1378 .asciz "vbl" | vertical blank 1379 .asciz "audio" | audio channels 1380 .asciz "rbf" | serial receive 1381 .asciz "exter" | EXTERN 1382 .asciz "nmi" | non-maskable 1383 .asciz "clock" | clock interrupts 1384 .asciz "spur6" | spurious level 6 1385 #ifdef DRACO 1386 .asciz "kbd/soft" | 1: native keyboard, soft ints 1387 .asciz "cia/zbus" | 2: cia, PORTS 1388 .asciz "lclbus" | 3: local bus, e.g. Altais vbl 1389 .asciz "drscsi" | 4: mainboard scsi 1390 .asciz "superio" | 5: superio chip 1391 .asciz "lcl/zbus" | 6: lcl/zorro lev6 1392 .asciz "buserr" | 7: nmi: bus timeout 1393 #endif 1394 #ifdef M68060 1395 .asciz "60intemu" 1396 .asciz "60fpiemu" 1397 .asciz "60fpdemu" 1398 .asciz "60fpeaemu" 1399 .asciz "60bpe" 1400 #endif 1401 #ifdef FPU_EMULATE 1402 .asciz "fpe" 1403 #endif 1404 GLOBAL(eintrnames) 1405 #ifdef __ELF__ 1406 .align 4 1407 #else 1408 .align 2 1409 #endif 1410 GLOBAL(intrcnt) 1411 .long 0,0,0,0,0,0,0,0,0,0 1412 #ifdef DRACO 1413 ASLOCAL(Drintrcnt) 1414 .long 0,0,0,0,0,0,0 1415 #endif 1416 #ifdef M68060 1417 L60iem: .long 0 1418 L60fpiem: .long 0 1419 L60fpdem: .long 0 1420 L60fpeaem: .long 0 1421 L60bpe: .long 0 1422 #endif 1423 #ifdef FPU_EMULATE 1424 Lfpecnt: .long 0 1425 #endif 1426 GLOBAL(eintrcnt) 1427