1/* $NetBSD: locore.s,v 1.6 2002/11/02 20:03:05 chs Exp $ */ 2 3/* 4 * Copyright (c) 1994, 1995 Gordon W. Ross 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1980, 1990, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 42 * 43 * @(#)locore.s 8.6 (Berkeley) 5/27/94 44 */ 45 46#include "opt_compat_netbsd.h" 47#include "opt_compat_svr4.h" 48#include "opt_compat_sunos.h" 49#include "opt_ddb.h" 50#include "opt_fpsp.h" 51 52#include "assym.h" 53#include <machine/asm.h> 54#include <machine/trap.h> 55 56/* 57 * This is for kvm_mkdb, and should be the address of the beginning 58 * of the kernel text segment (not necessarily the same as kernbase). 59 */ 60 .text 61GLOBAL(kernel_text) 62 63/* 64 * Temporary stack for a variety of purposes. 65 * Try and make this the first thing is the data segment so it 66 * is page aligned. Note that if we overflow here, we run into 67 * our text segment. 68 */ 69 .data 70 .space NBPG 71ASLOCAL(tmpstk) 72 73#include <cesfic/cesfic/vectors.s> 74 75 .text 76 77/* 78 * Macro to relocate a symbol, used before MMU is enabled. 79 */ 80#define _RELOC(var, ar) \ 81 lea var-KERNBASE,ar; \ 82 addl %a5,ar 83 84#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 85#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 86 87/* 88 * Initialization 89 * 90 * A4 contains the address of the end of the symtab 91 * A5 contains physical load point from boot 92 * VBR contains zero from ROM. Exceptions will continue to vector 93 * through ROM until MMU is turned on at which time they will vector 94 * through our table (vectors.s). 95 */ 96 97BSS(lowram,4) 98BSS(esym,4) 99 100 .text 101ASENTRY_NOPROFILE(start) 102 movw #PSL_HIGHIPL, %sr | no interrupts 103 movl #CACHE_OFF, %d0 104 movc %d0, %cacr | clear and disable on-chip cache(s) 105 106 /* XXX fixed load address */ 107 movl #0x20100000, %a5 108 109 movl #0x20000000, %a0 110 RELOC(edata, %a1) 1111: 112 movl %a5@+, %a0@+ 113 cmpl %a5, %a1 114 bne 1b 115 116 movl #0x20000000, %a5 117 118 ASRELOC(tmpstk, %a0) 119 movl %a0, %sp | give ourselves a temporary stack 120 121 RELOC(edata, %a0) 122 RELOC(end, %a1) 1232: 124 clrb %a0@+ 125 cmpl %a0, %a1 126 bne 2b 127 128 RELOC(esym, %a0) 129#if 0 130 movl %a4, %a0@ | store end of symbol table 131#else 132 clrl %a0@ | no symbol table, yet 133#endif 134 135 RELOC(lowram, %a0) 136 movl %a5, %a0@ | store start of physical memory 137 138#if 0 139 RELOC(boothowto, %a0) | save reboot flags 140 movl %d7, %a0@ 141 RELOC(bootdev, %a0) | and boot device 142 movl %d6, %a0@ 143#endif 144 145 /* 146 * All data registers are now free. All address registers 147 * except a5 are free. a5 is used by the RELOC() macro, 148 * and cannot be used until after the MMU is enabled. 149 */ 150 151/* determine our CPU/MMU combo - check for all regardless of kernel config */ 152 movl #0x200,%d0 | data freeze bit 153 movc %d0,%cacr | only exists on 68030 154 movc %cacr,%d0 | read it back 155 tstl %d0 | zero? 156 jeq Lnot68030 | yes, we have 68020/68040 157 RELOC(mmutype, %a0) | no, we have 68030 158 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU 159 RELOC(cputype, %a0) 160 movl #CPU_68030,%a0@ | and 68030 CPU 161 jra Lstart1 162Lnot68030: 163 bset #31,%d0 | data cache enable bit 164 movc %d0,%cacr | only exists on 68040 165 movc %cacr,%d0 | read it back 166 tstl %d0 | zero? 167 beq Lis68020 | yes, we have 68020 168 moveq #0,%d0 | now turn it back off 169 movec %d0,%cacr | before we access any data 170 RELOC(mmutype, %a0) 171 movl #MMU_68040,%a0@ | with a 68040 MMU 172 RELOC(cputype, %a0) 173 movl #CPU_68040,%a0@ | and a 68040 CPU 174 RELOC(fputype, %a0) 175 movl #FPU_68040,%a0@ | ...and FPU 176 jra Lstart1 177Lis68020: 178 /* impossible */ 179 180Lstart1: 181 182/* initialize source/destination control registers for movs */ 183 moveq #FC_USERD,%d0 | user space 184 movc %d0,%sfc | as source 185 movc %d0,%dfc | and destination of transfers 186 187/* initialize memory size (for pmap_bootstrap) */ 188 movl 0x5c00ac00, %d0 189 andb #0x60, %d0 190 jne Lnot8M 191 movl #0x20800000, %d1 | memory end, 8M 192 jra Lmemok 193Lnot8M: 194 cmpb #0x20, %d0 195 jne Lunkmem 196 movl #0x22000000, %d1 | memory end, 32M 197 jra Lmemok 198Lunkmem: 199 /* ??? */ 200 movl #0x20400000, %d1 | memory end, assume at least 4M 201 202Lmemok: 203 moveq #PGSHIFT,%d2 204 lsrl %d2,%d1 | convert to page (click) number 205 movl %a5,%d0 | lowram value from ROM via boot 206 lsrl %d2,%d0 | convert to page number 207 subl %d0,%d1 | compute amount of RAM present 208 RELOC(physmem, %a0) 209 movl %d1,%a0@ | and physmem 210/* configure kernel and proc0 VA space so we can get going */ 211 .globl _Sysseg, _pmap_bootstrap, _avail_start 212#ifdef DDB 213 RELOC(esym,%a0) | end of static kernel test/data/syms 214 movl %a0@,%d5 215 jne Lstart2 216#endif 217 movl #_C_LABEL(end),%d5 | end of static kernel text/data 218Lstart2: 219 addl #NBPG-1,%d5 220 andl #PG_FRAME,%d5 | round to a page 221 movl %d5,%a4 222 addl %a5,%a4 | convert to PA 223 subl #KERNBASE, %a4 224 pea %a5@ | firstpa 225 pea %a4@ | nextpa 226 RELOC(pmap_bootstrap,%a0) 227 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 228 addql #8,%sp 229 230/* 231 * Prepare to enable MMU. 232 */ 233 RELOC(Sysseg, %a0) | system segment table addr 234 movl %a0@,%d1 | read value (a KVA) 235 addl %a5,%d1 | convert to PA 236 subl #KERNBASE, %d1 237 238 RELOC(mmutype, %a0) 239 cmpl #MMU_68040,%a0@ | 68040? 240 jne Lmotommu1 | no, skip 241 .long 0x4e7b1807 | movc d1,srp 242 jra Lstploaddone 243Lmotommu1: 244 RELOC(protorp, %a0) 245 movl #0x80000202,%a0@ | nolimit + share global + 4 byte PTEs 246 movl %d1,%a0@(4) | + segtable address 247 pmove %a0@,%srp | load the supervisor root pointer 248 movl #0x80000002,%a0@ | reinit upper half for CRP loads 249Lstploaddone: 250 251 RELOC(mmutype, %a0) 252 cmpl #MMU_68040,%a0@ | 68040? 253 jne Lmotommu2 | no, skip 254 255 movel #0x2000c000, %d0 | double map RAM 256 .long 0x4e7b0004 | movc d0,itt0 257 .long 0x4e7b0006 | movc d0,dtt0 258 moveq #0, %d0 | ensure TT regs are disabled 259 .long 0x4e7b0005 | movc d0,itt1 260 .long 0x4e7b0007 | movc d0,dtt1 261 262 .word 0xf4d8 | cinva bc 263 .word 0xf518 | pflusha 264 265 movl #0x8000, %d0 266 .long 0x4e7b0003 | movc d0,tc 267 movl #0x80008000, %d0 268 movc %d0, %cacr | turn on both caches 269 270 jmp Lenab1:l | avoid pc-relative 271Lmotommu2: 272 /* XXX do TT here */ 273 RELOC(prototc, %a2) 274 movl #0x82c0aa00,%a2@ | value to load TC with 275 pmove %a2@,%tc | load it 276 jmp Lenab1 277 278/* 279 * Should be running mapped from this point on 280 */ 281Lenab1: 282 .word 0xf4d8 | cinva bc 283 .word 0xf518 | pflusha 284 nop 285 nop 286 nop 287 nop 288 nop 289 movl #_C_LABEL(vectab),%d0 | set Vector Base Register 290 movc %d0,%vbr 291 moveq #0,%d0 | ensure TT regs are disabled 292 .long 0x4e7b0004 | movc d0,itt0 293 .long 0x4e7b0005 | movc d0,itt1 294 .long 0x4e7b0006 | movc d0,dtt0 295 .long 0x4e7b0007 | movc d0,dtt1 296 297/* select the software page size now */ 298 lea _ASM_LABEL(tmpstk),%sp | temporary stack 299 jbsr _C_LABEL(uvm_setpagesize) | select software page size 300/* set kernel stack, user SP, and initial pcb */ 301 movl _C_LABEL(proc0paddr),%a1 | get proc0 pcb addr 302 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 303 lea _C_LABEL(proc0),%a2 | initialize proc0.p_addr so that 304 movl %a1,%a2@(P_ADDR) | we don't deref NULL in trap() 305 movl #USRSTACK-4,%a2 306 movl %a2,%usp | init user SP 307 movl %a1,_C_LABEL(curpcb) | proc0 is running 308 309 tstl _C_LABEL(fputype) | Have an FPU? 310 jeq Lenab2 | No, skip. 311 clrl %a1@(PCB_FPCTX) | ensure null FP context 312 movl %a1,%sp@- 313 jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) 314 addql #4,%sp 315Lenab2: 316 317/* flush TLB and turn on caches */ 318 jbsr _C_LABEL(_TBIA) | invalidate TLB 319 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 320 jeq Lnocache0 | yes, cache already on 321 movl #CACHE_ON,%d0 322 movc %d0,%cacr | clear cache(s) 323Lnocache0: 324 325/* Final setup for call to main(). */ 326 jbsr _C_LABEL(fic_init) 327 328/* 329 * Create a fake exception frame so that cpu_fork() can copy it. 330 * main() nevers returns; we exit to user mode from a forked process 331 * later on. 332 */ 333 clrw %sp@- | vector offset/frame type 334 clrl %sp@- | PC - filled in by "execve" 335 movw #PSL_USER,%sp@- | in user mode 336 clrl %sp@- | stack adjust count and padding 337 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 338 lea _C_LABEL(proc0),%a0 | save pointer to frame 339 movl %sp,%a0@(P_MD_REGS) | in proc0.p_md.md_regs 340 341 jra _C_LABEL(main) | main() 342 343 pea Lmainreturned | Yow! Main returned! 344 jbsr _C_LABEL(panic) 345 /* NOTREACHED */ 346Lmainreturned: 347 .asciz "main() returned" 348 .even 349 350GLOBAL(proc_trampoline) 351 movl %a3,%sp@- 352 jbsr %a2@ 353 addql #4,%sp 354 movl %sp@(FR_SP),%a0 | grab and load 355 movl %a0,%usp | user SP 356 moveml %sp@+,#0x7FFF | restore most user regs 357 addql #8,%sp | toss SP and stack adjust 358 jra _ASM_LABEL(rei) | and return 359 360 361/* 362 * Trap/interrupt vector routines 363 */ 364#include <m68k/m68k/trap_subr.s> 365 366 .data 367GLOBAL(m68k_fault_addr) 368 .long 0 369 370#if defined(M68040) || defined(M68060) 371ENTRY_NOPROFILE(addrerr4060) 372 clrl %sp@- | stack adjust count 373 moveml #0xFFFF,%sp@- | save user registers 374 movl %usp,%a0 | save the user SP 375 movl %a0,%sp@(FR_SP) | in the savearea 376 movl %sp@(FR_HW+8),%sp@- 377 clrl %sp@- | dummy code 378 movl #T_ADDRERR,%sp@- | mark address error 379 jra _ASM_LABEL(faultstkadj) | and deal with it 380#endif 381 382#if defined(M68060) 383 clrl %sp@- | stack adjust count 384 moveml #0xFFFF,%sp@- | save user registers 385 movl %usp,%a0 | save the user SP 386 movl %a0,%sp@(FR_SP) | in the savearea 387 movel %sp@(FR_HW+12),%d0 | FSLW 388 btst #2,%d0 | branch prediction error? 389 jeq Lnobpe 390 movc %cacr,%d2 391 orl #IC60_CABC,%d2 | clear all branch cache entries 392 movc %d2,%cacr 393 movl %d0,%d1 394 addql #1,L60bpe 395 andl #0x7ffd,%d1 396 jeq _ASM_LABEL(faultstkadjnotrap2) 397Lnobpe: 398| we need to adjust for misaligned addresses 399 movl %sp@(FR_HW+8),%d1 | grab VA 400 btst #27,%d0 | check for mis-aligned access 401 jeq Lberr3 | no, skip 402 addl #28,%d1 | yes, get into next page 403 | operand case: 3, 404 | instruction case: 4+12+12 405 andl #PG_FRAME,%d1 | and truncate 406Lberr3: 407 movl %d1,%sp@- 408 movl %d0,%sp@- | code is FSLW now. 409 andw #0x1f80,%d0 410 jeq Lberr60 | it is a bus error 411 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 412 jra _ASM_LABEL(faultstkadj) | and deal with it 413Lberr60: 414 tstl _C_LABEL(nofault) | catch bus error? 415 jeq Lisberr | no, handle as usual 416 movl %sp@(FR_HW+8+8),_C_LABEL(m68k_fault_addr) | save fault addr 417 movl _C_LABEL(nofault),%sp@- | yes, 418 jbsr _C_LABEL(longjmp) | longjmp(nofault) 419 /* NOTREACHED */ 420#endif 421#if defined(M68040) 422ENTRY_NOPROFILE(buserr40) 423 clrl %sp@- | stack adjust count 424 moveml #0xFFFF,%sp@- | save user registers 425 movl %usp,%a0 | save the user SP 426 movl %a0,%sp@(FR_SP) | in the savearea 427 movl %sp@(FR_HW+20),%d1 | get fault address 428 moveq #0,%d0 429 movw %sp@(FR_HW+12),%d0 | get SSW 430 btst #11,%d0 | check for mis-aligned 431 jeq Lbe1stpg | no skip 432 addl #3,%d1 | get into next page 433 andl #PG_FRAME,%d1 | and truncate 434Lbe1stpg: 435 movl %d1,%sp@- | pass fault address. 436 movl %d0,%sp@- | pass SSW as code 437 btst #10,%d0 | test ATC 438 jeq Lberr40 | it is a bus error 439 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 440 jra _ASM_LABEL(faultstkadj) | and deal with it 441Lberr40: 442 tstl _C_LABEL(nofault) | catch bus error? 443 jeq Lisberr | no, handle as usual 444 movl %sp@(FR_HW+8+20),_C_LABEL(m68k_fault_addr) | save fault addr 445 movl _C_LABEL(nofault),%sp@- | yes, 446 jbsr _C_LABEL(longjmp) | longjmp(nofault) 447 /* NOTREACHED */ 448#endif 449 450#if defined(M68020) || defined(M68030) 451ENTRY_NOPROFILE(busaddrerr2030) 452 clrl %sp@- | stack adjust count 453 moveml #0xFFFF,%sp@- | save user registers 454 movl %usp,%a0 | save the user SP 455 movl %a0,%sp@(FR_SP) | in the savearea 456 moveq #0,%d0 457 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 458 btst #12,%d0 | RB set? 459 jeq LbeX0 | no, test RC 460 bset #14,%d0 | yes, must set FB 461 movw %d0,%sp@(FR_HW+10) | for hardware too 462LbeX0: 463 btst #13,%d0 | RC set? 464 jeq LbeX1 | no, skip 465 bset #15,%d0 | yes, must set FC 466 movw %d0,%sp@(FR_HW+10) | for hardware too 467LbeX1: 468 btst #8,%d0 | data fault? 469 jeq Lbe0 | no, check for hard cases 470 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 471 jra Lbe10 | thats it 472Lbe0: 473 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 474 jne Lbe4 | yes, go handle 475 movl %sp@(FR_HW+2),%d1 | no, can use save PC 476 btst #14,%d0 | FB set? 477 jeq Lbe3 | no, try FC 478 addql #4,%d1 | yes, adjust address 479 jra Lbe10 | done 480Lbe3: 481 btst #15,%d0 | FC set? 482 jeq Lbe10 | no, done 483 addql #2,%d1 | yes, adjust address 484 jra Lbe10 | done 485Lbe4: 486 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 487 btst #15,%d0 | FC set? 488 jeq Lbe10 | no, all done 489 subql #2,%d1 | yes, adjust address 490Lbe10: 491 movl %d1,%sp@- | push fault VA 492 movl %d0,%sp@- | and padded SSW 493 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 494 andw #0x0FFF,%d0 | clear out frame format 495 cmpw #12,%d0 | address error vector? 496 jeq Lisaerr | yes, go to it 497#if defined(M68K_MMU_MOTOROLA) 498#if defined(M68K_MMU_HP) 499 tstl _C_LABEL(mmutype) | HP MMU? 500 jeq Lbehpmmu | yes, different MMU fault handler 501#endif 502 movl %d1,%a0 | fault address 503 movl %sp@,%d0 | function code from ssw 504 btst #8,%d0 | data fault? 505 jne Lbe10a 506 movql #1,%d0 | user program access FC 507 | (we dont separate data/program) 508 btst #5,%sp@(FR_HW+8) | supervisor mode? 509 jeq Lbe10a | if no, done 510 movql #5,%d0 | else supervisor program access 511Lbe10a: 512 ptestr %d0,%a0@,#7 | do a table search 513 pmove %psr,%sp@ | save result 514 movb %sp@,%d1 515 btst #2,%d1 | invalid (incl. limit viol. and berr)? 516 jeq Lmightnotbemerr | no -> wp check 517 btst #7,%d1 | is it MMU table berr? 518 jne Lisberr1 | yes, needs not be fast. 519#endif /* M68K_MMU_MOTOROLA */ 520Lismerr: 521 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 522 jra _ASM_LABEL(faultstkadj) | and deal with it 523#if defined(M68K_MMU_MOTOROLA) 524Lmightnotbemerr: 525 btst #3,%d1 | write protect bit set? 526 jeq Lisberr1 | no: must be bus error 527 movl %sp@,%d0 | ssw into low word of %d0 528 andw #0xc0,%d0 | Write protect is set on page: 529 cmpw #0x40,%d0 | was it read cycle? 530 jne Lismerr | no, was not WPE, must be MMU fault 531 jra Lisberr1 | real bus err needs not be fast. 532#endif /* M68K_MMU_MOTOROLA */ 533#if defined(M68K_MMU_HP) 534Lbehpmmu: 535 MMUADDR(%a0) 536 movl %a0@(MMUSTAT),%d0 | read MMU status 537 btst #3,%d0 | MMU fault? 538 jeq Lisberr1 | no, just a non-MMU bus error 539 andl #~MMU_FAULT,%a0@(MMUSTAT)| yes, clear fault bits 540 movw %d0,%sp@ | pass MMU stat in upper half of code 541 jra Lismerr | and handle it 542#endif 543Lisaerr: 544 movl #T_ADDRERR,%sp@- | mark address error 545 jra _ASM_LABEL(faultstkadj) | and deal with it 546Lisberr1: 547 clrw %sp@ | re-clear pad word 548 tstl _C_LABEL(nofault) | catch bus error? 549 jeq Lisberr | no, handle as usual 550 movl %sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr 551 movl _C_LABEL(nofault),%sp@- | yes, 552 jbsr _C_LABEL(longjmp) | longjmp(nofault) 553 /* NOTREACHED */ 554#endif /* M68020 || M68030 */ 555 556Lisberr: | also used by M68040/60 557 movl #T_BUSERR,%sp@- | mark bus error 558 jra _ASM_LABEL(faultstkadj) | and deal with it 559 560/* 561 * FP exceptions. 562 */ 563ENTRY_NOPROFILE(fpfline) 564#if defined(M68040) 565 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 566 jne Lfp_unimp | no, skip FPSP 567 cmpw #0x202c,%sp@(6) | format type 2? 568 jne _C_LABEL(illinst) | no, not an FP emulation 569Ldofp_unimp: 570#ifdef FPSP 571#if 0 572 addl #1, _C_LABEL(evcnt_fpsp_unimp)+EVCNT_COUNT 573#endif 574 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 575#endif 576Lfp_unimp: 577#endif /* M68040 */ 578#ifdef FPU_EMULATE 579 clrl %sp@- | stack adjust count 580 moveml #0xFFFF,%sp@- | save registers 581 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 582 jra _ASM_LABEL(fault) | do it 583#else 584 jra _C_LABEL(illinst) 585#endif 586 587ENTRY_NOPROFILE(fpunsupp) 588#if defined(M68040) 589 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 590 jne _C_LABEL(illinst) | no, treat as illinst 591#ifdef FPSP 592#if 0 593 addl #1, _C_LABEL(evcnt_fpsp_unsupp)+EVCNT_COUNT 594#endif 595 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 596#endif 597Lfp_unsupp: 598#endif /* M68040 */ 599#ifdef FPU_EMULATE 600 clrl %sp@- | stack adjust count 601 moveml #0xFFFF,%sp@- | save registers 602 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 603 jra _ASM_LABEL(fault) | do it 604#else 605 jra _C_LABEL(illinst) 606#endif 607 608/* 609 * Handles all other FP coprocessor exceptions. 610 * Note that since some FP exceptions generate mid-instruction frames 611 * and may cause signal delivery, we need to test for stack adjustment 612 * after the trap call. 613 */ 614ENTRY_NOPROFILE(fpfault) 615 clrl %sp@- | stack adjust count 616 moveml #0xFFFF,%sp@- | save user registers 617 movl %usp,%a0 | and save 618 movl %a0,%sp@(FR_SP) | the user stack pointer 619 clrl %sp@- | no VA arg 620 movl _C_LABEL(curpcb),%a0 | current pcb 621 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 622 fsave %a0@ | save state 623#if defined(M68040) || defined(M68060) 624 /* always null state frame on 68040, 68060 */ 625 cmpl #FPU_68040,_C_LABEL(fputype) 626 jle Lfptnull 627#endif 628 tstb %a0@ | null state frame? 629 jeq Lfptnull | yes, safe 630 clrw %d0 | no, need to tweak BIU 631 movb %a0@(1),%d0 | get frame size 632 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 633Lfptnull: 634 fmovem %fpsr,%sp@- | push %fpsr as code argument 635 frestore %a0@ | restore state 636 movl #T_FPERR,%sp@- | push type arg 637 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 638 639 640ENTRY_NOPROFILE(badtrap) 641 moveml #0xC0C0,%sp@- | save scratch regs 642 movw %sp@(22),%sp@- | push exception vector info 643 clrw %sp@- 644 movl %sp@(22),%sp@- | and PC 645 jbsr _C_LABEL(straytrap) | report 646 addql #8,%sp | pop args 647 moveml %sp@+,#0x0303 | restore regs 648 jra _ASM_LABEL(rei) | all done 649 650ENTRY_NOPROFILE(trap0) 651 clrl %sp@- | stack adjust count 652 moveml #0xFFFF,%sp@- | save user registers 653 movl %usp,%a0 | save the user SP 654 movl %a0,%sp@(FR_SP) | in the savearea 655 movl %d0,%sp@- | push syscall number 656 jbsr _C_LABEL(syscall) | handle it 657 addql #4,%sp | pop syscall arg 658 tstl _C_LABEL(astpending) 659 jne Lrei2 660 tstb _C_LABEL(ssir) 661 jeq Ltrap1 662 movw #SPL1,%sr 663 tstb _C_LABEL(ssir) 664 jne Lsir1 665Ltrap1: 666 movl %sp@(FR_SP),%a0 | grab and restore 667 movl %a0,%usp | user SP 668 moveml %sp@+,#0x7FFF | restore most registers 669 addql #8,%sp | pop SP and stack adjust 670 rte 671 672/* 673 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 674 * cachectl(command, addr, length) 675 * command in d0, addr in a1, length in d1 676 */ 677ENTRY_NOPROFILE(trap12) 678 movl _C_LABEL(curproc),%sp@- | push current proc pointer 679 movl %d1,%sp@- | push length 680 movl %a1,%sp@- | push addr 681 movl %d0,%sp@- | push command 682 jbsr _C_LABEL(cachectl1) | do it 683 lea %sp@(16),%sp | pop args 684 jra _ASM_LABEL(rei) | all done 685 686/* 687 * Trace (single-step) trap. Kernel-mode is special. 688 * User mode traps are simply passed on to trap(). 689 */ 690ENTRY_NOPROFILE(trace) 691 clrl %sp@- | stack adjust count 692 moveml #0xFFFF,%sp@- 693 moveq #T_TRACE,%d0 694 695 | Check PSW and see what happen. 696 | T=0 S=0 (should not happen) 697 | T=1 S=0 trace trap from user mode 698 | T=0 S=1 trace trap on a trap instruction 699 | T=1 S=1 trace trap from system mode (kernel breakpoint) 700 701 movw %sp@(FR_HW),%d1 | get PSW 702 notw %d1 | XXX no support for T0 on 680[234]0 703 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 704 jeq Lkbrkpt | yes, kernel breakpoint 705 jra _ASM_LABEL(fault) | no, user-mode fault 706 707 708/* 709 * Trap 15 is used for: 710 * - GDB breakpoints (in user programs) 711 * - KGDB breakpoints (in the kernel) 712 * - trace traps for SUN binaries (not fully supported yet) 713 * User mode traps are simply passed to trap(). 714 */ 715ENTRY_NOPROFILE(trap15) 716 clrl %sp@- | stack adjust count 717 moveml #0xFFFF,%sp@- 718 moveq #T_TRAP15,%d0 719 movw %sp@(FR_HW),%d1 | get PSW 720 andw #PSL_S,%d1 | from system mode? 721 jne Lkbrkpt | yes, kernel breakpoint 722 jra _ASM_LABEL(fault) | no, user-mode fault 723 724Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type) 725 | Save the system sp rather than the user sp. 726 movw #PSL_HIGHIPL,%sr | lock out interrupts 727 lea %sp@(FR_SIZE),%a6 | Save stack pointer 728 movl %a6,%sp@(FR_SP) | from before trap 729 730 | If were are not on tmpstk switch to it. 731 | (so debugger can change the stack pointer) 732 movl %a6,%d1 733 cmpl #_ASM_LABEL(tmpstk),%d1 734 jls Lbrkpt2 | already on tmpstk 735 | Copy frame to the temporary stack 736 movl %sp,%a0 | %a0=src 737 lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst 738 movl %a1,%sp | %sp=new frame 739 moveq #FR_SIZE,%d1 740Lbrkpt1: 741 movl %a0@+,%a1@+ 742 subql #4,%d1 743 bgt Lbrkpt1 744 745Lbrkpt2: 746 | Call the trap handler for the kernel debugger. 747 | Do not call trap() to do it, so that we can 748 | set breakpoints in trap() if we want. We know 749 | the trap type is either T_TRACE or T_BREAKPOINT. 750 movl %d0,%sp@- | push trap type 751 jbsr _C_LABEL(trap_kdebug) 752 addql #4,%sp | pop args 753 754 | The stack pointer may have been modified, or 755 | data below it modified (by kgdb push call), 756 | so push the hardware frame at the current sp 757 | before restoring registers and returning. 758 759 movl %sp@(FR_SP),%a0 | modified %sp 760 lea %sp@(FR_SIZE),%a1 | end of our frame 761 movl %a1@-,%a0@- | copy 2 longs with 762 movl %a1@-,%a0@- | ... predecrement 763 movl %a0,%sp@(FR_SP) | %sp = h/w frame 764 moveml %sp@+,#0x7FFF | restore all but %sp 765 movl %sp@,%sp | ... and %sp 766 rte | all done 767 768/* Use common m68k sigreturn */ 769#include <m68k/m68k/sigreturn.s> 770 771/* 772 * Interrupt handlers. 773 * All device interrupts are auto-vectored. The CPU provides 774 * the vector 0x18+level. Note we count spurious interrupts, but 775 * we don't do anything else with them. 776 */ 777 778#define INTERRUPT_SAVEREG moveml #0xC0C0,%sp@- 779#define INTERRUPT_RESTOREREG moveml %sp@+,#0x0303 780 781ENTRY_NOPROFILE(spurintr) /* level 0 */ 782 addql #1,_C_LABEL(intrcnt)+0 783 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 784 jra _ASM_LABEL(rei) 785 786ENTRY_NOPROFILE(intrhand) /* levels 1 through 5 */ 787 INTERRUPT_SAVEREG 788 movw %sp@(22),%sp@- | push exception vector info 789 clrw %sp@- 790 jbsr _C_LABEL(isrdispatch) | call dispatch routine 791 addql #4,%sp 792 INTERRUPT_RESTOREREG 793 jra _ASM_LABEL(rei) | all done 794 795ENTRY_NOPROFILE(lev6intr) /* Level 6: clock */ 796 INTERRUPT_SAVEREG 797 /* XXX */ 798 movl _C_LABEL(clockbase), %a0 799 movl %a0@, %d0 800 movl %d0, %a0@ 801 btst #2, %d0 802 jeq 1f 803 addql #1,_C_LABEL(intrcnt)+24 804 lea %sp@(16), %a1 | a1 = &clockframe 805 movl %a1, %sp@- 806 jbsr _C_LABEL(hardclock) | hardclock(&frame) 807 addql #4, %sp 808 jra 2f 8091: 810 movl %d0, %sp@- 811 jbsr _C_LABEL(otherclock) 812 addql #4, %sp 8132: 814 INTERRUPT_RESTOREREG 815 jra _ASM_LABEL(rei) | all done 816 817ENTRY_NOPROFILE(lev7intr) /* level 7: parity errors, reset key */ 818 addql #1,_C_LABEL(intrcnt)+28 819 clrl %sp@- 820 moveml #0xFFFF,%sp@- | save registers 821 movl %usp,%a0 | and save 822 movl %a0,%sp@(FR_SP) | the user stack pointer 823 jbsr _C_LABEL(nmihand) | call handler 824 movl %sp@(FR_SP),%a0 | restore 825 movl %a0,%usp | user SP 826 moveml %sp@+,#0x7FFF | and remaining registers 827 addql #8,%sp | pop SP and stack adjust 828 jra _ASM_LABEL(rei) | all done 829 830/* 831 * Emulation of VAX REI instruction. 832 * 833 * This code deals with checking for and servicing ASTs 834 * (profiling, scheduling) and software interrupts (network, softclock). 835 * We check for ASTs first, just like the VAX. To avoid excess overhead 836 * the T_ASTFLT handling code will also check for software interrupts so we 837 * do not have to do it here. After identifing that we need an AST we 838 * drop the IPL to allow device interrupts. 839 * 840 * This code is complicated by the fact that sendsig may have been called 841 * necessitating a stack cleanup. 842 */ 843BSS(ssir,1) 844 845ASENTRY_NOPROFILE(rei) 846 tstl _C_LABEL(astpending) | AST pending? 847 jeq Lchksir | no, go check for SIR 848Lrei1: 849 btst #5,%sp@ | yes, are we returning to user mode? 850 jne Lchksir | no, go check for SIR 851 movw #PSL_LOWIPL,%sr | lower SPL 852 clrl %sp@- | stack adjust 853 moveml #0xFFFF,%sp@- | save all registers 854 movl %usp,%a1 | including 855 movl %a1,%sp@(FR_SP) | the users SP 856Lrei2: 857 clrl %sp@- | VA == none 858 clrl %sp@- | code == none 859 movl #T_ASTFLT,%sp@- | type == async system trap 860 jbsr _C_LABEL(trap) | go handle it 861 lea %sp@(12),%sp | pop value args 862 movl %sp@(FR_SP),%a0 | restore user SP 863 movl %a0,%usp | from save area 864 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 865 jne Laststkadj | yes, go to it 866 moveml %sp@+,#0x7FFF | no, restore most user regs 867 addql #8,%sp | toss SP and stack adjust 868 rte | and do real RTE 869Laststkadj: 870 lea %sp@(FR_HW),%a1 | pointer to HW frame 871 addql #8,%a1 | source pointer 872 movl %a1,%a0 | source 873 addw %d0,%a0 | + hole size = dest pointer 874 movl %a1@-,%a0@- | copy 875 movl %a1@-,%a0@- | 8 bytes 876 movl %a0,%sp@(FR_SP) | new SSP 877 moveml %sp@+,#0x7FFF | restore user registers 878 movl %sp@,%sp | and our SP 879 rte | and do real RTE 880Lchksir: 881 tstb _C_LABEL(ssir) | SIR pending? 882 jeq Ldorte | no, all done 883 movl %d0,%sp@- | need a scratch register 884 movw %sp@(4),%d0 | get SR 885 andw #PSL_IPL7,%d0 | mask all but IPL 886 jne Lnosir | came from interrupt, no can do 887 movl %sp@+,%d0 | restore scratch register 888Lgotsir: 889 movw #SPL1,%sr | prevent others from servicing int 890 tstb _C_LABEL(ssir) | too late? 891 jeq Ldorte | yes, oh well... 892 clrl %sp@- | stack adjust 893 moveml #0xFFFF,%sp@- | save all registers 894 movl %usp,%a1 | including 895 movl %a1,%sp@(FR_SP) | the users SP 896Lsir1: 897 clrl %sp@- | VA == none 898 clrl %sp@- | code == none 899 movl #T_SSIR,%sp@- | type == software interrupt 900 jbsr _C_LABEL(trap) | go handle it 901 lea %sp@(12),%sp | pop value args 902 movl %sp@(FR_SP),%a0 | restore 903 movl %a0,%usp | user SP 904 moveml %sp@+,#0x7FFF | and all remaining registers 905 addql #8,%sp | pop SP and stack adjust 906 rte 907Lnosir: 908 movl %sp@+,%d0 | restore scratch register 909Ldorte: 910 rte | real return 911 912/* 913 * Use common m68k sigcode. 914 */ 915#include <m68k/m68k/sigcode.s> 916#ifdef COMPAT_SUNOS 917#include <m68k/m68k/sunos_sigcode.s> 918#endif 919#ifdef COMPAT_SVR4 920#include <m68k/m68k/svr4_sigcode.s> 921#endif 922 923/* 924 * Primitives 925 */ 926 927/* 928 * Use common m68k support routines. 929 */ 930#include <m68k/m68k/support.s> 931 932/* 933 * Use common m68k process manipulation routines. 934 */ 935#include <m68k/m68k/proc_subr.s> 936 937 .data 938GLOBAL(curpcb) 939GLOBAL(masterpaddr) | XXX compatibility (debuggers) 940 .long 0 941 942ASLOCAL(mdpflag) 943 .byte 0 | copy of proc md_flags low byte 944#ifdef __ELF__ 945 .align 4 946#else 947 .align 2 948#endif 949 950ASBSS(nullpcb,SIZEOF_PCB) 951 952/* 953 * At exit of a process, do a switch for the last time. 954 * Switch to a safe stack and PCB, and deallocate the process's resources. 955 */ 956ENTRY(switch_exit) 957 movl %sp@(4),%a0 958 /* save state into garbage pcb */ 959 movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) 960 lea _ASM_LABEL(tmpstk),%sp | goto a tmp stack 961 962 /* Schedule the vmspace and stack to be freed. */ 963 movl %a0,%sp@- | exit2(p) 964 jbsr _C_LABEL(exit2) 965 lea %sp@(4),%sp | pop args 966 967 jra _C_LABEL(cpu_switch) 968 969/* 970 * When no processes are on the runq, Swtch branches to Idle 971 * to wait for something to come ready. 972 */ 973ASENTRY_NOPROFILE(Idle) 974 stop #PSL_LOWIPL 975 movw #PSL_HIGHIPL,%sr 976 movl _C_LABEL(sched_whichqs),%d0 977 jeq _ASM_LABEL(Idle) 978 jra Lsw1 979 980Lbadsw: 981 PANIC("switch") 982 /*NOTREACHED*/ 983 984/* 985 * cpu_switch() 986 * 987 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 988 * entire ATC. The effort involved in selective flushing may not be 989 * worth it, maybe we should just flush the whole thing? 990 * 991 * NOTE 2: With the new VM layout we now no longer know if an inactive 992 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 993 * bit). For now, we just always flush the full ATC. 994 */ 995ENTRY(cpu_switch) 996 movl _C_LABEL(curpcb),%a0 | current pcb 997 movw %sr,%a0@(PCB_PS) | save %sr before changing ipl 998#ifdef notyet 999 movl _C_LABEL(curproc),%sp@- | remember last proc running 1000#endif 1001 clrl _C_LABEL(curproc) 1002 1003 /* 1004 * Find the highest-priority queue that isn't empty, 1005 * then take the first proc from that queue. 1006 */ 1007 movw #PSL_HIGHIPL,%sr | lock out interrupts 1008 movl _C_LABEL(sched_whichqs),%d0 1009 jeq _ASM_LABEL(Idle) 1010Lsw1: 1011 movl %d0,%d1 1012 negl %d0 1013 andl %d1,%d0 1014 bfffo %d0{#0:#32},%d1 1015 eorib #31,%d1 1016 1017 movl %d1,%d0 1018 lslb #3,%d1 | convert queue number to index 1019 addl #_C_LABEL(sched_qs),%d1 | locate queue (q) 1020 movl %d1,%a1 1021 movl %a1@(P_FORW),%a0 | p = q->p_forw 1022 cmpal %d1,%a0 | anyone on queue? 1023 jeq Lbadsw | no, panic 1024 movl %a0@(P_FORW),%a1@(P_FORW) | q->p_forw = p->p_forw 1025 movl %a0@(P_FORW),%a1 | n = p->p_forw 1026 movl %d1,%a1@(P_BACK) | n->p_back = q 1027 cmpal %d1,%a1 | anyone left on queue? 1028 jne Lsw2 | yes, skip 1029 movl _C_LABEL(sched_whichqs),%d1 1030 bclr %d0,%d1 | no, clear bit 1031 movl %d1,_C_LABEL(sched_whichqs) 1032Lsw2: 1033 /* p->p_cpu initialized in fork1() for single-processor */ 1034 movb #SONPROC,%a0@(P_STAT) | p->p_stat = SONPROC 1035 movl %a0,_C_LABEL(curproc) 1036 clrl _C_LABEL(want_resched) 1037#ifdef notyet 1038 movl %sp@+,%a1 1039 cmpl %a0,%a1 | switching to same proc? 1040 jeq Lswdone | yes, skip save and restore 1041#endif 1042 /* 1043 * Save state of previous process in its pcb. 1044 */ 1045 movl _C_LABEL(curpcb),%a1 1046 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1047 movl %usp,%a2 | grab USP (%a2 has been saved) 1048 movl %a2,%a1@(PCB_USP) | and save it 1049 1050 tstl _C_LABEL(fputype) | Do we have an FPU? 1051 jeq Lswnofpsave | No Then don't attempt save. 1052 lea %a1@(PCB_FPCTX),%a2 | pointer to FP save area 1053 fsave %a2@ | save FP state 1054 tstb %a2@ | null state frame? 1055 jeq Lswnofpsave | yes, all done 1056 fmovem %fp0-%fp7,%a2@(216) | save FP general registers 1057 fmovem %fpcr/%fpsr/%fpi,%a2@(312) | save FP control registers 1058Lswnofpsave: 1059 1060 clrl %a0@(P_BACK) | clear back link 1061 movb %a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags 1062 movl %a0@(P_ADDR),%a1 | get p_addr 1063 movl %a1,_C_LABEL(curpcb) 1064 1065 /* 1066 * Activate process's address space. 1067 * XXX Should remember the last USTP value loaded, and call this 1068 * XXX only if it has changed. 1069 */ 1070 pea %a0@ | push proc 1071 jbsr _C_LABEL(pmap_activate) | pmap_activate(p) 1072 addql #4,%sp 1073 movl _C_LABEL(curpcb),%a1 | restore p_addr 1074 1075 lea _ASM_LABEL(tmpstk),%sp | now goto a tmp stack for NMI 1076 1077 moveml %a1@(PCB_REGS),#0xFCFC | and registers 1078 movl %a1@(PCB_USP),%a0 1079 movl %a0,%usp | and USP 1080 1081 tstl _C_LABEL(fputype) | If we don't have an FPU, 1082 jeq Lnofprest | don't try to restore it. 1083 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1084 tstb %a0@ | null state frame? 1085 jeq Lresfprest | yes, easy 1086#if defined(M68040) 1087#if defined(M68020) || defined(M68030) 1088 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1089 jne Lresnot040 | no, skip 1090#endif 1091 clrl %sp@- | yes... 1092 frestore %sp@+ | ...magic! 1093Lresnot040: 1094#endif 1095 fmovem %a0@(312),%fpcr/%fpsr/%fpi | restore FP control registers 1096 fmovem %a0@(216),%fp0-%fp7 | restore FP general registers 1097Lresfprest: 1098 frestore %a0@ | restore state 1099 1100Lnofprest: 1101 movw %a1@(PCB_PS),%sr | no, restore PS 1102 moveq #1,%d0 | return 1 (for alternate returns) 1103 rts 1104 1105/* 1106 * savectx(pcb) 1107 * Update pcb, saving current processor state. 1108 */ 1109ENTRY(savectx) 1110 movl %sp@(4),%a1 1111 movw %sr,%a1@(PCB_PS) 1112 movl %usp,%a0 | grab USP 1113 movl %a0,%a1@(PCB_USP) | and save it 1114 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1115 1116 tstl _C_LABEL(fputype) | Do we have FPU? 1117 jeq Lsvnofpsave | No? Then don't save state. 1118 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1119 fsave %a0@ | save FP state 1120 tstb %a0@ | null state frame? 1121 jeq Lsvnofpsave | yes, all done 1122 fmovem %fp0-%fp7,%a0@(216) | save FP general registers 1123 fmovem %fpcr/%fpsr/%fpi,%a0@(312) | save FP control registers 1124Lsvnofpsave: 1125 moveq #0,%d0 | return 0 1126 rts 1127 1128#if defined(M68040) 1129ENTRY(suline) 1130 movl %sp@(4),%a0 | address to write 1131 movl _C_LABEL(curpcb),%a1 | current pcb 1132 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 1133 movl %sp@(8),%a1 | address of line 1134 movl %a1@+,%d0 | get lword 1135 movsl %d0,%a0@+ | put lword 1136 nop | sync 1137 movl %a1@+,%d0 | get lword 1138 movsl %d0,%a0@+ | put lword 1139 nop | sync 1140 movl %a1@+,%d0 | get lword 1141 movsl %d0,%a0@+ | put lword 1142 nop | sync 1143 movl %a1@+,%d0 | get lword 1144 movsl %d0,%a0@+ | put lword 1145 nop | sync 1146 moveq #0,%d0 | indicate no fault 1147 jra Lsldone 1148Lslerr: 1149 moveq #-1,%d0 1150Lsldone: 1151 movl _C_LABEL(curpcb),%a1 | current pcb 1152 clrl %a1@(PCB_ONFAULT) | clear fault address 1153 rts 1154#endif 1155 1156ENTRY_NOPROFILE(getsfc) 1157 movc %sfc,%d0 1158 rts 1159 1160ENTRY_NOPROFILE(getdfc) 1161 movc %dfc,%d0 1162 rts 1163 1164/* 1165 * Load a new user segment table pointer. 1166 */ 1167ENTRY(loadustp) 1168#if defined(M68K_MMU_MOTOROLA) 1169 tstl _C_LABEL(mmutype) | HP MMU? 1170 jeq Lhpmmu9 | yes, skip 1171 movl %sp@(4),%d0 | new USTP 1172 moveq #PGSHIFT,%d1 1173 lsll %d1,%d0 | convert to addr 1174#if defined(M68040) 1175 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1176 jne LmotommuC | no, skip 1177 .word 0xf518 | yes, pflusha 1178 .long 0x4e7b0806 | movc %d0,%urp 1179 rts 1180LmotommuC: 1181#endif 1182 pflusha | flush entire TLB 1183 lea _C_LABEL(protorp),%a0 | CRP prototype 1184 movl %d0,%a0@(4) | stash USTP 1185 pmove %a0@,%crp | load root pointer 1186 movl #CACHE_CLR,%d0 1187 movc %d0,%cacr | invalidate cache(s) 1188 rts 1189Lhpmmu9: 1190#endif 1191#if defined(M68K_MMU_HP) 1192 movl #CACHE_CLR,%d0 1193 movc %d0,%cacr | invalidate cache(s) 1194 MMUADDR(%a0) 1195 movl %a0@(MMUTBINVAL),%d1 | invalidate TLB 1196 tstl _C_LABEL(ectype) | have external VAC? 1197 jle 1f | no, skip 1198 andl #~MMU_CEN,%a0@(MMUCMD) | toggle cache enable 1199 orl #MMU_CEN,%a0@(MMUCMD) | to clear data cache 12001: 1201 movl %sp@(4),%a0@(MMUUSTP) | load a new USTP 1202#endif 1203 rts 1204 1205ENTRY(ploadw) 1206#if defined(M68K_MMU_MOTOROLA) 1207 movl %sp@(4),%a0 | address to load 1208#if defined(M68K_MMU_HP) 1209 tstl _C_LABEL(mmutype) | HP MMU? 1210 jeq Lploadwskp | yes, skip 1211#endif 1212#if defined(M68040) 1213 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1214 jeq Lploadwskp | yes, skip 1215#endif 1216 ploadw #1,%a0@ | pre-load translation 1217Lploadwskp: 1218#endif 1219 rts 1220 1221/* 1222 * Set processor priority level calls. Most are implemented with 1223 * inline asm expansions. However, spl0 requires special handling 1224 * as we need to check for our emulated software interrupts. 1225 */ 1226 1227ENTRY(spl0) 1228 moveq #0,%d0 1229 movw %sr,%d0 | get old SR for return 1230 movw #PSL_LOWIPL,%sr | restore new SR 1231 tstb _C_LABEL(ssir) | software interrupt pending? 1232 jeq Lspldone | no, all done 1233 subql #4,%sp | make room for RTE frame 1234 movl %sp@(4),%sp@(2) | position return address 1235 clrw %sp@(6) | set frame type 0 1236 movw #PSL_LOWIPL,%sp@ | and new SR 1237 jra Lgotsir | go handle it 1238Lspldone: 1239 rts 1240 1241/* 1242 * _delay(u_int N) 1243 * 1244 * Delay for at least (N/256) microsecends. 1245 * This routine depends on the variable: delay_divisor 1246 * which should be set based on the CPU clock rate. 1247 */ 1248ENTRY_NOPROFILE(_delay) 1249 | d0 = arg = (usecs << 8) 1250 movl %sp@(4),%d0 1251 | d1 = delay_divisor 1252 movl _C_LABEL(delay_divisor),%d1 1253L_delay: 1254 subl %d1,%d0 1255 jgt L_delay 1256 rts 1257 1258/* 1259 * Save and restore 68881 state. 1260 * Pretty awful looking since our assembler does not 1261 * recognize FP mnemonics. 1262 */ 1263ENTRY(m68881_save) 1264 movl %sp@(4),%a0 | save area pointer 1265 fsave %a0@ | save state 1266 tstb %a0@ | null state frame? 1267 jeq Lm68881sdone | yes, all done 1268 fmovem %fp0-%fp7,%a0@(216) | save FP general registers 1269 fmovem %fpcr/%fpsr/%fpi,%a0@(312) | save FP control registers 1270Lm68881sdone: 1271 rts 1272 1273ENTRY(m68881_restore) 1274 movl %sp@(4),%a0 | save area pointer 1275 tstb %a0@ | null state frame? 1276 jeq Lm68881rdone | yes, easy 1277 fmovem %a0@(312),%fpcr/%fpsr/%fpi | restore FP control registers 1278 fmovem %a0@(216),%fp0-%fp7 | restore FP general registers 1279Lm68881rdone: 1280 frestore %a0@ | restore state 1281 rts 1282 1283ENTRY_NOPROFILE(doboot) 1284 movl #0x5c00c060, %d0 | want phys addressing 1285 .long 0x4e7b0006 | movc d0,dtt0 1286 movl #1, 0x5c00b800 | reset 1287 stop #0x2700 | paranoia 1288 1289 .data 1290GLOBAL(mmutype) 1291 .long MMU_HP | default to HP MMU 1292GLOBAL(cputype) 1293 .long CPU_68020 | default to 68020 CPU 1294GLOBAL(fputype) 1295 .long FPU_68881 | default to 68881 FPU 1296GLOBAL(protorp) 1297 .long 0,0 | prototype root pointer 1298GLOBAL(prototc) 1299 .long 0 | prototype translation control 1300GLOBAL(want_resched) 1301 .long 0 1302 1303GLOBAL(proc0paddr) 1304 .long 0 | KVA of proc0 u-area 1305#ifdef DEBUG 1306 .globl fulltflush, fullcflush 1307fulltflush: 1308 .long 0 1309fullcflush: 1310 .long 0 1311#endif 1312 1313/* interrupt counters */ 1314GLOBAL(intrnames) 1315 .asciz "spur" 1316 .asciz "lev1" 1317 .asciz "lev2" 1318 .asciz "lev3" 1319 .asciz "lev4" 1320 .asciz "lev5" 1321 .asciz "clock" 1322 .asciz "nmi" 1323GLOBAL(eintrnames) 1324 .even 1325GLOBAL(intrcnt) 1326 .long 0,0,0,0,0,0,0,0 1327GLOBAL(eintrcnt) 1328