1/* $NetBSD: locore.s,v 1.89 2002/11/02 20:03:04 chs 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. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: locore.s 1.58 91/04/22$ 41 * 42 * @(#)locore.s 7.11 (Berkeley) 5/9/91 43 */ 44 45/* 46 * 47 * Original (hp300) Author: unknown, maybe Mike Hibler? 48 * Amiga author: Markus Wild 49 * Atari Modifications: Leo Weppelman 50 */ 51 52#include "opt_compat_netbsd.h" 53#include "opt_compat_svr4.h" 54#include "opt_compat_sunos.h" 55#include "opt_ddb.h" 56#include "opt_fpsp.h" 57#include "opt_kgdb.h" 58#include "opt_lockdebug.h" 59#include "opt_mbtype.h" 60#include "kbd.h" 61#include "ncrscsi.h" 62#include "zs.h" 63 64#include "assym.h" 65#include <machine/asm.h> 66 67/* 68 * This is for kvm_mkdb, and should be the address of the beginning 69 * of the kernel text segment (not necessarily the same as kernbase). 70 */ 71 .text 72 GLOBAL(kernel_text) 73 74/* 75 * Clear & skip page zero, it will not be mapped 76 */ 77 .fill NBPG/4,4,0 78 79#include <atari/atari/vectors.s> 80 81 .text 82 .even 83/* 84 * Do a dump. 85 * Called by auto-restart. 86 */ 87ENTRY_NOPROFILE(doadump) 88 jbsr _C_LABEL(dumpsys) 89 jbsr _C_LABEL(doboot) 90 /*NOTREACHED*/ 91 92/* 93 * Trap/interrupt vector routines 94 */ 95#include <m68k/m68k/trap_subr.s> 96 97#if defined(M68040) || defined(M68060) 98ENTRY_NOPROFILE(addrerr4060) 99 clrl %sp@- | stack adjust count 100 moveml #0xFFFF,%sp@- | save user registers 101 movl %usp,%a0 | save the user SP 102 movl %a0,%sp@(FR_SP) | in the savearea 103 movl %sp@(FR_HW+8),%sp@- 104 clrl %sp@- | dummy code 105 movl #T_ADDRERR,%sp@- | mark address error 106 jra _ASM_LABEL(faultstkadj) | and deal with it 107#endif /* defined(M68040) || defined(M68060) */ 108 109#if defined(M68060) 110ENTRY_NOPROFILE(buserr60) 111 clrl %sp@- | stack adjust count 112 moveml #0xFFFF,%sp@- | save user registers 113 movl %usp,%a0 | save the user SP 114 movl %a0,%sp@(FR_SP) | in the savearea 115 movel %sp@(FR_HW+12),%d0 | FSLW 116 btst #2,%d0 | branch prediction error? 117 jeq Lnobpe 118 movc %cacr,%d2 119 orl #IC60_CABC,%d2 | clear all branch cache entries 120 movc %d2,%cacr 121 movl %d0,%d1 122 addql #1,L60bpe 123 andl #0x7ffd,%d1 124 jeq _ASM_LABEL(faultstkadjnotrap2) 125Lnobpe: 126| we need to adjust for misaligned addresses 127 movl %sp@(FR_HW+8),%d1 | grab VA 128 btst #27,%d0 | check for mis-aligned access 129 jeq Lberr3 | no, skip 130 addl #28,%d1 | yes, get into next page 131 | operand case: 3, 132 | instruction case: 4+12+12 133 andl #PG_FRAME,%d1 | and truncate 134Lberr3: 135 movl %d1,%sp@- 136 movl %d0,%sp@- | code is FSLW now. 137 andw #0x1f80,%d0 138 jeq Lisberr 139 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 140 jra _ASM_LABEL(faultstkadj) | and deal with it 141#endif /* defined(M68060) */ 142 143#if defined(M68040) 144ENTRY_NOPROFILE(buserr40) 145 clrl %sp@- | stack adjust count 146 moveml #0xFFFF,%sp@- | save user registers 147 movl %usp,%a0 | save the user SP 148 movl %a0,%sp@(FR_SP) | in the savearea 149 movl %sp@(FR_HW+20),%d1 | get fault address 150 moveq #0,%d0 151 movw %sp@(FR_HW+12),%d0 | get SSW 152 btst #11,%d0 | check for mis-aligned 153 jeq Lbe1stpg | no skip 154 addl #3,%d1 | get into next page 155 andl #PG_FRAME,%d1 | and truncate 156Lbe1stpg: 157 movl %d1,%sp@- | pass fault address. 158 movl %d0,%sp@- | pass SSW as code 159 btst #10,%d0 | test ATC 160 jeq Lisberr | it is a bus error 161 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 162 jra _ASM_LABEL(faultstkadj) | and deal with it 163#endif /* defined(M68040) */ 164 165#if defined(M68020) || defined(M68030) 166ENTRY_NOPROFILE(buserr2030) 167ENTRY_NOPROFILE(addrerr2030) 168 clrl %sp@- | stack adjust count 169 moveml #0xFFFF,%sp@- | save user registers 170 movl %usp,%a0 | save the user SP 171 movl %a0,%sp@(FR_SP) | in the savearea 172 moveq #0,%d0 173 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 174 btst #12,%d0 | RB set? 175 jeq LbeX0 | no, test RC 176 bset #14,%d0 | yes, must set FB 177 movw %d0,%sp@(FR_HW+10) | for hardware too 178LbeX0: 179 btst #13,%d0 | RC set? 180 jeq LbeX1 | no, skip 181 bset #15,%d0 | yes, must set FC 182 movw %d0,%sp@(FR_HW+10) | for hardware too 183LbeX1: 184 btst #8,%d0 | data fault? 185 jeq Lbe0 | no, check for hard cases 186 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 187 jra Lbe10 | thats it 188Lbe0: 189 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 190 jne Lbe4 | yes, go handle 191 movl %sp@(FR_HW+2),%d1 | no, can use save PC 192 btst #14,%d0 | FB set? 193 jeq Lbe3 | no, try FC 194 addql #4,%d1 | yes, adjust address 195 jra Lbe10 | done 196Lbe3: 197 btst #15,%d0 | FC set? 198 jeq Lbe10 | no, done 199 addql #2,%d1 | yes, adjust address 200 jra Lbe10 | done 201Lbe4: 202 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 203 btst #15,%d0 | FC set? 204 jeq Lbe10 | no, all done 205 subql #2,%d1 | yes, adjust address 206Lbe10: 207 movl %d1,%sp@- | push fault VA 208 movl %d0,%sp@- | and padded SSW 209 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 210 andw #0x0FFF,%d0 | clear out frame format 211 cmpw #12,%d0 | address error vector? 212 jeq Lisaerr | yes, go to it 213 movl %d1,%a0 | fault address 214 movl %sp@,%d0 | function code from ssw 215 btst #8,%d0 | data fault? 216 jne Lbe10a 217 movql #1,%d0 | user program access FC 218 | (we do not separate data/program) 219 btst #5,%sp@(FR_HW+8) | supervisor mode? 220 jeq Lbe10a | if no, done 221 movql #5,%d0 | else supervisor program access 222Lbe10a: 223 ptestr %d0,%a0@,#7 | do a table search 224 pmove %psr,%sp@ | save result 225 movb %sp@,%d1 226 btst #2,%d1 | invalid (incl. limit viol. and berr)? 227 jeq Lmightnotbemerr | no -> wp check 228 btst #7,%d1 | is it MMU table berr? 229 jeq Lismerr | no, must be fast 230 jra Lisberr1 | real bus err needs not be fast. 231Lmightnotbemerr: 232 btst #3,%d1 | write protect bit set? 233 jeq Lisberr1 | no: must be bus error 234 movl %sp@,%d0 | ssw into low word of d0 235 andw #0xc0,%d0 | Write protect is set on page: 236 cmpw #0x40,%d0 | was it read cycle? 237 jeq Lisberr1 | yes, was not WPE, must be bus err 238Lismerr: 239 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 240 jra _ASM_LABEL(faultstkadj) | and deal with it 241Lisaerr: 242 movl #T_ADDRERR,%sp@- | mark address error 243 jra _ASM_LABEL(faultstkadj) | and deal with it 244Lisberr1: 245 clrw %sp@ | re-clear pad word 246#endif /* !(defined(M68020) || defined(M68030)) */ 247 248Lisberr: | also used by M68040/60 249 tstl _C_LABEL(nofault) | device probe? 250 jeq LberrIsProbe | no, handle as usual 251 movl _C_LABEL(nofault),%sp@- | yes, 252 jbsr _C_LABEL(longjmp) | longjmp(nofault) 253 /* NOTREACHED */ 254LberrIsProbe: 255 movl #T_BUSERR,%sp@- | mark bus error 256 jra _ASM_LABEL(faultstkadj) | and deal with it 257 258 /* 259 * This is where the default vectors end-up! 260 * At the time of the 'machine-type' probes, it seems necessary 261 * that the 'nofault' test is done first. Because the MMU is not 262 * yet setup at this point, the real fault handlers sometimes 263 * misinterpret the cause of the fault. 264 */ 265ENTRY_NOPROFILE(buserr) 266ENTRY_NOPROFILE(addrerr) 267 tstl _C_LABEL(nofault) | device probe? 268 jeq 1f | no, halt... 269 movl _C_LABEL(nofault),%sp@- | yes, 270 jbsr _C_LABEL(longjmp) | longjmp(nofault) 271 /* NOTREACHED */ 2721: 273 jra _C_LABEL(badtrap) | only catch probes! 274 275/* 276 * FP exceptions. 277 */ 278ENTRY_NOPROFILE(fpfline) 279 cmpl #MMU_68040,_C_LABEL(mmutype) 280 jne fpfline_not40 | not a 040 FPU, do 6888? emulation 281 cmpw #0x202c,%sp@(6) | format type 2? 282 jne _C_LABEL(illinst) | no, not an FP emulation 283#ifdef FPSP 284 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 285#endif 286fpfline_not40: 287 clrl %sp@- | stack adjust count 288 moveml #0xFFFF,%sp@- | save registers 289 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 290 jra _ASM_LABEL(fault) | do it 291 292ENTRY_NOPROFILE(fpunsupp) 293 cmpl #MMU_68040,_C_LABEL(mmutype) 294 jne fpunsupp_not40 | not a 040 FPU, try 6888? 295#ifdef FPSP 296 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 297#endif 298fpunsupp_not40: 299 clrl %sp@- | stack adjust count 300 moveml #0xFFFF,%sp@- | save registers 301 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 302 jra _ASM_LABEL(fault) | do it 303 304/* 305 * Handles all other FP coprocessor exceptions. 306 * Note that since some FP exceptions generate mid-instruction frames 307 * and may cause signal delivery, we need to test for stack adjustment 308 * after the trap call. 309 */ 310ENTRY_NOPROFILE(fpfault) 311 clrl %sp@- | stack adjust count 312 moveml #0xFFFF,%sp@- | save user registers 313 movl %usp,%a0 | and save 314 movl %a0,%sp@(FR_SP) | the user stack pointer 315 clrl %sp@- | no VA arg 316 movl _C_LABEL(curpcb),%a0 | current pcb 317 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 318 fsave %a0@ | save state 319 320#if defined(M68040) || defined(M68060) 321#ifdef notdef /* XXX: Can't use this while we don't have the cputype */ 322 movb _C_LABEL(cputype), %d0 323 andb #(ATARI_68040|ATARI_68060), %d0 324 jne Lfptnull 325#else 326 cmpb #0x41,%a0@ | is it the 68040 FPU-frame format? 327 jeq Lfptnull | yes, safe 328#endif /* notdef */ 329#endif /* defined(M68040) || defined(M68060) */ 330 331 tstb %a0@ | null state frame? 332 jeq Lfptnull | yes, safe 333 clrw %d0 | no, need to tweak BIU 334 movb %a0@(1),%d0 | get frame size 335 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 336Lfptnull: 337 fmovem %fpsr,%sp@- | push fpsr as code argument 338 frestore %a0@ | restore state 339 movl #T_FPERR,%sp@- | push type arg 340 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 341 342/* 343 * Other exceptions only cause four and six word stack frame and require 344 * no post-trap stack adjustment. 345 */ 346 347ENTRY_NOPROFILE(intr_glue) 348 moveml %d0-%d1/%a0-%a1,%sp@- | Save scratch registers 349 jbsr _C_LABEL(intr_dispatch) | handle interrupt 350 moveml %sp@+,%d0-%d1/%a0-%a1 351 jra _ASM_LABEL(rei) 352 353ENTRY_NOPROFILE(lev2intr) 354 rte | HBL, can't be turned off on Falcon! 355 356ENTRY_NOPROFILE(lev4intr) | VBL interrupt 357#ifdef FALCON_VIDEO 358 tstl _C_LABEL(falcon_needs_vbl) 359 jne 1f | Yes, go service a VBL-request 360 rte | Nothing to do. 3611: 362 moveml %d0-%d1/%a0-%a1,%sp@- 363 jbsr _C_LABEL(falcon_display_switch) 364 moveml %sp@+,%d0-%d1/%a0-%a1 365#endif /* FALCON_VIDEO */ 366 rte 367 368ENTRY_NOPROFILE(lev5intr) 369ENTRY_NOPROFILE(lev6intr) 370 371#ifdef _MILANHW_ 372 /* XXX 373 * Need to find better places to define these (Leo) 374 */ 375#define PLX_PCICR 0x4204 376#define PLX_CNTRL 0x42ec 377#define PLX_DMCFGA 0x42ac 378 moveml %d0-%d2/%a0-%a1,%sp@- 379 movw %sp@(20),%sp@- | push previous SR value 380 clrw %sp@- | padded to longword 381 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 382 movew #0xffff,%a0@(PLX_PCICR) | clear PCI_SR error bits 383 movel %a0@(PLX_CNTRL),%d0 | Change PCI command code from 384 andw #0xf0ff,%d0 385 movw %sr,%d2 | Block interrupts for now 386 oriw #0x0700,%sr 387 movl %d0,%a0@(PLX_CNTRL) 388 movq #0,%d1 | clear upper bits 389 | Read any (uncached!) PCI address 390 | to fetch vector number 391 movl _C_LABEL(pci_mem_uncached),%a1 392 movb %a1@,%d1 393 orw #0x0600,%d0 | Change PCI command code back 394 movel %d0,%a0@(PLX_CNTRL) | to Read Cycle 395 movew %d2,%sr | Re-enable interrupts 396 movel %d1,%sp@- | Call handler 397 jbsr _C_LABEL(milan_isa_intr) 398 addql #8,%sp 399 moveml %sp@+,%d0-%d2/%a0-%a1 400 jra _ASM_LABEL(rei) 401 402/* 403 * Support functions for reading and writing the Milan PCI config space. 404 * Of interest: 405 * - We need exclusive access to the PLX9080 during config space 406 * access, hence the splhigh(). 407 * - The 'confread' function shortcircuits the NMI to make probes to 408 * unexplored pci-config space possible. 409 */ 410ENTRY(milan_pci_confread) 411 movl %sp@(4),%d0 | get tag and regno 412 bset #31,%d0 | add config space flag 413 andl #~3,%d0 | access type 0 414 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 415 movw %sr,%d1 | goto splhigh 416 oriw #0x0700,%sr 417 movb #1,_ASM_LABEL(plx_nonmi)| no NMI interrupts please! 418 movl %d0,%a0@(PLX_DMCFGA) | write tag to the config register 419 movl _C_LABEL(pci_io_addr),%a1 420 movl %a1@,%d0 | fetch value 421 movl #0,%a0@(PLX_DMCFGA) | back to normal PCI access 422 423 | Make sure the C-function can peek 424 movw %a0@(PLX_PCICR),_C_LABEL(plx_status) | at the access results. 425 426 movw #0xf900,%a0@(PLX_PCICR) | Clear potential error bits 427 movb #0, _ASM_LABEL(plx_nonmi) 428 movw %d1,%sr | splx 429 rts 430 431ENTRY(milan_pci_confwrite) 432 movl %sp@(4),%d0 | get tag and regno 433 bset #31,%d0 | add config space flag 434 andl #~3,%d0 | access type 0 435 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 436 movw %sr,%d1 | goto splhigh 437 oriw #0x0700,%sr 438 movl %d0,%a0@(PLX_DMCFGA) | write tag to the config register 439 movl _C_LABEL(pci_io_addr),%a1 440 movl %sp@(8),%a1@ | write value 441 movl #0,%a0@(PLX_DMCFGA) | back to normal PCI access 442 movw %d1,%sr | splx 443 rts 444 445ENTRY_NOPROFILE(lev7intr) 446 tstl _ASM_LABEL(plx_nonmi) | milan_conf_read shortcut 447 jne 1f | .... get out immediately 448 moveml %d0-%d1/%a0-%a1,%sp@- 449 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 450 movw %a0@(PLX_PCICR),_C_LABEL(plx_status) 451 movw #0xf900,%a0@(PLX_PCICR) | Clear error bits 452 jbsr _C_LABEL(nmihandler) | notify... 453 moveml %sp@+,%d0-%d1/%a0-%a1 454 addql #1,_C_LABEL(intrcnt)+28 | add another nmi interrupt 4551: 456 rte | all done 457#endif /* _MILANHW_ */ 458 459ENTRY_NOPROFILE(lev3intr) 460ENTRY_NOPROFILE(badtrap) 461 moveml #0xC0C0,%sp@- | save scratch regs 462 movw %sp@(22),%sp@- | push exception vector info 463 clrw %sp@- 464 movl %sp@(22),%sp@- | and PC 465 jbsr _C_LABEL(straytrap) | report 466 addql #8,%sp | pop args 467 moveml %sp@+,#0x0303 | restore regs 468 jra _ASM_LABEL(rei) | all done 469 470ENTRY_NOPROFILE(badmfpint) 471 moveml #0xC0C0,%sp@- | save scratch regs 472 movw %sp@(22),%sp@- | push exception vector info 473 clrw %sp@- 474 movl %sp@(22),%sp@- | and PC 475 jbsr _C_LABEL(straymfpint) | report 476 addql #8,%sp | pop args 477 moveml %sp@+,#0x0303 | restore regs 478 jra _ASM_LABEL(rei) | all done 479 480ENTRY_NOPROFILE(trap0) 481 clrl %sp@- | stack adjust count 482 moveml #0xFFFF,%sp@- | save user registers 483 movl %usp,%a0 | save the user SP 484 movl %a0,%sp@(FR_SP) | in the savearea 485 movl %d0,%sp@- | push syscall number 486 jbsr _C_LABEL(syscall) | handle it 487 addql #4,%sp | pop syscall arg 488 movl %sp@(FR_SP),%a0 | grab and restore 489 movl %a0,%usp | user SP 490 moveml %sp@+,#0x7FFF | restore most registers 491 addql #8,%sp | pop SP and stack adjust 492 jra _ASM_LABEL(rei) | all done 493 494/* 495 * Trap 12 is the entry point for the cachectl "syscall" 496 * cachectl(command, addr, length) 497 * command in d0, addr in a1, length in d1 498 */ 499ENTRY_NOPROFILE(trap12) 500 movl _C_LABEL(curproc),%sp@- | push curproc pointer 501 movl %d1,%sp@- | push length 502 movl %a1,%sp@- | push addr 503 movl %d0,%sp@- | push command 504 jbsr _C_LABEL(cachectl1) | do it 505 lea %sp@(16),%sp | pop args 506 jra _ASM_LABEL(rei) | all done 507 508/* 509 * Trace (single-step) trap. Kernel-mode is special. 510 * User mode traps are simply passed on to trap(). 511 */ 512ENTRY_NOPROFILE(trace) 513 clrl %sp@- | stack adjust count 514 moveml #0xFFFF,%sp@- 515 moveq #T_TRACE,%d0 516 517 | Check PSW and see what happen. 518 | T=0 S=0 (should not happen) 519 | T=1 S=0 trace trap from user mode 520 | T=0 S=1 trace trap on a trap instruction 521 | T=1 S=1 trace trap from system mode (kernel breakpoint) 522 523 movw %sp@(FR_HW),%d1 | get PSW 524 notw %d1 | XXX no support for T0 on 680[234]0 525 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 526 jeq Lkbrkpt | yes, kernel breakpoint 527 jra _ASM_LABEL(fault) | no, user-mode fault 528 529/* 530 * Trap 15 is used for: 531 * - GDB breakpoints (in user programs) 532 * - KGDB breakpoints (in the kernel) 533 * - trace traps for SUN binaries (not fully supported yet) 534 * User mode traps are simply passed to trap(). 535 */ 536ENTRY_NOPROFILE(trap15) 537 clrl %sp@- 538 moveml #0xFFFF,%sp@- 539 moveq #T_TRAP15,%d0 540 movw %sp@(FR_HW),%d1 | get PSW 541 andw #PSL_S,%d1 | from system mode? 542 jne Lkbrkpt | yes, kernel breakpoint 543 jra _ASM_LABEL(fault) | no, user-mode fault 544 545Lkbrkpt: 546 | Kernel-mode breakpoint or trace trap. (d0=trap_type) 547 | Save the system sp rather than the user sp. 548 movw #PSL_HIGHIPL,%sr | lock out interrupts 549 lea %sp@(FR_SIZE),%a6 | Save stack pointer 550 movl %a6,%sp@(FR_SP) | from before trap 551 552 | If were are not on tmpstk switch to it. 553 | (so debugger can change the stack pointer) 554 movl %a6,%d1 555 cmpl #_ASM_LABEL(tmpstk),%d1 556 jls Lbrkpt2 | already on tmpstk 557 | Copy frame to the temporary stack 558 movl %sp,%a0 | a0=src 559 lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst 560 movl %a1,%sp | sp=new frame 561 moveq #FR_SIZE,%d1 562Lbrkpt1: 563 movl %a0@+,%a1@+ 564 subql #4,%d1 565 bgt Lbrkpt1 566 567Lbrkpt2: 568 | Call the trap handler for the kernel debugger. 569 | Do not call trap() to do it, so that we can 570 | set breakpoints in trap() if we want. We know 571 | the trap type is either T_TRACE or T_BREAKPOINT. 572 | If we have both DDB and KGDB, let KGDB see it first, 573 | because KGDB will just return 0 if not connected. 574 | Save args in d2, a2 575 movl %d0,%d2 | trap type 576 movl %sp,%a2 | frame ptr 577#ifdef KGDB 578 | Let KGDB handle it (if connected) 579 movl %a2,%sp@- | push frame ptr 580 movl %d2,%sp@- | push trap type 581 jbsr _C_LABEL(kgdb_trap) | handle the trap 582 addql #8,%sp | pop args 583 cmpl #0,%d0 | did kgdb handle it? 584 jne Lbrkpt3 | yes, done 585#endif 586#ifdef DDB 587 | Let DDB handle it 588 movl %a2,%sp@- | push frame ptr 589 movl %d2,%sp@- | push trap type 590 jbsr _C_LABEL(kdb_trap) | handle the trap 591 addql #8,%sp | pop args 592#if 0 /* not needed on atari */ 593 cmpl #0,%d0 | did ddb handle it? 594 jne Lbrkpt3 | yes, done 595#endif 596#endif 597 /* Sun 3 drops into PROM here. */ 598Lbrkpt3: 599 | The stack pointer may have been modified, or 600 | data below it modified (by kgdb push call), 601 | so push the hardware frame at the current sp 602 | before restoring registers and returning. 603 604 movl %sp@(FR_SP),%a0 | modified sp 605 lea %sp@(FR_SIZE),%a1 | end of our frame 606 movl %a1@-,%a0@- | copy 2 longs with 607 movl %a1@-,%a0@- | ... predecrement 608 movl %a0,%sp@(FR_SP) | sp = h/w frame 609 moveml %sp@+,#0x7FFF | restore all but sp 610 movl %sp@,%sp | ... and sp 611 rte | all done 612 613/* Use common m68k sigreturn */ 614#include <m68k/m68k/sigreturn.s> 615 616/* 617 * Interrupt handlers. 618 * 619 * Level 0: Spurious: ignored. 620 * Level 1: softint 621 * Level 2: HBL 622 * Level 3: not used 623 * Level 4: not used 624 * Level 5: SCC (not used) 625 * Level 6: MFP1/MFP2 (not used -> autovectored) 626 * Level 7: Non-maskable: shouldn't be possible. ignore. 627 */ 628 629/* Provide a generic interrupt dispatcher, only handle hardclock (int6) 630 * specially, to improve performance 631 */ 632 633ENTRY_NOPROFILE(spurintr) 634 addql #1,_C_LABEL(intrcnt)+0 635 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 636 jra _ASM_LABEL(rei) 637 638 /* MFP timer A handler --- System clock --- */ 639ASENTRY_NOPROFILE(mfp_tima) 640 moveml %d0-%d1/%a0-%a1,%sp@- | save scratch registers 641 movl %sp,%sp@- | push pointer to clockframe 642 jbsr _C_LABEL(hardclock) | call generic clock int routine 643 addql #4,%sp | pop params 644 addql #1,_C_LABEL(intrcnt_user)+52 645 | add another system clock interrupt 646 moveml %sp@+,%d0-%d1/%a0-%a1 | restore scratch regs 647 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 648 jra _ASM_LABEL(rei) | all done 649 650#ifdef STATCLOCK 651 /* MFP timer C handler --- Stat/Prof clock --- */ 652ASENTRY_NOPROFILE(mfp_timc) 653 moveml %d0-%d1/%a0-%a1,%sp@- | save scratch registers 654 jbsr _C_LABEL(statintr) | call statistics clock handler 655 addql #1,_C_LABEL(intrcnt)+36 | add another stat clock interrupt 656 moveml %sp@+,%d0-%d1/%a0-%a1 | restore scratch regs 657 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 658 jra _ASM_LABEL(rei) | all done 659#endif /* STATCLOCK */ 660 661#if NKBD > 0 662 /* MFP ACIA handler --- keyboard/midi --- */ 663ASENTRY_NOPROFILE(mfp_kbd) 664 addql #1,_C_LABEL(intrcnt)+8 | add another kbd/mouse interrupt 665 666 moveml %d0-%d1/%a0-%a1,%sp@- | Save scratch registers 667 movw %sp@(16),%sp@- | push previous SR value 668 clrw %sp@- | padded to longword 669 jbsr _C_LABEL(kbdintr) | handle interrupt 670 addql #4,%sp | pop SR 671 moveml %sp@+,%d0-%d1/%a0-%a1 672 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 673 jra _ASM_LABEL(rei) 674#endif /* NKBD */ 675 676#if NNCRSCSI > 0 677 /* MFP2 SCSI DMA handler --- NCR5380 --- */ 678ASENTRY_NOPROFILE(mfp2_5380dm) 679 addql #1,_C_LABEL(intrcnt)+24 | add another 5380-DMA interrupt 680 681 moveml %d0-%d1/%a0-%a1,%sp@- | Save scratch registers 682 movw %sp@(16),%sp@- | push previous SR value 683 clrw %sp@- | padded to longword 684 jbsr _C_LABEL(scsi_dma) | handle interrupt 685 addql #4,%sp | pop SR 686 moveml %sp@+,%d0-%d1/%a0-%a1 687 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 688 jra _ASM_LABEL(rei) 689 690 /* MFP2 SCSI handler --- NCR5380 --- */ 691ASENTRY_NOPROFILE(mfp2_5380) 692 addql #1,_C_LABEL(intrcnt)+20 | add another 5380-SCSI interrupt 693 694 moveml %d0-%d1/%a0-%a1,%sp@- | Save scratch registers 695 movw %sp@(16),%sp@- | push previous SR value 696 clrw %sp@- | padded to longword 697 jbsr _C_LABEL(scsi_ctrl) | handle interrupt 698 addql #4,%sp | pop SR 699 moveml %sp@+,%d0-%d1/%a0-%a1 700 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 701 jra _ASM_LABEL(rei) 702#endif /* NNCRSCSI > 0 */ 703 704#if NZS > 0 705 /* SCC Interrupt --- modem2/serial2 --- */ 706ASENTRY_NOPROFILE(sccint) 707 addql #1,_C_LABEL(intrcnt)+32 | add another SCC interrupt 708 709 moveml %d0-%d1/%a0-%a1,%sp@- | Save scratch registers 710 movw %sp@(16),%sp@- | push previous SR value 711 clrw %sp@- | padded to longword 712 jbsr _C_LABEL(zshard) | handle interrupt 713 addql #4,%sp | pop SR 714 moveml %sp@+,%d0-%d1/%a0-%a1 715 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 716 jra _ASM_LABEL(rei) 717#endif /* NZS > 0 */ 718 719#ifdef _ATARIHW_ 720 /* Level 1 (Software) interrupt handler */ 721ENTRY_NOPROFILE(lev1intr) 722 moveml %d0-%d1/%a0-%a1,%sp@- 723 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 724 moveb #0, %a0@(SCU_SOFTINT) | Turn off software interrupt 725 addql #1,_C_LABEL(intrcnt)+16 | add another software interrupt 726 jbsr _C_LABEL(softint) | handle software interrupts 727 moveml %sp@+,%d0-%d1/%a0-%a1 728 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 729 jra _ASM_LABEL(rei) 730 731 /* 732 * Should never occur, except when special hardware modification 733 * is installed. In this case, one expects to be dropped into 734 * the debugger. 735 */ 736ENTRY_NOPROFILE(lev7intr) 737#ifdef DDB 738 /* 739 * Note that the nmi has to be turned off while handling it because 740 * the hardware modification has no de-bouncing logic.... 741 */ 742 movl %a0, %sp@- | save a0 743 movl _C_LABEL(stio_addr),%a0 | get KVA of ST-IO area 744 movb %a0@(SCU_SYSMASK),%sp@- | save current sysmask 745 movb #0, %a0@(SCU_SYSMASK) | disable all interrupts 746 trap #15 | drop into the debugger 747 movb %sp@+, %a0@(SCU_SYSMASK)| restore sysmask 748 movl %sp@+, %a0 | restore a0 749#endif 750 addql #1,_C_LABEL(intrcnt)+28 | add another nmi interrupt 751 rte | all done 752 753#endif /* _ATARIHW_ */ 754 755 756/* 757 * Emulation of VAX REI instruction. 758 * 759 * This code deals with checking for and servicing ASTs 760 * (profiling, scheduling) and software interrupts (network, softclock). 761 * We check for ASTs first, just like the VAX. To avoid excess overhead 762 * the T_ASTFLT handling code will also check for software interrupts so we 763 * do not have to do it here. After identifing that we need an AST we 764 * drop the IPL to allow device interrupts. 765 * 766 * This code is complicated by the fact that sendsig may have been called 767 * necessitating a stack cleanup. A cleanup should only be needed at this 768 * point for coprocessor mid-instruction frames (type 9), but we also test 769 * for bus error frames (type 10 and 11). 770 */ 771 BSS(ssir,1) 772ASENTRY_NOPROFILE(rei) 773#ifdef DEBUG 774 tstl _C_LABEL(panicstr) | have we paniced? 775 jne Ldorte | yes, do not make matters worse 776#endif 777 tstl _C_LABEL(astpending) | AST pending? 778 jeq Lchksir | no, go check for SIR 779Lrei1: 780 btst #5,%sp@ | yes, are we returning to user mode? 781 jne Lchksir | no, go check for SIR 782 movw #PSL_LOWIPL,%sr | lower SPL 783 clrl %sp@- | stack adjust 784 moveml #0xFFFF,%sp@- | save all registers 785 movl %usp,%a1 | including 786 movl %a1,%sp@(FR_SP) | the users SP 787 clrl %sp@- | VA == none 788 clrl %sp@- | code == none 789 movl #T_ASTFLT,%sp@- | type == async system trap 790 jbsr _C_LABEL(trap) | go handle it 791 lea %sp@(12),%sp | pop value args 792 movl %sp@(FR_SP),%a0 | restore user SP 793 movl %a0,%usp | from save area 794 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 795 jne Laststkadj | yes, go to it 796 moveml %sp@+,#0x7FFF | no, restore most user regs 797 addql #8,%sp | toss SP and stack adjust 798 rte | and do real RTE 799Laststkadj: 800 lea %sp@(FR_HW),%a1 | pointer to HW frame 801 addql #8,%a1 | source pointer 802 movl %a1,%a0 | source 803 addw %d0,%a0 | + hole size = dest pointer 804 movl %a1@-,%a0@- | copy 805 movl %a1@-,%a0@- | 8 bytes 806 movl %a0,%sp@(FR_SP) | new SSP 807 moveml %sp@+,#0x7FFF | restore user registers 808 movl %sp@,%sp | and our SP 809 rte | and do real RTE 810Lchksir: 811 tstb _C_LABEL(ssir) | SIR pending? 812 jeq Ldorte | no, all done 813 movl %d0,%sp@- | need a scratch register 814 movw %sp@(4),%d0 | get SR 815 andw #PSL_IPL7,%d0 | mask all but IPL 816 jne Lnosir | came from interrupt, no can do 817 movl %sp@+,%d0 | restore scratch register 818Lgotsir: 819 movw #SPL1,%sr | prevent others from servicing int 820 tstb _C_LABEL(ssir) | too late? 821 jeq Ldorte | yes, oh well... 822 clrl %sp@- | stack adjust 823 moveml #0xFFFF,%sp@- | save all registers 824 movl %usp,%a1 | including 825 movl %a1,%sp@(FR_SP) | the users SP 826 clrl %sp@- | VA == none 827 clrl %sp@- | code == none 828 movl #T_SSIR,%sp@- | type == software interrupt 829 jbsr _C_LABEL(trap) | go handle it 830 lea %sp@(12),%sp | pop value args 831 movl %sp@(FR_SP),%a0 | restore 832 movl %a0,%usp | user SP 833 moveml %sp@+,#0x7FFF | and all remaining registers 834 addql #8,%sp | pop SP and stack adjust 835 rte 836Lnosir: 837 movl %sp@+,%d0 | restore scratch register 838Ldorte: 839 rte | real return 840 841/* 842 * Initialization 843 * 844 * A5 contains physical load point from boot 845 * exceptions vector thru our table, that's bad.. just hope nothing exceptional 846 * happens till we had time to initialize ourselves.. 847 */ 848 BSS(lowram,4) 849 BSS(esym,4) 850 851 .globl _C_LABEL(edata) 852 .globl _C_LABEL(etext),_C_LABEL(end) 853 854GLOBAL(bootversion) 855 .word 0x0003 | Glues kernel/installboot/loadbsd 856 | and other bootcode together. 857ASENTRY_NOPROFILE(start) 858 movw #PSL_HIGHIPL,%sr | No interrupts 859 860 /* 861 * a0 = start of loaded kernel 862 * a1 = value of esym 863 * d0 = fastmem size 864 * d1 = stmem size 865 * d2 = cputype 866 * d3 = boothowto 867 * d4 = size of loaded kernel 868 */ 869 movl #8,%a5 | Addresses 0-8 are mapped to ROM on the 870 addql #8,%a0 | atari ST. We cannot set these. 871 subl #8,%d4 872 873 /* 874 * Copy until end of kernel relocation code. 875 */ 876Lstart0: 877 movl %a0@+,%a5@+ 878 subl #4, %d4 879 cmpl #Lstart3,%a5 880 jle Lstart0 881 /* 882 * Enter kernel at destination address and continue copy 883 * Make sure that the jump is absolute (by adding ':l') otherwise 884 * the assembler tries to use a pc-relative jump. 885 * Which is definitely not what is needed at this point! 886 */ 887 jmp Lstart2:l 888Lstart2: 889 movl %a0@+,%a5@+ | copy the rest of the kernel 890 subl #4, %d4 891 jcc Lstart2 892Lstart3: 893 894 lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack 895 896 /* 897 * save the passed parameters. `prepass' them on the stack for 898 * later catch by _start_c 899 */ 900 movl %a1,%sp@- | pass address of _esym 901 movl %d1,%sp@- | pass stmem-size 902 movl %d0,%sp@- | pass fastmem-size 903 movl %d5,%sp@- | pass fastmem_start 904 movl %d2,%sp@- | pass machine id 905 movl %d3,_C_LABEL(boothowto) | save reboot flags 906 907 908 /* 909 * Set cputype and mmutype dependent on the machine-id passed 910 * in from the loader. Also make sure that all caches are cleared. 911 */ 912 movl #ATARI_68030,%d1 | 68030 type from loader 913 andl %d2,%d1 914 jeq Ltestfor020 | Not an 68030, try 68020 915 movl #MMU_68030,_C_LABEL(mmutype) | Use 68030 MMU 916 movl #CPU_68030,_C_LABEL(cputype) | and a 68030 CPU 917 movl #CACHE_OFF,%d0 | 68020/030 cache clear 918 jra Lend_cpuset | skip to init. 919Ltestfor020: 920 movl #ATARI_68020,%d1 | 68020 type from loader 921 andl %d2,%d1 922 jeq Ltestfor040 923 movl #MMU_68851,_C_LABEL(mmutype) | Assume 68851 with 68020 924 movl #CPU_68020,_C_LABEL(cputype) | and a 68020 CPU 925 movl #CACHE_OFF,%d0 | 68020/030 cache clear 926 jra Lend_cpuset | skip to init. 927Ltestfor040: 928 movl #CACHE_OFF,%d0 | 68020/030 cache 929 movl #ATARI_68040,%d1 930 andl %d2,%d1 931 jeq Ltestfor060 932 movl #MMU_68040,_C_LABEL(mmutype) | Use a 68040 MMU 933 movl #CPU_68040,_C_LABEL(cputype) | and a 68040 CPU 934 .word 0xf4f8 | cpusha bc - push&inval caches 935 movl #CACHE40_OFF,%d0 | 68040 cache disable 936 jra Lend_cpuset | skip to init. 937Ltestfor060: 938 movl #ATARI_68060,%d1 939 andl %d2,%d1 940 jeq Lend_cpuset 941 movl #MMU_68040,_C_LABEL(mmutype) | Use a 68040 MMU 942 movl #CPU_68060,_C_LABEL(cputype) | and a 68060 CPU 943 .word 0xf4f8 | cpusha bc - push&inval caches 944 movl #CACHE40_OFF,%d0 | 68040 cache disable 945 orl #IC60_CABC,%d0 | and clear 060 branch cache 946 947Lend_cpuset: 948 movc %d0,%cacr | clear and disable on-chip cache(s) 949 movl #_C_LABEL(vectab),%a0 | set address of vector table 950 movc %a0,%vbr 951 952 /* 953 * Initialize source/destination control registers for movs 954 */ 955 moveq #FC_USERD,%d0 | user space 956 movc %d0,%sfc | as source 957 movc %d0,%dfc | and destination of transfers 958 959 /* 960 * let the C function initialize everything and enable the MMU 961 */ 962 jsr _C_LABEL(start_c) 963 964 /* 965 * set kernel stack, user SP, and initial pcb 966 */ 967 movl _C_LABEL(proc0paddr),%a1| proc0 kernel stack 968 lea %a1@(USPACE),%sp | set kernel stack to end of area 969 movl #USRSTACK-4,%a2 970 movl %a2,%usp | init user SP 971 movl %a2,%a1@(PCB_USP) | and save it 972 movl %a1,_C_LABEL(curpcb) | proc0 is running 973 clrw %a1@(PCB_FLAGS) | clear flags 974 975 /* flush TLB and turn on caches */ 976 jbsr _C_LABEL(_TBIA) | invalidate TLB 977 movl #CACHE_ON,%d0 978 cmpl #MMU_68040,_C_LABEL(mmutype) 979 jne Lcacheon 980 /* is this needed? MLH */ 981 .word 0xf4f8 | cpusha bc - push & invalidate caches 982 movl #CACHE40_ON,%d0 983#ifdef M68060 984 cmpl #CPU_68060,_C_LABEL(cputype) 985 jne Lcacheon 986 movl #CACHE60_ON,%d0 987#endif 988Lcacheon: 989 movc %d0,%cacr | clear cache(s) 990 991 /* 992 * Final setup for C code 993 */ 994 movw #PSL_LOWIPL,%sr | lower SPL 995 996#ifdef notdef 997 movl %d6,_C_LABEL(bootdev) | and boot device 998#endif 999 1000 /* 1001 * Create a fake exception frame that returns to user mode, 1002 * make space for the rest of a fake saved register set, and 1003 * pass a pointer to the register set to "main()". 1004 * "main()" will call "icode()", which fakes 1005 * an "execve()" system call, which is why we need to do that 1006 * ("main()" sets "u.u_ar0" to point to the register set). 1007 * When "main()" returns, we're running in process 1 and have 1008 * successfully faked the "execve()". We load up the registers from 1009 * that set; the "rte" loads the PC and PSR, which jumps to "init". 1010 */ 1011 movl #0,%a6 | make DDB stack_trace() work 1012 clrw %sp@- | vector offset/frame type 1013 clrl %sp@- | PC - filled in by "execve" 1014 movw #PSL_USER,%sp@- | in user mode 1015 clrl %sp@- | stack adjust count 1016 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 1017 lea _C_LABEL(proc0),%a0 | proc0 in a0 1018 movl %sp,%a0@(P_MD + MD_REGS)| save frame for proc0 1019 movl %usp,%a1 1020 movl %a1,%sp@(FR_SP) | save user stack pointer in frame 1021 pea %sp@ | addr of space for D0 1022 jbsr _C_LABEL(main) | main(r0) 1023 addql #4,%sp | pop args 1024 cmpl #MMU_68040,_C_LABEL(mmutype) 1025 jne Lnoflush | Not an 68040, skip flush 1026 .word 0xf478 | cpusha dc 1027 .word 0xf498 | cinva ic 1028Lnoflush: 1029 movl %sp@(FR_SP),%a0 | grab and load 1030 movl %a0,%usp | user SP 1031 moveml %sp@+,#0x7FFF | load most registers (all but SSP) 1032 addql #8,%sp | pop SSP and stack adjust count 1033 rte 1034 1035/* 1036 * proc_trampoline call function in register a2 with a3 as an arg 1037 * and then rei. 1038 */ 1039ENTRY_NOPROFILE(proc_trampoline) 1040 movl %a3,%sp@- | push function arg 1041 jbsr %a2@ | call function 1042 addql #4,%sp | pop arg 1043 movl %sp@(FR_SP),%a0 | usp to a0 1044 movl %a0,%usp | setup user stack pointer 1045 moveml %sp@+,#0x7FFF | restore all but sp 1046 addql #8,%sp | pop sp and stack adjust 1047 jra _ASM_LABEL(rei) | all done 1048 1049/* 1050 * Use common m68k sigcode. 1051 */ 1052#include <m68k/m68k/sigcode.s> 1053#ifdef COMPAT_SUNOS 1054#include <m68k/m68k/sunos_sigcode.s> 1055#endif 1056#ifdef COMPAT_SVR4 1057#include <m68k/m68k/svr4_sigcode.s> 1058#endif 1059 1060/* 1061 * Primitives 1062 */ 1063 1064/* 1065 * Use common m68k support routines. 1066 */ 1067#include <m68k/m68k/support.s> 1068 1069/* 1070 * update profiling information for the user 1071 * addupc(pc, &u.u_prof, ticks) 1072 */ 1073ENTRY(addupc) 1074 movl %a2,%sp@- | scratch register 1075 movl %sp@(12),%a2 | get &u.u_prof 1076 movl %sp@(8),%d0 | get user pc 1077 subl %a2@(8),%d0 | pc -= pr->pr_off 1078 jlt Lauexit | less than 0, skip it 1079 movl %a2@(12),%d1 | get pr->pr_scale 1080 lsrl #1,%d0 | pc /= 2 1081 lsrl #1,%d1 | scale /= 2 1082 mulul %d1,%d0 | pc /= scale 1083 moveq #14,%d1 1084 lsrl %d1,%d0 | pc >>= 14 1085 bclr #0,%d0 | pc &= ~1 1086 cmpl %a2@(4),%d0 | too big for buffer? 1087 jge Lauexit | yes, screw it 1088 addl %a2@,%d0 | no, add base 1089 movl %d0,%sp@- | push address 1090 jbsr _C_LABEL(fusword) | grab old value 1091 movl %sp@+,%a0 | grab address back 1092 cmpl #-1,%d0 | access ok 1093 jeq Lauerror | no, skip out 1094 addw %sp@(18),%d0 | add tick to current value 1095 movl %d0,%sp@- | push value 1096 movl %a0,%sp@- | push address 1097 jbsr _C_LABEL(susword) | write back new value 1098 addql #8,%sp | pop params 1099 tstl %d0 | fault? 1100 jeq Lauexit | no, all done 1101Lauerror: 1102 clrl %a2@(12) | clear scale (turn off prof) 1103Lauexit: 1104 movl %sp@+,%a2 | restore scratch reg 1105 rts 1106 1107/* 1108 * non-local gotos 1109 */ 1110ENTRY(qsetjmp) 1111 movl %sp@(4),%a0 | savearea pointer 1112 lea %a0@(40),%a0 | skip regs we do not save 1113 movl %a6,%a0@+ | save FP 1114 movl %sp,%a0@+ | save SP 1115 movl %sp@,%a0@ | and return address 1116 moveq #0,%d0 | return 0 1117 rts 1118 1119 BSS(want_resched,4) 1120 1121/* 1122 * Use common m68k process manipulation routines. 1123 */ 1124#include <m68k/m68k/proc_subr.s> 1125 1126Lsw0: 1127 .asciz "cpu_switch" 1128 .even 1129 1130 .data 1131GLOBAL(masterpaddr) | XXX compatibility (debuggers) 1132GLOBAL(curpcb) 1133 .long 0 1134Lpcbflag: 1135 .byte 0 | copy of pcb_flags low byte 1136 .align 2 1137 ASBSS(nullpcb,SIZEOF_PCB) 1138 .text 1139 1140/* 1141 * At exit of a process, do a switch for the last time. 1142 * Switch to a safe stack and PCB, and select a new process to run. The 1143 * old stack and u-area will be freed by the reaper. 1144 */ 1145ENTRY(switch_exit) 1146 movl %sp@(4),%a0 1147 movl #nullpcb,_C_LABEL(curpcb) | save state into garbage pcb 1148 lea tmpstk,%sp | goto a tmp stack 1149 1150 /* Schedule the vmspace and stack to be freed. */ 1151 movl %a0,%sp@- | exit2(p) 1152 jbsr _C_LABEL(exit2) 1153 lea %sp@(4),%sp | pop args 1154 1155#if defined(LOCKDEBUG) 1156 /* Acquire sched_lock */ 1157 jbsr _C_LABEL(sched_lock_idle) 1158#endif 1159 1160 jra _C_LABEL(cpu_switch) 1161 1162/* 1163 * When no processes are on the runq, Swtch branches to idle 1164 * to wait for something to come ready. 1165 */ 1166ASENTRY_NOPROFILE(Idle) 1167#if defined(LOCKDEBUG) 1168 /* Release sched_lock */ 1169 jbsr _C_LABEL(sched_unlock_idle) 1170#endif 1171 stop #PSL_LOWIPL 1172 movw #PSL_HIGHIPL,%sr 1173#if defined(LOCKDEBUG) 1174 /* Acquire sched_lock */ 1175 jbsr _C_LABEL(sched_lock_idle) 1176#endif 1177 movl _C_LABEL(sched_whichqs),%d0 1178 jeq _ASM_LABEL(Idle) 1179 jra Lsw1 1180 1181Lbadsw: 1182 movl #Lsw0,%sp@- 1183 jbsr _C_LABEL(panic) 1184 /*NOTREACHED*/ 1185 1186/* 1187 * Cpu_switch() 1188 * 1189 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1190 * entire ATC. The effort involved in selective flushing may not be 1191 * worth it, maybe we should just flush the whole thing? 1192 * 1193 * NOTE 2: With the new VM layout we now no longer know if an inactive 1194 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1195 * bit). For now, we just always flush the full ATC. 1196 */ 1197ENTRY(cpu_switch) 1198 movl _C_LABEL(curpcb),%a0 | current pcb 1199 movw %sr,%a0@(PCB_PS) | save sr before changing ipl 1200#ifdef notyet 1201 movl _C_LABEL(curproc),%sp@- | remember last proc running 1202#endif 1203 clrl _C_LABEL(curproc) 1204 1205 /* 1206 * Find the highest-priority queue that isn't empty, 1207 * then take the first proc from that queue. 1208 */ 1209 movl _C_LABEL(sched_whichqs),%d0 1210 jeq _ASM_LABEL(Idle) 1211Lsw1: 1212 /* 1213 * Interrupts are blocked, sched_lock is held. If 1214 * we come here via Idle, %d0 contains the contents 1215 * of a non-zero sched_whichqs. 1216 */ 1217 movl %d0,%d1 1218 negl %d0 1219 andl %d1,%d0 1220 bfffo %d0{#0:#32},%d1 1221 eorib #31,%d1 1222 1223 movl %d1,%d0 1224 lslb #3,%d1 | convert queue number to index 1225 addl #_C_LABEL(sched_qs),%d1 | locate queue (q) 1226 movl %d1,%a1 1227 movl %a1@(P_FORW),%a0 | p = q->p_forw 1228 cmpal %d1,%a0 | anyone on queue? 1229 jeq Lbadsw | no, panic 1230#ifdef DIAGNOSTIC 1231 tstl %a0@(P_WCHAN) 1232 jne Lbadsw 1233 cmpb #SRUN,%a0@(P_STAT) 1234 jne Lbadsw 1235#endif 1236 movl %a0@(P_FORW),%a1@(P_FORW) | q->p_forw = p->p_forw 1237 movl %a0@(P_FORW),%a1 | n = p->p_forw 1238 movl %a0@(P_BACK),%a1@(P_BACK) | n->p_back = q 1239 cmpal %d1,%a1 | anyone left on queue? 1240 jne Lsw2 | yes, skip 1241 movl _C_LABEL(sched_whichqs),%d1 1242 bclr %d0,%d1 | no, clear bit 1243 movl %d1,_C_LABEL(sched_whichqs) 1244Lsw2: 1245 /* p->p_cpu initialized in fork1() for single-processor */ 1246 movb #SONPROC,%a0@(P_STAT) | p->p_stat = SONPROC 1247 movl %a0,_C_LABEL(curproc) 1248 clrl _C_LABEL(want_resched) 1249#ifdef notyet 1250 movl %sp@+,%a1 1251 cmpl %a0,%a1 | switching to same proc? 1252 jeq Lswdone | yes, skip save and restore 1253#endif 1254 1255 /* 1256 * Save state of previous process in its pcb. 1257 */ 1258 movl _C_LABEL(curpcb),%a1 1259 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1260 movl %usp,%a2 | grab USP (a2 has been saved) 1261 movl %a2,%a1@(PCB_USP) | and save it 1262 movl _C_LABEL(CMAP2),%a1@(PCB_CMAP2) | save temporary map PTE 1263 tstl _C_LABEL(fputype) | do we have an FPU? 1264 jeq Lswnofpsave | no? don't attempt to save 1265 lea %a1@(PCB_FPCTX),%a2 | pointer to FP save area 1266 fsave %a2@ | save FP state 1267#ifdef M68060 1268 cmpl #CPU_68060,_C_LABEL(cputype) 1269 jeq Lsavfp60 | It's a 060 1270#endif 1271 tstb %a2@ | null state frame? 1272 jeq Lswnofpsave | yes, all done 1273 fmovem %fp0-%fp7,%a2@(FPF_REGS) | save FP general registers 1274 fmovem %fpcr/%fpsr/%fpi,%a2@(FPF_FPCR) | save FP control registers 1275#ifdef M68060 1276 jra Lswnofpsave 1277Lsavfp60: 1278 tstb %a2@(2) | null state frame? 1279 jeq Lswnofpsave | yes, all done 1280 fmovem %fp0-%fp7,%a2@(FPF_REGS) | save FP general registers 1281 fmovem %fpcr,%a2@(FPF_FPCR) | save FP control registers 1282 fmovem %fpsr,%a2@(FPF_FPSR) 1283 fmovem %fpi,%a2@(FPF_FPI) 1284#endif 1285Lswnofpsave: 1286 1287 clrl %a0@(P_BACK) | clear back link 1288 movl %a0@(P_ADDR),%a1 | get p_addr 1289 movl %a1,_C_LABEL(curpcb) 1290 movb %a1@(PCB_FLAGS+1),Lpcbflag | copy of pcb_flags low byte 1291 1292#if defined(LOCKDEBUG) 1293 /* 1294 * Done mucking with the run queues, release the 1295 * scheduler lock, but keep interrupts out. 1296 */ 1297 movl %a0,sp@- | not args... 1298 movl %a1,sp@- | ...just saving 1299 jbsr _C_LABEL(sched_unlock_idle) 1300 movl sp@+,%a1 1301 movl sp@+,%a0 1302#endif 1303 1304 /* 1305 * Activate process's address space. 1306 * XXX Should remember the last USTP value loaded, and call this 1307 * XXX only if it has changed. 1308 */ 1309 pea %a0@ | push proc 1310 jbsr _C_LABEL(pmap_activate) | pmap_activate(p) 1311 addql #4,%sp 1312 movl _C_LABEL(curpcb),%a1 | restore p_addr 1313 1314 lea _ASM_LABEL(tmpstk),%sp | now goto a tmp stack for NMI 1315 1316 movl %a1@(PCB_CMAP2),_C_LABEL(CMAP2) | reload tmp map 1317 moveml %a1@(PCB_REGS),#0xFCFC | and registers 1318 movl %a1@(PCB_USP),%a0 1319 movl %a0,%usp | and USP 1320 tstl _C_LABEL(fputype) | do we have an FPU? 1321 jeq Lnofprest | no, don't attempt to restore 1322 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1323#ifdef M68060 1324 cmpl #CPU_68060,_C_LABEL(cputype) 1325 jeq Lresfp60rest1 | handle a 060 1326#endif 1327 tstb %a0@ | null state frame? 1328 jeq Lresfprest | yes, easy 1329 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1330 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1331Lresfprest: 1332 frestore %a0@ | restore state 1333 1334Lnofprest: 1335 movw %a1@(PCB_PS),%sr | no, restore PS 1336 moveq #1,%d0 | return 1 (for alternate returns) 1337 rts 1338 1339#ifdef M68060 1340Lresfp60rest1: 1341 tstb %a0@(2) | null state frame? 1342 jeq Lresfp60rest2 | yes, easy 1343 fmovem %a0@(FPF_FPCR),%fpcr | restore FP control registers 1344 fmovem %a0@(FPF_FPSR),%fpsr 1345 fmovem %a0@(FPF_FPI),%fpi 1346 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1347Lresfp60rest2: 1348 frestore %a0@ | restore state 1349 movw %a1@(PCB_PS),%sr | no, restore PS 1350 moveq #1,%d0 | return 1 (for alternate returns) 1351 rts 1352#endif 1353 1354/* 1355 * savectx(pcb) 1356 * Update pcb, saving current processor state 1357 */ 1358ENTRY(savectx) 1359 movl %sp@(4),%a1 1360 movw %sr,%a1@(PCB_PS) 1361 movl %usp,%a0 | grab USP 1362 movl %a0,%a1@(PCB_USP) | and save it 1363 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1364 movl _C_LABEL(CMAP2),%a1@(PCB_CMAP2) | save temporary map PTE 1365 tstl _C_LABEL(fputype) | do we have an FPU? 1366 jeq Lsavedone | no, don't attempt to save 1367 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1368 fsave %a0@ | save FP state 1369#ifdef M68060 1370 cmpl #CPU_68060,_C_LABEL(cputype) 1371 jeq Lsavctx60 | handle a 060 1372#endif 1373 tstb %a0@ | null state frame? 1374 jeq Lsavedone | yes, all done 1375 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1376 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1377Lsavedone: 1378 moveq #0,%d0 | return 0 1379 rts 1380 1381#ifdef M68060 1382Lsavctx60: 1383 tstb %a0@(2) 1384 jeq Lsavedone 1385 fmovem %fp0-%fp7,%a0@(FPF_REGS)| save FP general registers 1386 fmovem %fpcr,%a0@(FPF_FPCR) | save FP control registers 1387 fmovem %fpsr,%a0@(FPF_FPSR) 1388 fmovem %fpi,%a0@(FPF_FPI) 1389 moveq #0,%d0 | return 0 1390 rts 1391#endif 1392 1393#if defined(M68040) 1394ENTRY(suline) 1395 movl %sp@(4),%a0 | address to write 1396 movl _C_LABEL(curpcb),%a1 | current pcb 1397 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 1398 movl %sp@(8),%a1 | address of line 1399 movl %a1@+,%d0 | get lword 1400 movsl %d0,%a0@+ | put lword 1401 nop | sync 1402 movl %a1@+,%d0 | get lword 1403 movsl %d0,%a0@+ | put lword 1404 nop | sync 1405 movl %a1@+,%d0 | get lword 1406 movsl %d0,%a0@+ | put lword 1407 nop | sync 1408 movl %a1@+,%d0 | get lword 1409 movsl %d0,%a0@+ | put lword 1410 nop | sync 1411 moveq #0,%d0 | indicate no fault 1412 jra Lsldone 1413Lslerr: 1414 moveq #-1,%d0 1415Lsldone: 1416 movl _C_LABEL(curpcb),%a1 | current pcb 1417 clrl %a1@(PCB_ONFAULT) | clear fault address 1418 rts 1419#endif /* defined(M68040) */ 1420 1421ENTRY(ecacheon) 1422 rts 1423 1424ENTRY(ecacheoff) 1425 rts 1426 1427/* 1428 * Get callers current SP value. 1429 * Note that simply taking the address of a local variable in a C function 1430 * doesn't work because callee saved registers may be outside the stack frame 1431 * defined by A6 (e.g. GCC generated code). 1432 */ 1433ENTRY_NOPROFILE(getsp) 1434 movl %sp,%d0 | get current SP 1435 addql #4,%d0 | compensate for return address 1436 rts 1437 1438ENTRY_NOPROFILE(getsfc) 1439 movc %sfc,%d0 1440 rts 1441ENTRY_NOPROFILE(getdfc) 1442 movc %dfc,%d0 1443 rts 1444 1445/* 1446 * Check out a virtual address to see if it's okay to write to. 1447 * 1448 * probeva(va, fc) 1449 * 1450 */ 1451ENTRY(probeva) 1452 movl %sp@(8),%d0 1453 movec %d0,%dfc 1454 movl %sp@(4),%a0 1455 .word 0xf548 | ptestw (a0) 1456 moveq #FC_USERD,%d0 | restore DFC to user space 1457 movc %d0,%dfc 1458 .word 0x4e7a,0x0805 | movec MMUSR,d0 1459 rts 1460 1461/* 1462 * Load a new user segment table pointer. 1463 */ 1464ENTRY(loadustp) 1465 movl %sp@(4),%d0 | new USTP 1466 moveq #PGSHIFT,%d1 1467 lsll %d1,%d0 | convert to addr 1468#if defined(M68060) 1469 cmpl #CPU_68060,_C_LABEL(cputype) | 68060? 1470 jeq Lldustp060 | yes, skip 1471#endif 1472 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1473 jeq Lldustp040 | yes, skip 1474 pflusha | flush entire TLB 1475 lea _C_LABEL(protorp),%a0 | CRP prototype 1476 movl %d0,%a0@(4) | stash USTP 1477 pmove %a0@,%crp | load root pointer 1478 movl #CACHE_CLR,%d0 1479 movc %d0,%cacr | invalidate on-chip d-cache 1480 rts 1481#if defined(M68060) 1482Lldustp060: 1483 movc %cacr,%d1 1484 orl #IC60_CUBC,%d1 | clear user branch cache entries 1485 movc %d1,%cacr 1486#endif 1487Lldustp040: 1488 .word 0xf518 | pflusha 1489 .word 0x4e7b,0x0806 | movec d0,URP 1490 rts 1491 1492/* 1493 * Flush any hardware context associated with given USTP. 1494 * Only does something for HP330 where we must flush RPT 1495 * and ATC entries in PMMU. 1496 */ 1497ENTRY(flushustp) 1498#if defined(M68060) 1499 cmpl #CPU_68060,_C_LABEL(cputype) 1500 jeq Lflustp060 | A 060 needs special treatment 1501#endif 1502 cmpl #MMU_68040,_C_LABEL(mmutype) 1503 jeq Lnot68851 1504 tstl _C_LABEL(mmutype) | 68851 PMMU? 1505 jle Lnot68851 | no, nothing to do 1506 movl %sp@(4),%d0 | get USTP to flush 1507 moveq #PGSHIFT,%d1 1508 lsll %d1,%d0 | convert to address 1509 movl %d0,_C_LABEL(protorp)+4 | stash USTP 1510 pflushr _C_LABEL(protorp) | flush RPT/TLB entries 1511Lnot68851: 1512 rts 1513#if defined(M68060) 1514Lflustp060: 1515 movc %cacr,%d1 1516 orl IC60_CUBC,%d1 | clear user branch cache entries 1517 movc %d1,%cacr 1518 rts 1519#endif 1520 1521ENTRY(ploadw) 1522 movl %sp@(4),%a0 | address to load 1523 cmpl #MMU_68040,_C_LABEL(mmutype) 1524 jeq Lploadw040 1525 ploadw #1,%a0@ | pre-load translation 1526Lploadw040: | should 68040 do a ptest? 1527 rts 1528 1529/* 1530 * Set processor priority level calls. Most are implemented with 1531 * inline asm expansions. However, spl0 requires special handling 1532 * as we need to check for our emulated software interrupts. 1533 */ 1534 1535ENTRY(spl0) 1536 moveq #0,%d0 1537 movw %sr,%d0 | get old SR for return 1538 movw #PSL_LOWIPL,%sr | restore new SR 1539 tstb _C_LABEL(ssir) | software interrupt pending? 1540 jeq Lspldone | no, all done 1541 subql #4,%sp | make room for RTE frame 1542 movl %sp@(4),%sp@(2) | position return address 1543 clrw %sp@(6) | set frame type 0 1544 movw #PSL_LOWIPL,%sp@ | and new SR 1545 jra Lgotsir | go handle it 1546Lspldone: 1547 rts 1548 1549/* 1550 * Save and restore 68881 state. 1551 * Pretty awful looking since our assembler does not 1552 * recognize FP mnemonics. 1553 */ 1554ENTRY(m68881_save) 1555 movl %sp@(4),%a0 | save area pointer 1556 fsave %a0@ | save state 1557#if defined(M68060) 1558 cmpl #CPU_68060,_C_LABEL(cputype) 1559 jeq Lm68060fpsave | Handle 060 fpu 1560#endif 1561 tstb %a0@ | null state frame? 1562 jeq Lm68881sdone | yes, all done 1563 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1564 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1565Lm68881sdone: 1566 rts 1567 1568#if defined(M68060) 1569Lm68060fpsave: 1570 tstb %a0@(2) | null state frame? 1571 jeq Lm68060sdone | yes, all done 1572 fmovem %fp0-%fp7,%a0@(FPF_REGS)| save FP general registers 1573 fmovem %fpcr,%a0@(FPF_FPCR) | save FP control registers 1574 fmovem %fpsr,%a0@(FPF_FPSR) 1575 fmovem %fpi,%a0@(FPF_FPI) 1576Lm68060sdone: 1577 rts 1578#endif 1579 1580ENTRY(m68881_restore) 1581 movl %sp@(4),%a0 | save area pointer 1582#if defined(M68060) 1583 cmpl #CPU_68060,_C_LABEL(cputype) 1584 jeq Lm68060fprestore | a 060 fpu 1585#endif 1586 tstb %a0@ | null state frame? 1587 jeq Lm68881rdone | yes, easy 1588 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1589 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1590Lm68881rdone: 1591 frestore %a0@ | restore state 1592 rts 1593 1594#if defined(M68060) 1595Lm68060fprestore: 1596 tstb %a0@(2) | null state frame? 1597 jeq Lm68060fprdone | yes, easy 1598 fmovem %a0@(FPF_FPCR),%fpcr | restore FP control registers 1599 fmovem %a0@(FPF_FPSR),%fpsr 1600 fmovem %a0@(FPF_FPI),%fpi 1601 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1602Lm68060fprdone: 1603 frestore %a0@ | restore state 1604 rts 1605#endif 1606 1607/* 1608 * Handle the nitty-gritty of rebooting the machine. 1609 * 1610 */ 1611ENTRY_NOPROFILE(doboot) 1612 movl #CACHE_OFF,%d0 1613 cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040? 1614 jne Ldoboot0 1615 .word 0xf4f8 | cpusha bc - push and inval caches 1616 nop 1617 movl #CACHE40_OFF,%d0 1618Ldoboot0: 1619 movc %d0,%cacr | disable on-chip cache(s) 1620 1621 movw #0x2700,%sr | cut off any interrupts 1622 1623 /* 1624 * Clear first 2k of ST-memory. We start clearing at address 0x8 1625 * because the lower 8 bytes are mapped to ROM. 1626 * This makes sure that the machine will 'cold-boot'. 1627 */ 1628 movl _C_LABEL(page_zero),%a0 1629 addl #0x8,%a0 1630 movl #512,%d0 1631Ldb1: 1632 clrl %a0@+ 1633 dbra %d0,Ldb1 1634 1635 lea Ldoreboot,%a1 | a1 = start of copy range 1636 lea Ldorebootend,%a2 | a2 = end of copy range 1637 movl _C_LABEL(page_zero),%a0 | a0 = virtual base for page zero 1638 addl %a1,%a0 | + offset of Ldoreboot 1639Ldb2: | Do the copy 1640 movl %a1@+,%a0@+ 1641 cmpl %a2,%a1 1642 jle Ldb2 1643 1644 /* 1645 * Ok, turn off MMU.. 1646 */ 1647Ldoreboot: 1648 cmpl #MMU_68040,_C_LABEL(mmutype) 1649 jeq Lmmuoff040 | Go turn off 68040 MMU 1650 lea _ASM_LABEL(zero),%a0 1651 pmove %a0@,%tc | Turn off MMU 1652 lea _ASM_LABEL(nullrp),%a0 1653 pmove %a0@,%crp | Invalidate Cpu root pointer 1654 pmove %a0@,%srp | and the Supervisor root pointer 1655 jra Ldoboot1 | Ok, continue with actual reboot 1656Lmmuoff040: 1657 movl #0,%d0 1658 .word 0x4e7b,0x0003 | movc d0,TC 1659 .word 0x4e7b,0x0806 | movc d0,URP 1660 .word 0x4e7b,0x0807 | movc d0,SRP 1661 1662Ldoboot1: 1663 movl #0, %a0 1664 movc %a0,%vbr 1665 movl %a0@(4), %a0 | fetch reset-vector 1666 jmp %a0@ | jump through it 1667 /* NOTREACHED */ 1668 1669/* A do-nothing MMU root pointer (includes the following long as well) */ 1670 1671ASLOCAL(nullrp) 1672 .long 0x7fff0001 1673ASLOCAL(zero) 1674 .long 0 1675Ldorebootend: 1676 1677 .data 1678 .space NBPG 1679ASLOCAL(tmpstk) 1680GLOBAL(protorp) 1681 .long 0x80000002,0 | prototype root pointer 1682 1683GLOBAL(proc0paddr) 1684 .long 0 | KVA of proc0 u-area 1685#ifdef M68060 /* XXX */ 1686L60iem: .long 0 1687L60fpiem: .long 0 1688L60fpdem: .long 0 1689L60fpeaem: .long 0 1690L60bpe: .long 0 1691#endif 1692#ifdef DEBUG 1693 1694ASLOCAL(fulltflush) 1695 .long 0 1696ASLOCAL(fullcflush) 1697 .long 0 1698GLOBAL(timebomb) 1699 .long 0 1700#endif 1701ASLOCAL(plx_nonmi) 1702 .long 0 1703GLOBAL(plx_status) 1704 .long 0 1705 1706/* interrupt counters & names */ 1707#include <atari/atari/intrcnt.h> 1708