1/* $NetBSD: locore.s,v 1.85 2024/01/17 12:33:50 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1998 Darrin B. Jewell 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/* 42 * Copyright (c) 1994, 1995 Gordon W. Ross 43 * Copyright (c) 1988 University of Utah. 44 * 45 * This code is derived from software contributed to Berkeley by 46 * the Systems Programming Group of the University of Utah Computer 47 * Science Department. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 3. All advertising materials mentioning features or use of this software 58 * must display the following acknowledgement: 59 * This product includes software developed by the University of 60 * California, Berkeley and its contributors. 61 * 4. Neither the name of the University nor the names of its contributors 62 * may be used to endorse or promote products derived from this software 63 * without specific prior written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 68 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 75 * SUCH DAMAGE. 76 * 77 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 78 * 79 * @(#)locore.s 8.6 (Berkeley) 5/27/94 80 */ 81 82/* This is currently amid development by 83 * Darrin Jewell <jewell@mit.edu> Fri Jan 2 14:36:47 1998 84 * for the next68k port 85 */ 86 87#include "opt_compat_netbsd.h" 88#include "opt_compat_sunos.h" 89#include "opt_ddb.h" 90#include "opt_fpsp.h" 91#include "opt_kgdb.h" 92#include "opt_lockdebug.h" 93#include "opt_fpu_emulate.h" 94#include "opt_useleds.h" 95#include "opt_m68k_arch.h" 96 97#include "assym.h" 98#include <machine/asm.h> 99#include <machine/trap.h> 100 101#if (!defined(M68040)) 102#error "M68040 is not defined! (check that the generated assym.h is not empty)" 103#endif 104 105#include "ksyms.h" 106 107/* 108 * This is for kvm_mkdb, and should be the address of the beginning 109 * of the kernel text segment (not necessarily the same as kernbase). 110 */ 111 .text 112GLOBAL(kernel_text) 113 114 /* 115 * Leave page zero empty so it can be unmapped 116 */ 117 .space PAGE_SIZE 118 119/* 120 * Temporary stack for a variety of purposes. 121 */ 122 .data 123GLOBAL(endstack) 124 .space PAGE_SIZE 125GLOBAL(bgnstack) 126ASLOCAL(tmpstk) 127 128/* 129 * Macro to relocate a symbol, used before MMU is enabled. 130 * On the NeXT, memory is laid out as in the mach header 131 * so therefore we need to relocate symbols until the MMU 132 * is turned on. 133 */ 134#define _RELOC(var, ar) \ 135 lea var,ar; \ 136 addl %a5,ar 137 138#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 139#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 140 141/* 142 * Initialization info as per grossman's boot loader: 143 * 144 * We are called from the boot prom, not the boot loader. We have the 145 * prom's stack initialized for us and we were called like this: 146 * start(mg, mg->mg_console_i, mg->mg_console_o, 147 * mg->mg_boot_dev, mg->mg_boot_arg, mg->mg_boot_info, 148 * mg->mg_sid, mg->mg_pagesize, 4, mg->mg_region, 149 * etheraddr, mg->mg_boot_file); 150 * so we actually only really need the first parameter from the stack. 151 * Exceptions will be handled by the prom until we feel ready to handle 152 * them ourselves. 153 * By the way, we get loaded at our final address i.e. PA==VA for the kernel. 154 */ 155 /* I think the PA==VA comment to be a lie, but I have yet to verify it. 156 * Darrin B Jewell <jewell@mit.edu> Sun Jan 11 01:05:54 1998 157 */ 158BSS(lowram,4) 159BSS(esym,4) 160 161ASENTRY_NOPROFILE(start) 162 movw #PSL_HIGHIPL,%sr | no interrupts 163 movl #CACHE_OFF,%d0 164 movc %d0,%cacr | clear and disable on-chip cache(s) 165 166 moveal #NEXT_RAMBASE,%a5 | amount to RELOC by. 167 RELOC(lowram,%a0) | store base of memory. 168 movl %a5,%a0@ 169 170 | Create a new stack at address tmpstk, and push 171 | The existing sp onto it as an arg for next68k_bootargs. 172 ASRELOC(tmpstk, %a0) 173 movel %sp,%a0@- 174 moveal %a0,%sp 175 moveal #0,%a6 176 177 /* Read the header to get our segment list */ 178 RELOC(next68k_bootargs,%a0) 179 jbsr %a0@ | next68k_bootargs(args) 180 addqw #4,%sp | clear arg from stack. 181 182 /* 183 * All data registers are now free. All address registers 184 * except %a5 are free. %a5 is used by the RELOC() macro on hp300 185 * and cannot be used until after the MMU is enabled. 186 */ 187 188/* determine our CPU/MMU combo - check for all regardless of kernel config */ 189 movl #0x200,%d0 | data freeze bit 190 movc %d0,%cacr | only exists on 68030 191 movc %cacr,%d0 | read it back 192 tstl %d0 | zero? 193 jeq Lnot68030 | yes, we have 68020/68040 194 195 /* 196 * 68030 models 197 */ 198 199 RELOC(mmutype, %a0) | no, we have 68030 200 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU 201 RELOC(cputype, %a0) 202 movl #CPU_68030,%a0@ | and 68030 CPU 203 RELOC(machineid, %a0) 204 movl #30,%a0@ | @@@ useless 205 jra Lstart1 206 207 /* 208 * End of 68030 section 209 */ 210 211Lnot68030: 212 bset #31,%d0 | data cache enable bit 213 movc %d0,%cacr | only exists on 68040 214 movc %cacr,%d0 | read it back 215 tstl %d0 | zero? 216 beq Lis68020 | yes, we have 68020 217 moveq #0,%d0 | now turn it back off 218 movec %d0,%cacr | before we access any data 219 220 /* 221 * 68040 models 222 */ 223 224 RELOC(mmutype, %a0) 225 movl #MMU_68040,%a0@ | with a 68040 MMU 226 RELOC(cputype, %a0) 227 movl #CPU_68040,%a0@ | and a 68040 CPU 228 RELOC(fputype, %a0) 229 movl #FPU_68040,%a0@ | ...and FPU 230 RELOC(machineid, %a0) 231 movl #40,%a0@ | @@@ useless 232 jra Lstart1 233 234 /* 235 * End of 68040 section 236 */ 237 238 /* 239 * 68020 models 240 * (There are no 68020 models of NeXT, but we'll pretend) 241 */ 242 243Lis68020: 244 RELOC(mmutype, %a0) 245 movl #MMU_68851,%a0@ | no, we have PMMU 246 RELOC(fputype, %a0) | all of the 68020 systems 247 movl #FPU_68881,%a0@ | have a 68881 FPU 248 RELOC(cputype, %a0) 249 movl #CPU_68020,%a0@ | and a 68020 CPU 250 RELOC(machineid, %a0) 251 movl #20,%a0@ | @@@ useless 252 jra Lstart1 253 254 /* 255 * End of 68020 section 256 */ 257 258Lstart1: 259/* initialize source/destination control registers for movs */ 260 moveq #FC_USERD,%d0 | user space 261 movc %d0,%sfc | as source 262 movc %d0,%dfc | and destination of transfers 263/* configure kernel and lwp0 VA space so we can get going */ 264#if NKSYMS || defined(DDB) || defined(MODULAR) 265 RELOC(esym,%a0) | end of static kernel test/data/syms 266 movl %a0@,%d5 267 jne Lstart3 268#endif 269 movl #_C_LABEL(end),%d5 | end of static kernel text/data 270 271Lstart3: 272 addl #PAGE_SIZE-1,%d5 273 andl #PG_FRAME,%d5 | round to a page 274 movl %d5,%a4 275 addl %a5,%a4 | convert to PA 276 pea %a5@ | firstpa 277 pea %a4@ | nextpa 278 RELOC(pmap_bootstrap,%a0) 279 jbsr %a0@ | pmap_bootstrap(firstpa,nextpa) 280 addql #8,%sp 281 282/* 283 * Prepare to enable MMU. 284 * Since the kernel is not mapped logical == physical we must insure 285 * that when the MMU is turned on, all prefetched addresses (including 286 * the PC) are valid. In order guarantee that, we use the transparent 287 * translation registers (which provide PA == VA mappings) and just 288 * turns on the MMU, then jump from the VA == PA address (at 0x40XXXXXX) 289 * to the actual kernel virtual address (at 0x00XXXXXX) code via a far 290 * jump instruction so that we can defeat the prefetch. 291 */ 292 RELOC(Sysseg_pa, %a0) | system segment table addr 293 movl %a0@,%d1 | read value (a PA) 294 295 RELOC(mmutype, %a0) 296 cmpl #MMU_68040,%a0@ | 68040? 297 jne Lmotommu1 | no, skip 298 .long 0x4e7b1807 | movc %d1,%srp 299 jra Lstploaddone 300Lmotommu1: 301#ifdef M68030 302 RELOC(protorp, %a0) 303 movl %d1,%a0@(4) | segtable address 304 pmove %a0@,%srp | load the supervisor root pointer 305#endif /* M68030 */ 306 307Lstploaddone: 308 RELOC(mmutype, %a0) 309 cmpl #MMU_68040,%a0@ | 68040? 310 jne Lmotommu2 | no, skip 311 312 | This is a hack to get PA=KVA when turning on MMU as mentioned above. 313 | Currently this will only work on 68040's. We should also provide 314 | %tt0 and %tt1 settings to boot 68030's later. 315 movel #NEXT68K_TT40_IO,%d0 | see pmap.h 316 .long 0x4e7b0004 | movc %d0,%itt0 317 .long 0x4e7b0006 | movc %d0,%dtt0 318 movel #NEXT68K_TT40_KERN,%d0 | see pmap.h 319 .long 0x4e7b0005 | movc %d0,%itt1 320 .long 0x4e7b0007 | movc %d0,%dtt1 321 322 .word 0xf4d8 | cinva bc 323 .word 0xf518 | pflusha 324 movl #MMU40_TCR_BITS,%d0 325 .long 0x4e7b0003 | movc %d0,%tc 326 movl #0x80008000,%d0 327 movc %d0,%cacr | turn on both caches 328 329 jmp Lturnoffttr:l | global jump into mapped memory. 330Lturnoffttr: 331 moveq #0,%d0 | ensure TT regs are disabled 332 .long 0x4e7b0004 | movc %d0,%itt0 333 .long 0x4e7b0006 | movc %d0,%dtt0 334 .long 0x4e7b0005 | movc %d0,%itt1 335 .long 0x4e7b0007 | movc %d0,%dtt1 336 jmp Lenab1 337 338Lmotommu2: 339 pflusha 340 RELOC(prototc, %a2) 341 movl #MMU51_TCR_BITS,%a2@ | value to load TC with 342 pmove %a2@,%tc | load it 343 jmp Lenab1:l | force absolute (not pc-relative) jmp 344 345/* 346 * Should be running mapped from this point on 347 */ 348Lenab1: 349 lea _ASM_LABEL(tmpstk),%sp | re-load temporary stack 350 jbsr _C_LABEL(vec_init) | initialize vector table 351/* call final pmap setup */ 352 jbsr _C_LABEL(pmap_bootstrap_finalize) 353/* set kernel stack, user SP */ 354 movl _C_LABEL(lwp0uarea),%a1 | get lwp0 uarea 355 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 356 movl #USRSTACK-4,%a2 357 movl %a2,%usp | init user SP 358 359 tstl _C_LABEL(fputype) | Have an FPU? 360 jeq Lenab2 | No, skip. 361 clrl %a1@(PCB_FPCTX) | ensure null FP context 362 movl %a1,%sp@- 363 jbsr _C_LABEL(m68881_restore) | restore it (does not kill %a1) 364 addql #4,%sp 365Lenab2: 366 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 367 jeq Ltbia040 | yes, cache already on 368 pflusha 369 movl #CACHE_ON,%d0 370 movc %d0,%cacr | clear cache(s) 371 jra Lenab3 372Ltbia040: 373 .word 0xf518 | pflusha 374Lenab3: 375 376 jbsr _C_LABEL(next68k_init) 377 378/* Final setup for call to main(). */ 379/* 380 * Create a fake exception frame so that cpu_lwp_fork() can copy it. 381 * main() nevers returns; we exit to user mode from a forked process 382 * later on. 383 */ 384 clrw %sp@- | vector offset/frame type 385 clrl %sp@- | PC - filled in by "execve" 386 movw #PSL_USER,%sp@- | in user mode 387 clrl %sp@- | stack adjust count and padding 388 lea %sp@(-64),%sp | construct space for %D0-%D7/%A0-%A7 389 lea _C_LABEL(lwp0),%a0 | save pointer to frame 390 movl %sp,%a0@(L_MD_REGS) | in lwp0.p_md.md_regs 391 392 jra _C_LABEL(main) | main() 393 PANIC("main() returned") 394 /* NOTREACHED */ 395 396/* 397 * Trap/interrupt vector routines 398 */ 399#include <m68k/m68k/trap_subr.s> 400 401/* 402 * Use common m68k bus error and address error handlers. 403 */ 404#include <m68k/m68k/busaddrerr.s> 405 406/* 407 * FP exceptions. 408 */ 409ENTRY_NOPROFILE(fpfline) 410#if defined(M68040) 411 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 412 jne Lfp_unimp | no, skip FPSP 413 cmpw #0x202c,%sp@(6) | format type 2? 414 jne _C_LABEL(illinst) | no, not an FP emulation 415Ldofp_unimp: 416#ifdef FPSP 417 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 418#endif 419Lfp_unimp: 420#endif /* M68040 */ 421#ifdef FPU_EMULATE 422 clrl %sp@- | stack adjust count 423 moveml #0xFFFF,%sp@- | save registers 424 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 425 jra _ASM_LABEL(fault) | do it 426#else 427 jra _C_LABEL(illinst) 428#endif 429 430ENTRY_NOPROFILE(fpunsupp) 431#if defined(M68040) 432 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 433 jne _C_LABEL(illinst) | no, treat as illinst 434#ifdef FPSP 435 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 436#endif 437Lfp_unsupp: 438#endif /* M68040 */ 439#ifdef FPU_EMULATE 440 clrl %sp@- | stack adjust count 441 moveml #0xFFFF,%sp@- | save registers 442 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 443 jra _ASM_LABEL(fault) | do it 444#else 445 jra _C_LABEL(illinst) 446#endif 447 448/* 449 * Handles all other FP coprocessor exceptions. 450 * Note that since some FP exceptions generate mid-instruction frames 451 * and may cause signal delivery, we need to test for stack adjustment 452 * after the trap call. 453 */ 454ENTRY_NOPROFILE(fpfault) 455 clrl %sp@- | stack adjust count 456 moveml #0xFFFF,%sp@- | save user registers 457 movl %usp,%a0 | and save 458 movl %a0,%sp@(FR_SP) | the user stack pointer 459 clrl %sp@- | no VA arg 460 movl _C_LABEL(curpcb),%a0 | current pcb 461 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 462 fsave %a0@ | save state 463#if defined(M68040) || defined(M68060) 464 /* always null state frame on 68040, 68060 */ 465 cmpl #FPU_68040,_C_LABEL(fputype) 466 jge Lfptnull 467#endif 468 tstb %a0@ | null state frame? 469 jeq Lfptnull | yes, safe 470 clrw %d0 | no, need to tweak BIU 471 movb %a0@(1),%d0 | get frame size 472 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 473Lfptnull: 474 fmovem %fpsr,%sp@- | push %fpsr as code argument 475 frestore %a0@ | restore state 476 movl #T_FPERR,%sp@- | push type arg 477 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 478 479/* 480 * Other exceptions only cause four and six word stack frame and require 481 * no post-trap stack adjustment. 482 */ 483 484ENTRY_NOPROFILE(badtrap) 485 moveml #0xC0C0,%sp@- | save scratch regs 486 movw %sp@(22),%sp@- | push exception vector info 487 clrw %sp@- 488 movl %sp@(22),%sp@- | and PC 489 jbsr _C_LABEL(straytrap) | report 490 addql #8,%sp | pop args 491 moveml %sp@+,#0x0303 | restore regs 492 jra _ASM_LABEL(rei) | all done 493 494ENTRY_NOPROFILE(trap0) 495 clrl %sp@- | stack adjust count 496 moveml #0xFFFF,%sp@- | save user registers 497 movl %usp,%a0 | save the user SP 498 movl %a0,%sp@(FR_SP) | in the savearea 499 movl %d0,%sp@- | push syscall number 500 jbsr _C_LABEL(syscall) | handle it 501 addql #4,%sp | pop syscall arg 502 tstl _C_LABEL(astpending) 503 jne Lrei 504 movl %sp@(FR_SP),%a0 | grab and restore 505 movl %a0,%usp | user SP 506 moveml %sp@+,#0x7FFF | restore most registers 507 addql #8,%sp | pop SP and stack adjust 508 rte 509 510/* 511 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 512 * cachectl(command, addr, length) 513 * command in %d0, addr in %a1, length in %d1 514 */ 515ENTRY_NOPROFILE(trap12) 516 movl _C_LABEL(curlwp),%a0 517 movl %a0@(L_PROC),%sp@- | push curproc pointer 518 movl %d1,%sp@- | push length 519 movl %a1,%sp@- | push addr 520 movl %d0,%sp@- | push command 521 jbsr _C_LABEL(cachectl1) | do it 522 lea %sp@(16),%sp | pop args 523 jra _ASM_LABEL(rei) | all done 524 525/* 526 * Trace (single-step) trap. Kernel-mode is special. 527 * User mode traps are simply passed on to trap(). 528 */ 529ENTRY_NOPROFILE(trace) 530 clrl %sp@- | stack adjust count 531 moveml #0xFFFF,%sp@- 532 moveq #T_TRACE,%d0 533 534 | Check PSW and see what happen. 535 | T=0 S=0 (should not happen) 536 | T=1 S=0 trace trap from user mode 537 | T=0 S=1 trace trap on a trap instruction 538 | T=1 S=1 trace trap from system mode (kernel breakpoint) 539 540 movw %sp@(FR_HW),%d1 | get PSW 541 notw %d1 | XXX no support for T0 on 680[234]0 542 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 543 jeq Lkbrkpt | yes, kernel breakpoint 544 jra _ASM_LABEL(fault) | no, user-mode fault 545 546/* 547 * Trap 15 is used for: 548 * - GDB breakpoints (in user programs) 549 * - KGDB breakpoints (in the kernel) 550 * - trace traps for SUN binaries (not fully supported yet) 551 * User mode traps are simply passed to trap(). 552 */ 553ENTRY_NOPROFILE(trap15) 554 clrl %sp@- | stack adjust count 555 moveml #0xFFFF,%sp@- 556 moveq #T_TRAP15,%d0 557 movw %sp@(FR_HW),%d1 | get PSW 558 andw #PSL_S,%d1 | from system mode? 559 jne Lkbrkpt | yes, kernel breakpoint 560 jra _ASM_LABEL(fault) | no, user-mode fault 561 562Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type) 563 | Save the system %sp rather than the user %sp. 564 movw #PSL_HIGHIPL,%sr | lock out interrupts 565 lea %sp@(FR_SIZE),%a6 | Save stack pointer 566 movl %a6,%sp@(FR_SP) | from before trap 567 568 | If were are not on tmpstk switch to it. 569 | (so debugger can change the stack pointer) 570 movl %a6,%d1 571 cmpl #_ASM_LABEL(tmpstk),%d1 572 jls Lbrkpt2 | already on tmpstk 573 | Copy frame to the temporary stack 574 movl %sp,%a0 | %a0=src 575 lea _ASM_LABEL(tmpstk)-96,%a1 | %a1=dst 576 movl %a1,%sp | %sp=new frame 577 moveq #FR_SIZE,%d1 578Lbrkpt1: 579 movl %a0@+,%a1@+ 580 subql #4,%d1 581 bgt Lbrkpt1 582 583Lbrkpt2: 584 | Call the trap handler for the kernel debugger. 585 | Do not call trap() to do it, so that we can 586 | set breakpoints in trap() if we want. We know 587 | the trap type is either T_TRACE or T_BREAKPOINT. 588 | If we have both DDB and KGDB, let KGDB see it first, 589 | because KGDB will just return 0 if not connected. 590 | Save args in %d2, %a2 591 movl %d0,%d2 | trap type 592 movl %sp,%a2 | frame ptr 593#ifdef KGDB 594 | Let KGDB handle it (if connected) 595 movl %a2,%sp@- | push frame ptr 596 movl %d2,%sp@- | push trap type 597 jbsr _C_LABEL(kgdb_trap) | handle the trap 598 addql #8,%sp | pop args 599 cmpl #0,%d0 | did kgdb handle it? 600 jne Lbrkpt3 | yes, done 601#endif 602#ifdef DDB 603 | Let DDB handle it 604 movl %a2,%sp@- | push frame ptr 605 movl %d2,%sp@- | push trap type 606 jbsr _C_LABEL(kdb_trap) | handle the trap 607 addql #8,%sp | pop args 608#if 0 /* not needed on hp300 */ 609 cmpl #0,%d0 | did ddb handle it? 610 jne Lbrkpt3 | yes, done 611#endif 612#endif 613 /* Sun 3 drops into PROM here. */ 614Lbrkpt3: 615 | The stack pointer may have been modified, or 616 | data below it modified (by kgdb push call), 617 | so push the hardware frame at the current %sp 618 | before restoring registers and returning. 619 620 movl %sp@(FR_SP),%a0 | modified %sp 621 lea %sp@(FR_SIZE),%a1 | end of our frame 622 movl %a1@-,%a0@- | copy 2 longs with 623 movl %a1@-,%a0@- | ... predecrement 624 movl %a0,%sp@(FR_SP) | %sp = h/w frame 625 moveml %sp@+,#0x7FFF | restore all but %sp 626 movl %sp@,%sp | ... and %sp 627 rte | all done 628 629/* 630 * Interrupt handlers. 631 * 632 * For auto-vectored interrupts, the CPU provides the 633 * vector 0x18+level. Note we count spurious interrupts, 634 * but don't do anything else with them. 635 * 636 * intrhand_autovec is the entry point for auto-vectored 637 * interrupts. 638 * 639 * For vectored interrupts, we pull the pc, evec, and exception frame 640 * and pass them to the vectored interrupt dispatcher. The vectored 641 * interrupt dispatcher will deal with strays. 642 */ 643 644ENTRY_NOPROFILE(lev7intr) /* level 7: parity errors, reset key */ 645 addql #1,_C_LABEL(m68k_intr_evcnt)+NMI_INTRCNT 646 clrl %sp@- 647 moveml #0xFFFF,%sp@- | save registers 648 movl %usp,%a0 | and save 649 movl %a0,%sp@(FR_SP) | the user stack pointer 650 jbsr _C_LABEL(nmihand) | call handler 651 movl %sp@(FR_SP),%a0 | restore 652 movl %a0,%usp | user SP 653 moveml %sp@+,#0x7FFF | and remaining registers 654 addql #8,%sp | pop SP and stack adjust 655 jra _ASM_LABEL(rei) | all done 656 657/* 658 * Emulation of VAX REI instruction. 659 * 660 * This code deals with checking for and servicing ASTs 661 * (profiling, scheduling) and software interrupts (network, softclock). 662 * We check for ASTs first, just like the VAX. To avoid excess overhead 663 * the T_ASTFLT handling code will also check for software interrupts so we 664 * do not have to do it here. After identifying that we need an AST we 665 * drop the IPL to allow device interrupts. 666 * 667 * This code is complicated by the fact that sendsig may have been called 668 * necessitating a stack cleanup. 669 */ 670 671ASENTRY_NOPROFILE(rei) 672 tstl _C_LABEL(astpending) | AST pending? 673 jne 1f | no, done 674 rte 6751: 676 btst #5,%sp@ | yes, are we returning to user mode? 677 jeq 2f | no, done 678 rte 6792: 680 movw #PSL_LOWIPL,%sr | lower SPL 681 clrl %sp@- | stack adjust 682 moveml #0xFFFF,%sp@- | save all registers 683 movl %usp,%a1 | including 684 movl %a1,%sp@(FR_SP) | the users SP 685Lrei: 686 clrl %sp@- | VA == none 687 clrl %sp@- | code == none 688 movl #T_ASTFLT,%sp@- | type == async system trap 689 pea %sp@(12) | fp == address of trap frame 690 jbsr _C_LABEL(trap) | go handle it 691 lea %sp@(16),%sp | pop value args 692 movl %sp@(FR_SP),%a0 | restore user SP 693 movl %a0,%usp | from save area 694 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 695 jne Laststkadj | yes, go to it 696 moveml %sp@+,#0x7FFF | no, restore most user regs 697 addql #8,%sp | toss SP and stack adjust 698 rte | and do real RTE 699Laststkadj: 700 lea %sp@(FR_HW),%a1 | pointer to HW frame 701 addql #8,%a1 | source pointer 702 movl %a1,%a0 | source 703 addw %d0,%a0 | + hole size = dest pointer 704 movl %a1@-,%a0@- | copy 705 movl %a1@-,%a0@- | 8 bytes 706 movl %a0,%sp@(FR_SP) | new SSP 707 moveml %sp@+,#0x7FFF | restore user registers 708 movl %sp@,%sp | and our SP 709 rte | and do real RTE 710 711/* 712 * Primitives 713 */ 714 715/* 716 * Use common m68k process/lwp switch and context save subroutines. 717 */ 718#define FPCOPROC /* XXX: Temp. Reqd. */ 719#include <m68k/m68k/switch_subr.s> 720 721 722#if defined(M68040) 723ENTRY(suline) 724 movl %sp@(4),%a0 | address to write 725 movl _C_LABEL(curpcb),%a1 | current pcb 726 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 727 movl %sp@(8),%a1 | address of line 728 movl %a1@+,%d0 | get lword 729 movsl %d0,%a0@+ | put lword 730 nop | sync 731 movl %a1@+,%d0 | get lword 732 movsl %d0,%a0@+ | put lword 733 nop | sync 734 movl %a1@+,%d0 | get lword 735 movsl %d0,%a0@+ | put lword 736 nop | sync 737 movl %a1@+,%d0 | get lword 738 movsl %d0,%a0@+ | put lword 739 nop | sync 740 moveq #0,%d0 | indicate no fault 741 jra Lsldone 742Lslerr: 743 moveq #-1,%d0 744Lsldone: 745 movl _C_LABEL(curpcb),%a1 | current pcb 746 clrl %a1@(PCB_ONFAULT) | clear fault address 747 rts 748#endif 749 750/* 751 * _delay(u_int N) 752 * 753 * Delay for at least (N/256) microseconds. 754 * This routine depends on the variable: delay_divisor 755 * which should be set based on the CPU clock rate. 756 */ 757ENTRY_NOPROFILE(_delay) 758 | %d0 = arg = (usecs << 8) 759 movl %sp@(4),%d0 760 | %d1 = delay_divisor 761 movl _C_LABEL(delay_divisor),%d1 762 jra L_delay /* Jump into the loop! */ 763 764 /* 765 * Align the branch target of the loop to a half-line (8-byte) 766 * boundary to minimize cache effects. This guarantees both 767 * that there will be no prefetch stalls due to cache line burst 768 * operations and that the loop will run from a single cache 769 * half-line. 770 */ 771 .align 8 772L_delay: 773 subl %d1,%d0 774 jgt L_delay 775 rts 776 777/* 778 * Handle the nitty-gritty of rebooting the machine. 779 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 780 * Note that we must be running in an address range that is mapped one-to-one 781 * logical to physical so that the PC is still valid immediately after the MMU 782 * is turned off. We have conveniently mapped the last page of physical 783 * memory this way. 784 */ 785ENTRY_NOPROFILE(doboot) 786 movw #PSL_HIGHIPL,%sr | no interrupts 787 788 movl #CACHE_OFF,%d0 789 movc %d0,%cacr | clear and disable on-chip cache(s) 790 791 | Turn on physical memory mapping. 792 | @@@ This is also 68040 specific and needs fixing. 793 movel #0x0200c040,%d0 | intio devices are at 0x02000000 794 .long 0x4e7b0004 | movc %d0,%itt0 795 .long 0x4e7b0006 | movc %d0,%dtt0 796 movel #0x0403c000,%d0 | kernel text and data at 0x04000000 797 .long 0x4e7b0005 | movc %d0,%itt1 798 .long 0x4e7b0007 | movc %d0,%dtt1 799 800 moveal #NEXT_RAMBASE,%a5 | amount to RELOC by. 801 802 | Create a new stack at address tmpstk, and push 803 | The existing sp onto it for kicks. 804 ASRELOC(tmpstk, %a0) 805 movel %sp,%a0@- 806 moveal %a0,%sp 807 moveal #0,%a6 808 809 ASRELOC(Ldoboot1, %a0) 810 jmp %a0@ | jump into physical address space. 811Ldoboot1: 812 RELOC(saved_vbr, %a0) 813 movl %a0@,%d0 814 movc %d0,%vbr 815 816 | reset the registers as the boot rom likes them: 817 movel #0x0200c040,%d0 | 818 .long 0x4e7b0004 | movc %d0,%itt0 819 .long 0x4e7b0006 | movc %d0,%dtt0 820 movel #0x00ffc000,%d0 | 821 .long 0x4e7b0005 | movc %d0,%itt1 822 .long 0x4e7b0007 | movc %d0,%dtt1 823 824 RELOC(monbootflag, %a0) 825 movel %a0,%d0 | "-h" halts instead of reboot. 826 trap #13 827 828hloop: 829 bra hloop | This shouldn't be reached. 830/* 831 * Misc. global variables. 832 */ 833 .data 834GLOBAL(machineid) 835 .long 0xdeadbeef | default to @@@ 836 837GLOBAL(mmuid) 838 .long 0 | default to nothing 839 840GLOBAL(mmutype) 841 .long 0xdeadbeef | default to 68040 mmu 842 843GLOBAL(cputype) 844 .long 0xdeadbeef | default to 68020 CPU 845 846GLOBAL(fputype) 847 .long 0xdeadbeef | default to 68882 FPU 848 849GLOBAL(prototc) 850 .long 0 | prototype translation control 851 852GLOBAL(intiobase) 853 .long INTIOBASE | KVA of base of internal IO space 854 855GLOBAL(intiolimit) 856 .long INTIOTOP | KVA of end of internal IO space 857 858GLOBAL(fbbase) 859 .long 0 | KVA of base of framebuffer 860 861GLOBAL(fblimit) 862 .long 0 | KVA of end of framebuffer 863 864GLOBAL(fbbasepa) 865 .long MONOBASE | PA of base of framebuffer 866 867GLOBAL(fblimitpa) 868 .long MONOTOP | PA of end of framebuffer 869 870GLOBAL(monbootflag) 871 .long 0 872 873#ifdef USELEDS 874ASLOCAL(heartbeat) 875 .long 0 | clock ticks since last pulse of heartbeat 876 877ASLOCAL(beatstatus) 878 .long 0 | for determining a fast or slow throb 879#endif 880 881#ifdef DEBUG 882ASGLOBAL(fulltflush) 883 .long 0 884 885ASGLOBAL(fullcflush) 886 .long 0 887#endif 888