1/* $NetBSD: locore.s,v 1.134 2024/09/07 06:17:37 andvar Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1980, 1990, 1993 6 * The Regents of the University of California. 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.66 92/12/22$ 37 * 38 * @(#)locore.s 8.6 (Berkeley) 5/27/94 39 */ 40 41#include "opt_compat_netbsd.h" 42#include "opt_compat_sunos.h" 43#include "opt_ddb.h" 44#include "opt_fpsp.h" 45#include "opt_kgdb.h" 46#include "opt_lockdebug.h" 47#include "opt_fpu_emulate.h" 48#include "opt_m68k_arch.h" 49 50#include "ite.h" 51#include "fd.h" 52#include "par.h" 53#include "assym.h" 54#include "ksyms.h" 55 56#include <machine/asm.h> 57 58/* 59 * This is for kvm_mkdb, and should be the address of the beginning 60 * of the kernel text segment (not necessarily the same as kernbase). 61 */ 62 .text 63GLOBAL(kernel_text) 64 65/* 66 * Temporary stack for a variety of purposes. 67 * Try and make this the first thing is the data segment so it 68 * is page aligned. Note that if we overflow here, we run into 69 * our text segment. 70 */ 71 .data 72 .space PAGE_SIZE 73ASLOCAL(tmpstk) 74 75#include <x68k/x68k/vectors.s> 76 77 .text 78/* 79 * This is where we wind up if the kernel jumps to location 0. 80 * (i.e. a bogus PC) This is known to immediately follow the vector 81 * table and is hence at 0x400 (see reset vector in vectors.s). 82 */ 83 PANIC("kernel jump to zero") 84 /* NOTREACHED */ 85 86/* 87 * Macro to relocate a symbol, used before MMU is enabled. 88 */ 89#define _RELOC(var, ar) \ 90 lea var,ar; \ 91 addl %a5,ar 92 93#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 94#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 95 96/* 97 * Initialization 98 * 99 * A4 contains the address of the end of the symtab 100 * A5 contains physical load point from boot 101 * VBR contains zero from ROM. Exceptions will continue to vector 102 * through ROM until MMU is turned on at which time they will vector 103 * through our table (vectors.s). 104 */ 105 106BSS(lowram,4) 107BSS(esym,4) 108 109GLOBAL(_verspad) 110 .word 0 111GLOBAL(boot_version) 112 .word X68K_BOOTIF_VERS 113 114ASENTRY_NOPROFILE(start) 115 movw #PSL_HIGHIPL,%sr | no interrupts 116 117 addql #4,%sp 118 movel %sp@+,%a5 | firstpa 119 movel %sp@+,%d5 | fphysize -- last page 120 movel %sp@,%a4 | esym 121 122 RELOC(vectab,%a0) | set Vector Base Register temporarily 123 movc %a0,%vbr 124 125#if 0 /* XXX this should be done by the boot loader */ 126 RELOC(edata, %a0) | clear out BSS 127 movl #_C_LABEL(end)-4,%d0 | (must be <= 256 kB) 128 subl #_C_LABEL(edata),%d0 129 lsrl #2,%d0 1301: clrl %a0@+ 131 dbra %d0,1b 132#endif 133 134 ASRELOC(tmpstk, %a0) 135 movl %a0,%sp | give ourselves a temporary stack 136 RELOC(esym, %a0) 137#if 1 138 movl %a4,%a0@ | store end of symbol table 139#else 140 clrl %a0@ | no symbol table, yet 141#endif 142 RELOC(lowram, %a0) 143 movl %a5,%a0@ | store start of physical memory 144 145 movl #CACHE_OFF,%d0 146 movc %d0,%cacr | clear and disable on-chip cache(s) 147 148/* determine our CPU/MMU combo - check for all regardless of kernel config */ 149 movl #DC_FREEZE,%d0 | data freeze bit 150 movc %d0,%cacr | only exists on 68030 151 movc %cacr,%d0 | read it back 152 tstl %d0 | zero? 153 jeq Lnot68030 | yes, we have 68020/68040/68060 154 jra Lstart1 | no, we have 68030 155Lnot68030: 156 bset #31,%d0 | data cache enable bit 157 movc %d0,%cacr | only exists on 68040/68060 158 movc %cacr,%d0 | read it back 159 tstl %d0 | zero? 160 jeq Lis68020 | yes, we have 68020 161 moveq #0,%d0 | now turn it back off 162 movec %d0,%cacr | before we access any data 163 .word 0xf4d8 | cinva bc - invalidate caches XXX 164 bset #30,%d0 | data cache no allocate mode bit 165 movc %d0,%cacr | only exists on 68060 166 movc %cacr,%d0 | read it back 167 tstl %d0 | zero? 168 jeq Lis68040 | yes, we have 68040 169 RELOC(mmutype, %a0) | no, we have 68060 170 movl #MMU_68040,%a0@ | with a 68040 compatible MMU 171 RELOC(cputype, %a0) 172 movl #CPU_68060,%a0@ | and a 68060 CPU 173 jra Lstart1 174Lis68040: 175 RELOC(mmutype, %a0) 176 movl #MMU_68040,%a0@ | with a 68040 MMU 177 RELOC(cputype, %a0) 178 movl #CPU_68040,%a0@ | and a 68040 CPU 179 jra Lstart1 180Lis68020: 181 RELOC(mmutype, %a0) 182 movl #MMU_68851,%a0@ | we have PMMU 183 RELOC(cputype, %a0) 184 movl #CPU_68020,%a0@ | and a 68020 CPU 185 186Lstart1: 187 /* 188 * Now that we know what CPU we have, initialize the address error 189 * and bus error handlers in the vector table: 190 * 191 * vectab+8 bus error 192 * vectab+12 address error 193 */ 194 RELOC(cputype,%a0) 195 RELOC(vectab,%a2) 196#if defined(M68060) 197 cmpl #CPU_68060,%a0@ | 68060? 198 jne 1f 199 movl #_C_LABEL(buserr60),%a2@(8) 200 movl #_C_LABEL(addrerr4060),%a2@(12) 201 jra Lstart2 2021: 203#endif 204#if defined(M68040) 205 cmpl #CPU_68040,%a0@ | 68040? 206 jne 1f 207 movl #_C_LABEL(buserr40),%a2@(8) 208 movl #_C_LABEL(addrerr4060),%a2@(12) 209 jra Lstart2 2101: 211#endif 212#if defined(M68030) 213 movl #_C_LABEL(busaddrerr2030),%a2@(8) 214 movl #_C_LABEL(busaddrerr2030),%a2@(12) 215#endif 216 217Lstart2: 218/* initialize source/destination control registers for movs */ 219 moveq #FC_USERD,%d0 | user space 220 movc %d0,%sfc | as source 221 movc %d0,%dfc | and destination of transfers 222/* initialize memory sizes (for pmap_bootstrap) */ 223 movl %d5,%d1 | last page 224 moveq #PGSHIFT,%d2 225 lsrl %d2,%d1 | convert to page (click) number 226 RELOC(maxmem, %a0) 227 movl %d1,%a0@ | save as maxmem 228 movl %a5,%d0 | lowram value from ROM via boot 229 lsrl %d2,%d0 | convert to page number 230 subl %d0,%d1 | compute amount of RAM present 231 RELOC(physmem, %a0) 232 movl %d1,%a0@ | and physmem 233 234/* configure kernel and lwp0 VA space so we can get going */ 235#if NKSYMS || defined(DDB) || defined(MODULAR) 236 RELOC(esym,%a0) | end of static kernel test/data/syms 237 movl %a0@,%d5 238 jne Lstart3 239#endif 240 movl #_C_LABEL(end),%d5 | end of static kernel text/data 241Lstart3: 242 RELOC(setmemrange,%a0) | call setmemrange() 243 jbsr %a0@ | to probe all memory regions 244 addl #PAGE_SIZE-1,%d5 245 andl #PG_FRAME,%d5 | round to a page 246 movl %d5,%a4 247 addl %a5,%a4 | convert to PA 248 pea %a5@ | firstpa 249 pea %a4@ | nextpa 250 RELOC(pmap_bootstrap,%a0) 251 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 252 addql #8,%sp 253 254/* 255 * Prepare to enable MMU. 256 * Since the kernel is mapped logical == physical, we just turn it on. 257 */ 258 RELOC(Sysseg_pa, %a0) | system segment table addr 259 movl %a0@,%d1 | read value (a PA) 260 RELOC(mmutype, %a0) 261 cmpl #MMU_68040,%a0@ | 68040? 262 jne Lmotommu1 | no, skip 263 .long 0x4e7b1807 | movc %d1,%srp 264 jra Lstploaddone 265Lmotommu1: 266 RELOC(protorp, %a0) 267 movl %d1,%a0@(4) | segtable address 268 pmove %a0@,%srp | load the supervisor root pointer 269Lstploaddone: 270 RELOC(mmutype, %a0) 271 cmpl #MMU_68040,%a0@ | 68040? 272 jne Lmotommu2 | no, skip 273#include "opt_jupiter.h" 274#ifdef JUPITER 275 /* JUPITER-X: set system register "SUPER" bit */ 276 movl #0x0200a240,%d0 | translate DRAM area transparently 277 .long 0x4e7b0006 | movc d0,dtt0 278 lea 0x00c00000,%a0 | %a0: graphic VRAM 279 lea 0x02c00000,%a1 | %a1: graphic VRAM ( not JUPITER-X ) 280 | DRAM ( JUPITER-X ) 281 movw %a0@,%d0 282 movw %d0,%d1 283 notw %d1 284 movw %d1,%a1@ 285 movw %d0,%a0@ 286 cmpw %a1@,%d1 | JUPITER-X? 287 jne Ljupiterdone | no, skip 288 movl #0x0100a240,%d0 | to access system register 289 .long 0x4e7b0006 | movc %d0,%dtt0 290 movb #0x01,0x01800003 | set "SUPER" bit 291Ljupiterdone: 292#endif /* JUPITER */ 293 moveq #0,%d0 | ensure TT regs are disabled 294 .long 0x4e7b0004 | movc %d0,%itt0 295 .long 0x4e7b0005 | movc %d0,%itt1 296 .long 0x4e7b0006 | movc %d0,%dtt0 297 .long 0x4e7b0007 | movc %d0,%dtt1 298 .word 0xf4d8 | cinva bc 299 .word 0xf518 | pflusha 300 movl #MMU40_TCR_BITS,%d0 301 .long 0x4e7b0003 | movc %d0,%tc 302#ifdef M68060 303 RELOC(cputype, %a0) 304 cmpl #CPU_68060,%a0@ | 68060? 305 jne Lnot060cache 306 movl #1,%d0 307 .long 0x4e7b0808 | movcl %d0,%pcr 308 movl #0xa0808000,%d0 309 movc %d0,%cacr | enable store buffer, both caches 310 jmp Lenab1 311Lnot060cache: 312#endif 313 movl #CACHE40_ON,%d0 314 movc %d0,%cacr | turn on both caches 315 jmp Lenab1 316Lmotommu2: 317 pflusha 318 movl #MMU51_TCR_BITS,%sp@- | value to load TC with 319 pmove %sp@,%tc | load it 320 321/* 322 * Should be running mapped from this point on 323 */ 324Lenab1: 325/* set vector base in virtual address */ 326 movl #_C_LABEL(vectab),%d0 | set Vector Base Register 327 movc %d0,%vbr 328 lea _ASM_LABEL(tmpstk),%sp | temporary stack 329/* call final pmap setup */ 330 jbsr _C_LABEL(pmap_bootstrap_finalize) 331/* set kernel stack, user SP */ 332 movl _C_LABEL(lwp0uarea),%a1 | get lwp0 uarea 333 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 334 movl #USRSTACK-4,%a2 335 movl %a2,%usp | init user SP 336 337/* detect FPU type */ 338 jbsr _C_LABEL(fpu_probe) 339 movl %d0,_C_LABEL(fputype) 340 tstl _C_LABEL(fputype) | Have an FPU? 341 jeq Lenab2 | No, skip. 342 clrl %a1@(PCB_FPCTX) | ensure null FP context 343 movl %a1,%sp@- 344 jbsr _C_LABEL(m68881_restore) | restore it (does not kill %a1) 345 addql #4,%sp 346Lenab2: 347 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 348 jeq Ltbia040 | yes, cache already on 349 pflusha 350 tstl _C_LABEL(mmutype) 351 jpl Lenab3 | 68851 implies no d-cache 352 movl #CACHE_ON,%d0 353 movc %d0,%cacr | clear cache(s) 354 jra Lenab3 355Ltbia040: 356 .word 0xf518 | pflusha 357Lenab3: 358/* final setup for C code */ 359 movl %d7,_C_LABEL(boothowto) | save reboot flags 360 movl %d6,_C_LABEL(bootdev) | and boot device 361 jbsr _C_LABEL(x68k_init) | additional pre-main initialization 362 363/* 364 * Create a fake exception frame so that cpu_lwp_fork() can copy it. 365 * main() nevers returns; we exit to user mode from a forked process 366 * later on. 367 */ 368 clrw %sp@- | vector offset/frame type 369 clrl %sp@- | PC - filled in by "execve" 370 movw #PSL_USER,%sp@- | in user mode 371 clrl %sp@- | stack adjust count and padding 372 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 373 lea _C_LABEL(lwp0),%a0 | save pointer to frame 374 movl %sp,%a0@(L_MD_REGS) | in lwp0.l_md.md_regs 375 376 jra _C_LABEL(main) | main() 377 378 PANIC("main() returned") | Yow! Main returned! 379 /* NOTREACHED */ 380 381/* 382 * Trap/interrupt vector routines 383 */ 384#include <m68k/m68k/trap_subr.s> 385 386/* 387 * Use common m68k bus error and address error handlers. 388 */ 389#include <m68k/m68k/busaddrerr.s> 390 391/* 392 * FP exceptions. 393 */ 394ENTRY_NOPROFILE(fpfline) 395#if defined(M68040) 396 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 397 jne Lfp_unimp | no, skip FPSP 398 cmpw #0x202c,%sp@(6) | format type 2? 399 jne _C_LABEL(illinst) | no, not an FP emulation 400#ifdef FPSP 401 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 402#else 403 clrl %sp@- | stack adjust count 404 moveml #0xFFFF,%sp@- | save registers 405 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 406 jra _ASM_LABEL(fault) | do it 407#endif 408Lfp_unimp: 409#endif /* M68040 */ 410#ifdef FPU_EMULATE 411 clrl %sp@- | stack adjust count 412 moveml #0xFFFF,%sp@- | save registers 413 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 414 jra _ASM_LABEL(fault) | do it 415#else 416 jra _C_LABEL(illinst) 417#endif 418 419ENTRY_NOPROFILE(fpunsupp) 420#if defined(M68040) 421 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 422 jne Lfp_unsupp | no, skip FPSP 423#ifdef FPSP 424 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 425#else 426 clrl %sp@- | stack adjust count 427 moveml #0xFFFF,%sp@- | save registers 428 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 429 jra _ASM_LABEL(fault) | do it 430#endif /* M68040 */ 431Lfp_unsupp: 432#endif 433#ifdef FPU_EMULATE 434 clrl %sp@- | stack adjust count 435 moveml #0xFFFF,%sp@- | save registers 436 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 437 jra _ASM_LABEL(fault) | do it 438#else 439 jra _C_LABEL(illinst) 440#endif 441 442/* 443 * Handles all other FP coprocessor exceptions. 444 * Note that since some FP exceptions generate mid-instruction frames 445 * and may cause signal delivery, we need to test for stack adjustment 446 * after the trap call. 447 */ 448ENTRY_NOPROFILE(fpfault) 449 clrl %sp@- | stack adjust count 450 moveml #0xFFFF,%sp@- | save user registers 451 movl %usp,%a0 | and save 452 movl %a0,%sp@(FR_SP) | the user stack pointer 453 clrl %sp@- | no VA arg 454 movl _C_LABEL(curpcb),%a0 | current pcb 455 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 456 fsave %a0@ | save state 457#if defined(M68040) || defined(M68060) 458 /* always null state frame on 68040, 68060 */ 459 cmpl #FPU_68040,_C_LABEL(fputype) 460 jge Lfptnull 461#endif 462 tstb %a0@ | null state frame? 463 jeq Lfptnull | yes, safe 464 clrw %d0 | no, need to tweak BIU 465 movb %a0@(1),%d0 | get frame size 466 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 467Lfptnull: 468 fmovem %fpsr,%sp@- | push fpsr as code argument 469 frestore %a0@ | restore state 470 movl #T_FPERR,%sp@- | push type arg 471 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 472 473/* 474 * Other exceptions only cause four and six word stack frame and require 475 * no post-trap stack adjustment. 476 */ 477 478ENTRY_NOPROFILE(badtrap) 479 moveml #0xC0C0,%sp@- | save scratch regs 480 movw %sp@(22),%sp@- | push exception vector info 481 clrw %sp@- 482 movl %sp@(22),%sp@- | and PC 483 jbsr _C_LABEL(straytrap) | report 484 addql #8,%sp | pop args 485 moveml %sp@+,#0x0303 | restore regs 486 jra _ASM_LABEL(rei) | all done 487 488ENTRY_NOPROFILE(trap0) 489 clrl %sp@- | stack adjust count 490 moveml #0xFFFF,%sp@- | save user registers 491 movl %usp,%a0 | save the user SP 492 movl %a0,%sp@(FR_SP) | in the savearea 493 movl %d0,%sp@- | push syscall number 494 jbsr _C_LABEL(syscall) | handle it 495 addql #4,%sp | pop syscall arg 496 tstl _C_LABEL(astpending) | AST pending? 497 jne Lrei | yes, handle it via trap 498 movl %sp@(FR_SP),%a0 | grab and restore 499 movl %a0,%usp | user SP 500 moveml %sp@+,#0x7FFF | restore most registers 501 addql #8,%sp | pop SP and stack adjust 502 rte 503 504/* 505 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 506 * cachectl(command, addr, length) 507 * command in %d0, addr in %a1, length in %d1 508 */ 509ENTRY_NOPROFILE(trap12) 510 movl _C_LABEL(curlwp),%a0 511 movl %a0@(L_PROC),%sp@- | push current proc pointer 512 movl %d1,%sp@- | push length 513 movl %a1,%sp@- | push addr 514 movl %d0,%sp@- | push command 515 jbsr _C_LABEL(cachectl1) | do it 516 lea %sp@(16),%sp | pop args 517 jra _ASM_LABEL(rei) | all done 518 519/* 520 * Trace (single-step) trap. Kernel-mode is special. 521 * User mode traps are simply passed on to trap(). 522 */ 523ENTRY_NOPROFILE(trace) 524 clrl %sp@- | stack adjust count 525 moveml #0xFFFF,%sp@- 526 moveq #T_TRACE,%d0 527 528 | Check PSW and see what happen. 529 | T=0 S=0 (should not happen) 530 | T=1 S=0 trace trap from user mode 531 | T=0 S=1 trace trap on a trap instruction 532 | T=1 S=1 trace trap from system mode (kernel breakpoint) 533 534 movw %sp@(FR_HW),%d1 | get PSW 535 notw %d1 | XXX no support for T0 on 680[234]0 536 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 537 jeq Lkbrkpt | yes, kernel breakpoint 538 jra _ASM_LABEL(fault) | no, user-mode fault 539 540/* 541 * Trap 15 is used for: 542 * - GDB breakpoints (in user programs) 543 * - KGDB breakpoints (in the kernel) 544 * - trace traps for SUN binaries (not fully supported yet) 545 * User mode traps are simply passed to trap(). 546 */ 547ENTRY_NOPROFILE(trap15) 548 clrl %sp@- | stack adjust count 549 moveml #0xFFFF,%sp@- 550 moveq #T_TRAP15,%d0 551 movw %sp@(FR_HW),%d1 | get PSW 552 andw #PSL_S,%d1 | from system mode? 553 jne Lkbrkpt | yes, kernel breakpoint 554 jra _ASM_LABEL(fault) | no, user-mode fault 555 556Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type) 557 | Save the system sp rather than the user sp. 558 movw #PSL_HIGHIPL,%sr | lock out interrupts 559 lea %sp@(FR_SIZE),%a6 | Save stack pointer 560 movl %a6,%sp@(FR_SP) | from before trap 561 562 | If were are not on tmpstk switch to it. 563 | (so debugger can change the stack pointer) 564 movl %a6,%d1 565 cmpl #_ASM_LABEL(tmpstk),%d1 566 jls Lbrkpt2 | already on tmpstk 567 | Copy frame to the temporary stack 568 movl %sp,%a0 | %a0=src 569 lea _ASM_LABEL(tmpstk)-96,%a1 | %a1=dst 570 movl %a1,%sp | %sp=new frame 571 moveq #FR_SIZE,%d1 572Lbrkpt1: 573 movl %a0@+,%a1@+ 574 subql #4,%d1 575 jgt Lbrkpt1 576 577Lbrkpt2: 578 | Call the trap handler for the kernel debugger. 579 | Do not call trap() to do it, so that we can 580 | set breakpoints in trap() if we want. We know 581 | the trap type is either T_TRACE or T_BREAKPOINT. 582 | If we have both DDB and KGDB, let KGDB see it first, 583 | because KGDB will just return 0 if not connected. 584 | Save args in %d2, %a2 585 movl %d0,%d2 | trap type 586 movl %sp,%a2 | frame ptr 587#ifdef KGDB 588 | Let KGDB handle it (if connected) 589 movl %a2,%sp@- | push frame ptr 590 movl %d2,%sp@- | push trap type 591 jbsr _C_LABEL(kgdb_trap) | handle the trap 592 addql #8,%sp | pop args 593 cmpl #0,%d0 | did kgdb handle it? 594 jne Lbrkpt3 | yes, done 595#endif 596#ifdef DDB 597 | Let DDB handle it 598 movl %a2,%sp@- | push frame ptr 599 movl %d2,%sp@- | push trap type 600 jbsr _C_LABEL(kdb_trap) | handle the trap 601 addql #8,%sp | pop args 602#if 0 /* not needed on hp300 */ 603 cmpl #0,%d0 | did ddb handle it? 604 jne Lbrkpt3 | yes, done 605#endif 606#endif 607 /* Sun 3 drops into PROM here. */ 608Lbrkpt3: 609 | The stack pointer may have been modified, or 610 | data below it modified (by kgdb push call), 611 | so push the hardware frame at the current sp 612 | before restoring registers and returning. 613 614 movl %sp@(FR_SP),%a0 | modified %sp 615 lea %sp@(FR_SIZE),%a1 | end of our frame 616 movl %a1@-,%a0@- | copy 2 longs with 617 movl %a1@-,%a0@- | ... predecrement 618 movl %a0,%sp@(FR_SP) | %sp = h/w frame 619 moveml %sp@+,#0x7FFF | restore all but %sp 620 movl %sp@,%sp | ... and %sp 621 rte | all done 622 623/* 624 * Provide a generic interrupt dispatcher, only handle hardclock (int6) 625 * specially, to improve performance 626 */ 627 628ENTRY_NOPROFILE(spurintr) /* level 0 */ 629 addql #1,_C_LABEL(intrcnt)+0 630 INTERRUPT_SAVEREG 631 CPUINFO_INCREMENT(CI_NINTR) 632 INTERRUPT_RESTOREREG 633 rte | XXX mfpcure (x680x0 hardware bug) 634 635ENTRY_NOPROFILE(kbdtimer) 636 rte 637 638ENTRY_NOPROFILE(intiotrap) 639 addql #1,_C_LABEL(intr_depth) 640 INTERRUPT_SAVEREG 641 pea %sp@(16-(FR_HW)) | XXX 642 jbsr _C_LABEL(intio_intr) 643 addql #4,%sp 644 CPUINFO_INCREMENT(CI_NINTR) 645 INTERRUPT_RESTOREREG 646 subql #1,_C_LABEL(intr_depth) 647 jra rei 648 649ENTRY_NOPROFILE(lev1intr) 650ENTRY_NOPROFILE(lev2intr) 651ENTRY_NOPROFILE(lev3intr) 652ENTRY_NOPROFILE(lev4intr) 653ENTRY_NOPROFILE(lev5intr) 654ENTRY_NOPROFILE(lev6intr) 655 addql #1,_C_LABEL(intr_depth) 656 INTERRUPT_SAVEREG 657Lnotdma: 658 lea _C_LABEL(intrcnt),%a0 659 movw %sp@(22),%d0 | use vector offset 660 andw #0xfff,%d0 | sans frame type 661 addql #1,%a0@(-0x60,%d0:w) | to increment apropos counter 662 movw %sr,%sp@- | push current SR value 663 clrw %sp@- | padded to longword 664 jbsr _C_LABEL(intrhand) | handle interrupt 665 addql #4,%sp | pop SR 666 CPUINFO_INCREMENT(CI_NINTR) 667 INTERRUPT_RESTOREREG 668 subql #1,_C_LABEL(intr_depth) 669 jra _ASM_LABEL(rei) 670 671ENTRY_NOPROFILE(timertrap) 672 addql #1,_C_LABEL(intr_depth) 673 INTERRUPT_SAVEREG | save scratch registers 674 addql #1,_C_LABEL(intrcnt)+32 | count hardclock interrupts 675 movl %sp,%sp@- | push pointer to clockframe 676 jbsr _C_LABEL(hardclock) | hardclock(&frame) 677 addql #4,%sp 678 CPUINFO_INCREMENT(CI_NINTR) | chalk up another interrupt 679 INTERRUPT_RESTOREREG | restore scratch registers 680 subql #1,_C_LABEL(intr_depth) 681 jra _ASM_LABEL(rei) | all done 682 683ENTRY_NOPROFILE(lev7intr) 684 addql #1,_C_LABEL(intr_depth) 685 addql #1,_C_LABEL(intrcnt)+28 686 clrl %sp@- 687 moveml #0xFFFF,%sp@- | save registers 688 movl %usp,%a0 | and save 689 movl %a0,%sp@(FR_SP) | the user stack pointer 690 jbsr _C_LABEL(nmihand) | call handler 691 movl %sp@(FR_SP),%a0 | restore 692 movl %a0,%usp | user SP 693 moveml %sp@+,#0x7FFF | and remaining registers 694 addql #8,%sp | pop SP and stack adjust 695 subql #1,_C_LABEL(intr_depth) 696 jra _ASM_LABEL(rei) | all done 697 698/* 699 * floppy ejection trap 700 */ 701 702ENTRY_NOPROFILE(fdeject) 703 jra _ASM_LABEL(rei) 704 705/* 706 * Emulation of VAX REI instruction. 707 * 708 * This code deals with checking for and servicing ASTs 709 * (profiling, scheduling) and software interrupts (network, softclock). 710 * We check for ASTs first, just like the VAX. To avoid excess overhead 711 * the T_ASTFLT handling code will also check for software interrupts so we 712 * do not have to do it here. After identifying that we need an AST we 713 * drop the IPL to allow device interrupts. 714 * 715 * This code is complicated by the fact that sendsig may have been called 716 * necessitating a stack cleanup. 717 */ 718 719ASENTRY_NOPROFILE(rei) 720 tstl _C_LABEL(astpending) | AST pending? 721 jne 1f | no, done 722 rte 7231: 724 btst #5,%sp@ | yes, are we returning to user mode? 725 beq 2f | no, done 726 rte 7272: 728 movw #PSL_LOWIPL,%sr | lower SPL 729 clrl %sp@- | stack adjust 730 moveml #0xFFFF,%sp@- | save all registers 731 movl %usp,%a1 | including 732 movl %a1,%sp@(FR_SP) | the users SP 733Lrei: 734 clrl %sp@- | VA == none 735 clrl %sp@- | code == none 736 movl #T_ASTFLT,%sp@- | type == async system trap 737 pea %sp@(12) | fp == trap frame address 738 jbsr _C_LABEL(trap) | go handle it 739 lea %sp@(16),%sp | pop value args 740 movl %sp@(FR_SP),%a0 | restore user SP 741 movl %a0,%usp | from save area 742 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 743 jne Laststkadj | yes, go to it 744 moveml %sp@+,#0x7FFF | no, restore most user regs 745 addql #8,%sp | toss SP and stack adjust 746 rte | and do real RTE 747Laststkadj: 748 lea %sp@(FR_HW),%a1 | pointer to HW frame 749 addql #8,%a1 | source pointer 750 movl %a1,%a0 | source 751 addw %d0,%a0 | + hole size = dest pointer 752 movl %a1@-,%a0@- | copy 753 movl %a1@-,%a0@- | 8 bytes 754 movl %a0,%sp@(FR_SP) | new SSP 755 moveml %sp@+,#0x7FFF | restore user registers 756 movl %sp@,%sp | and our SP 757 rte | and do real RTE 758 759/* 760 * Primitives 761 */ 762 763/* 764 * Use common m68k process/lwp switch and context save subroutines. 765 */ 766#define FPCOPROC /* XXX: Temp. reqd. */ 767#include <m68k/m68k/switch_subr.s> 768 769 770#if defined(M68040) || defined(M68060) 771ENTRY(suline) 772 movl %sp@(4),%a0 | address to write 773 movl _C_LABEL(curpcb),%a1 | current pcb 774 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 775 movl %sp@(8),%a1 | address of line 776 movl %a1@+,%d0 | get lword 777 movsl %d0,%a0@+ | put lword 778 nop | sync 779 movl %a1@+,%d0 | get lword 780 movsl %d0,%a0@+ | put lword 781 nop | sync 782 movl %a1@+,%d0 | get lword 783 movsl %d0,%a0@+ | put lword 784 nop | sync 785 movl %a1@+,%d0 | get lword 786 movsl %d0,%a0@+ | put lword 787 nop | sync 788 moveq #0,%d0 | indicate no fault 789 jra Lsldone 790Lslerr: 791 moveq #-1,%d0 792Lsldone: 793 movl _C_LABEL(curpcb),%a1 | current pcb 794 clrl %a1@(PCB_ONFAULT) | clear fault address 795 rts 796#endif 797 798ENTRY(ecacheon) 799 rts 800 801ENTRY(ecacheoff) 802 rts 803 804/* 805 * _delay(u_int N) 806 * 807 * Delay for at least N microseconds. 808 * This routine depends on the variable: delay_divisor 809 * which should be set based on the CPU clock rate. 810 */ 811ENTRY_NOPROFILE(_delay) 812 | %d0 = (usecs * a certain magnification factor) 813 movl %sp@(4),%d0 814 lsll #8,%d0 815 | %d1 = delay_divisor 816 movl _C_LABEL(delay_divisor),%d1 817L_delay: 818 subl %d1,%d0 819 jgt L_delay 820 rts 821 822/* 823 * Handle the nitty-gritty of rebooting the machine. 824 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 825 * Note that we must be running in an address range that is mapped one-to-one 826 * logical to physical so that the PC is still valid immediately after the MMU 827 * is turned off. We have conveniently mapped the last page of physical 828 * memory this way. 829 */ 830ENTRY_NOPROFILE(doboot) 831 movw #PSL_HIGHIPL,%sr | cut off any interrupts 832 subal %a1,%a1 | a1 = 0 833 834 movl #CACHE_OFF,%d0 835#if defined(M68040) || defined(M68060) 836 movl _C_LABEL(mmutype),%d2 | d2 = mmutype 837 addl #(-1 * MMU_68040),%d2 | 68040? 838 jne Ldoboot0 | no, skip 839 .word 0xf4f8 | cpusha bc - push and invalidate caches 840 nop 841 movl #CACHE40_OFF,%d0 842Ldoboot0: 843#endif 844 movc %d0,%cacr | disable on-chip cache(s) 845 846 | ok, turn off MMU.. 847Ldoreboot: 848#if defined(M68040) || defined(M68060) 849 tstl %d2 | 68040? 850 jne LmotommuF | no, skip 851 movc %a1,%cacr | caches off 852 .long 0x4e7b9003 | movc a1(=0),tc ; disable MMU 853 jra Ldoreboot1 854LmotommuF: 855#endif 856 clrl %sp@ 857 pmove %sp@,%tc | disable MMU 858Ldoreboot1: 859 moveml 0x00ff0000,#0x0101 | get RESET vectors in ROM 860 | (d0: ssp, a0: pc) 861 moveml #0x0101,%a1@ | put them at 0x0000 (for Xellent30) 862 movc %a1,%vbr | reset Vector Base Register 863 jmp %a0@ | reboot X680x0 864Lebootcode: 865 866/* 867 * Misc. global variables. 868 */ 869 .data 870GLOBAL(mmutype) 871 .long MMU_68030 | default to 030 internal MMU 872 873GLOBAL(cputype) 874 .long CPU_68030 | default to 68030 CPU 875 876#ifdef M68K_MMU_HP 877GLOBAL(ectype) 878 .long EC_NONE | external cache type, default to none 879#endif 880 881GLOBAL(fputype) 882 .long FPU_NONE 883 884GLOBAL(intiobase) 885 .long 0 | KVA of base of internal IO space 886 887GLOBAL(intiolimit) 888 .long 0 | KVA of end of internal IO space 889 890#ifdef DEBUG 891ASGLOBAL(fulltflush) 892 .long 0 893 894ASGLOBAL(fullcflush) 895 .long 0 896#endif 897 898/* interrupt counters */ 899 900GLOBAL(intrnames) 901 .asciz "spur" 902 .asciz "lev1" 903 .asciz "lev2" 904 .asciz "lev3" 905 .asciz "lev4" 906 .asciz "lev5" 907 .asciz "lev6" 908 .asciz "nmi" 909 .asciz "clock" 910 .asciz "com" 911GLOBAL(eintrnames) 912 .even 913 914GLOBAL(intrcnt) 915 .long 0,0,0,0,0,0,0,0,0,0 916GLOBAL(eintrcnt) 917