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