1/* $NetBSD: locore.s,v 1.107 2011/02/08 20:20:20 rmind Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1980, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 37 * 38 * @(#)locore.s 8.6 (Berkeley) 5/27/94 39 */ 40 41#include "opt_compat_netbsd.h" 42#include "opt_compat_svr4.h" 43#include "opt_compat_sunos.h" 44#include "opt_fpsp.h" 45#include "opt_ddb.h" 46#include "opt_kgdb.h" 47#include "opt_lockdebug.h" 48#include "opt_m68k_arch.h" 49 50#include "assym.h" 51#include <machine/asm.h> 52#include <machine/trap.h> 53 54#include "ksyms.h" 55 56/* 57 * Temporary stack for a variety of purposes. 58 * Try and make this the first thing is the data segment so it 59 * is page aligned. Note that if we overflow here, we run into 60 * our text segment. 61 */ 62 .data 63 .space PAGE_SIZE 64ASLOCAL(tmpstk) 65 66ASLOCAL(bug_vbr) 67 .long 0 68 69#include <mvme68k/mvme68k/vectors.s> 70 71 72/* 73 * Macro to relocate a symbol, used before MMU is enabled. 74 */ 75#define _RELOC(var, ar) \ 76 lea var,ar 77 78#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 79#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 80 81/* 82 * Macro to call into the Bug ROM monitor 83 */ 84#define CALLBUG(func) \ 85 trap #15; .short func 86 87/* 88 * Initialization 89 * 90 * The bootstrap loader loads us in starting at 0, and VBR is non-zero. 91 * On entry, args on stack are boot device, boot filename, console unit, 92 * boot flags (howto), boot device name, filesystem type name. 93 */ 94BSS(lowram,4) 95BSS(esym,4) 96 97 .globl _C_LABEL(edata) 98 .globl _C_LABEL(etext),_C_LABEL(end) 99 100 101/* 102 * This is for kvm_mkdb, and should be the address of the beginning 103 * of the kernel text segment (not necessarily the same as kernbase). 104 */ 105 .text 106GLOBAL(kernel_text) 107 108/* 109 * start of kernel and .text! 110 */ 111ASENTRY_NOPROFILE(start) 112 movw #PSL_HIGHIPL,%sr | no interrupts 113 movl #0,%a5 | RAM starts at 0 (a5) 114 movl %sp@(4), %d7 | get boothowto 115 movl %sp@(8), %d6 | get bootaddr 116 movl %sp@(12),%d5 | get bootctrllun 117 movl %sp@(16),%d4 | get bootdevlun 118 movl %sp@(20),%d3 | get bootpart 119 movl %sp@(24),%d2 | get esyms 120 121 RELOC(bootpart,%a0) 122 movl %d3, %a0@ | save bootpart 123 RELOC(bootdevlun,%a0) 124 movl %d4, %a0@ | save bootdevlun 125 RELOC(bootctrllun,%a0) 126 movl %d5, %a0@ | save booctrllun 127 RELOC(bootaddr,%a0) 128 movl %d6, %a0@ | save bootaddr 129 RELOC(boothowto,%a0) 130 movl %d7, %a0@ | save boothowto 131 /* note: d3-d7 free, d2 still in use */ 132 133 ASRELOC(tmpstk, %a0) 134 movl %a0,%sp | give ourselves a temporary stack 135 136 RELOC(edata,%a0) | clear out BSS 137 movl #_C_LABEL(end) - 4, %d0 | (must be <= 256 kB) 138 subl #_C_LABEL(edata), %d0 139 lsrl #2,%d0 1401: clrl %a0@+ 141 dbra %d0,1b 142 143 RELOC(esym, %a0) 144 movl %d2,%a0@ | store end of symbol table 145 /* d2 now free */ 146 RELOC(lowram, %a0) 147 movl %a5,%a0@ | store start of physical memory 148 movl #CACHE_OFF,%d0 149 movc %d0,%cacr | clear and disable on-chip cache(s) 150 151 /* ask the Bug what we are... */ 152 clrl %sp@- 153 CALLBUG(MVMEPROM_GETBRDID) 154 movl %sp@+,%a1 155 156 /* copy to a struct mvmeprom_brdid */ 157 movl #MVMEPROM_BRDID_SIZE,%d0 158 RELOC(boardid,%a0) 1591: movb %a1@+,%a0@+ 160 subql #1,%d0 161 jbne 1b 162 163 /* 164 * Grab the model number from _boardid and use the value 165 * to setup machineid, cputype, and mmutype. 166 */ 167 clrl %d0 168 RELOC(boardid,%a1) 169 movw %a1@(MVMEPROM_BRDID_MODEL_OFFSET),%d0 170 RELOC(machineid,%a0) 171 movl %d0,%a0@ 172 173 ASRELOC(Lbrdid2mach,%a0) 174Lbrdmatch: 175 cmpw %a0@+,%d0 176 jbeq Lgotmatch 177 addw #0x12,%a0 | Each entry is 20-2 bytes long 178 tstw %a0@ 179 jbne Lbrdmatch 180 181 /* 182 * If we fall to here, the board is not supported. 183 * Print a warning, then drop out to the Bug. 184 */ 185 movl #Lenotconf,%sp@- 186 movl #Lnotconf,%sp@- 187 CALLBUG(MVMEPROM_OUTSTRCRLF) 188 addql #8,%sp | clean up stack after call 189 190 CALLBUG(MVMEPROM_EXIT) 191 /* NOTREACHED */ 192 193 .data 194Lnotconf: 195 .ascii "Sorry, the kernel isn't configured for this model." 196Lenotconf: 197 .even 198 199ASLOCAL(Lbrdid2mach) 200#ifdef MVME147 201 .word MVME_147 202 .word CPU_68030 203 .word MMU_68030 204 .word FPU_68882 205 .long _C_LABEL(busaddrerr2030) 206 .long _C_LABEL(busaddrerr2030) 207 .long Linit147 208#endif 209#ifdef MVME162 210 .word MVME_162 211 .word CPU_68040 212 .word MMU_68040 213 .word FPU_68040 214 .long _C_LABEL(buserr40) 215 .long _C_LABEL(addrerr4060) 216 .long Linit1x2 217#endif 218#ifdef MVME167 219 .word MVME_167 220 .word CPU_68040 221 .word MMU_68040 222 .word FPU_68040 223 .long _C_LABEL(buserr40) 224 .long _C_LABEL(addrerr4060) 225 .long Linit1x7 226#endif 227#ifdef MVME172 228 .word MVME_172 229 .word CPU_68060 230 .word MMU_68040 231 .word FPU_68060 232 .long _C_LABEL(buserr60) 233 .long _C_LABEL(addrerr4060) 234 .long Linit1x2 235#endif 236#ifdef MVME177 237 .word MVME_177 238 .word CPU_68060 239 .word MMU_68040 240 .word FPU_68060 241 .long _C_LABEL(buserr60) 242 .long _C_LABEL(addrerr4060) 243 .long Linit1x7 244#endif 245 .word 0 246 .text 247 .even 248 249/* 250 * We have a match, so the kernel should support this board. 251 * a0 points to the matching entry in Lbrdid2mach. 252 */ 253Lgotmatch: 254 movew %a0@+,%d1 | Copy the CPU type 255 extl %d1 256 RELOC(cputype,%a1) 257 movel %d1,%a1@ 258 movew %a0@+,%d1 | Copy the MMU type 259 extl %d1 260 RELOC(mmutype,%a1) 261 movel %d1,%a1@ 262 movew %a0@+,%d1 | Copy the FPU type 263 extl %d1 264 RELOC(fputype,%a1) 265 movel %d1,%a1@ 266 movel %a0@+,%a2 | Fetch the bus error vector 267 RELOC(vectab,%a1) 268 movl %a2,%a1@(8) 269 movel %a0@+,%a2 | Fetch the address error vector 270 movl %a2,%a1@(12) 271 movel %a0@,%a0 | Finally, the board-specific init code 272 jmp %a0@ 273 274 275#ifdef MVME147 276Linit147: 277 /* MVME-147 - 68030 CPU/MMU, 68882 FPU */ 278 /* XXXCDC SHUTUP 147 CALL */ 279 movb #0, 0xfffe1026 | serial interrupt off 280 movb #0, 0xfffe1018 | timer 1 off 281 movb #0, 0xfffe1028 | ethernet off 282 /* XXXCDC SHUTUP 147 CALL */ 283 284 /* Save our ethernet address */ 285 RELOC(mvme_ea, %a0) 286 lea 0xfffe0778,%a1 | XXXCDC -- HARDWIRED HEX 287 movb #0x08,%a0@+ 288 clrb %a0@+ 289 movb #0x3e,%a0@+ 290 movql #0x0f,%d0 291 andb %a1@+,%d0 292 orb #0x20,%d0 293 movb %d0,%a0@+ 294 movb %a1@+,%a0@+ 295 movb %a1@,%a0@ 296 297 /* 298 * Fix up the physical addresses of the MVME147's onboard 299 * I/O registers. 300 */ 301 RELOC(intiobase_phys, %a0); 302 movl #INTIOBASE147,%a0@ 303 RELOC(intiotop_phys, %a0); 304 movl #INTIOTOP147,%a0@ 305 306 /* initialise list of physical memory segments for pmap_bootstrap */ 307 RELOC(phys_seg_list, %a0) 308 movl %a5,%a0@ | phys_seg_list[0].ps_start 309 movl 0xfffe0774,%d1 | End + 1 of onboard memory 310 movl %d1,%a0@(4) | phys_seg_list[0].ps_end 311 clrl %a0@(8) | phys_seg_list[0].ps_startpage 312 313 /* offboard RAM */ 314 clrl %a0@(0x0c) | phys_seg_list[1].ps_start 315 movl #PAGE_SIZE-1,%d0 316 addl 0xfffe0764,%d0 | Start of offboard segment 317 andl #-PAGE_SIZE,%d0 | Round up to page boundary 318 jbeq Lsavmaxmem | Jump if none defined 319 movl #PAGE_SIZE,%d1 | Note: implicit '+1' 320 addl 0xfffe0768,%d1 | End of offboard segment 321 andl #-PAGE_SIZE,%d1 | Round up to page boundary 322 cmpl %d1,%d0 | Quick and dirty validity check 323 jbcs Loff_ok | Yup, looks good. 324 movel %a0@(4),%d1 | Just use onboard RAM otherwise 325 jbra Lsavmaxmem 326Loff_ok: 327 movl %d0,%a0@(0x0c) | phys_seg_list[1].ps_start 328 movl %d1,%a0@(0x10) | phys_seg_list[1].ps_end 329 clrl %a0@(0x14) | phys_seg_list[1].ps_startpage 330 331 /* 332 * Offboard RAM needs to be cleared to zero to initialise parity 333 * on most VMEbus RAM cards. Without this, some cards will buserr 334 * when first read. 335 */ 336 movel %d0,%a0 | offboard start address again. 337Lclearoff: 338 clrl %a0@+ | zap a word 339 cmpl %a0,%d1 | reached end? 340 jbne Lclearoff 341 342Lsavmaxmem: 343 moveq #PGSHIFT,%d2 344 lsrl %d2,%d1 | convert to page (click) number 345 RELOC(maxmem, %a0) 346 movl %d1,%a0@ | save as maxmem 347 jra Lstart1 348#endif 349 350#if defined(MVME162) || defined(MVME172) 351Linit1x2: 352 /* MVME-162 - 68040 CPU/MMU/FPU */ 353 /* MVME-172 - 68060 CPU/MMU/FPU */ 354 355 /* 356 * Verify the user has removed the GPIO#0 jumper... 357 */ 358 btst #0,0xfff4202d | Clear == jumper installed 359 jne 1f | Ok. 360 361 movl #Le1x2jump,%sp@- 362 movl #L1x2jump,%sp@- 363 CALLBUG(MVMEPROM_OUTSTRCRLF) 364 addql #8,%sp | clean up stack after call 365 366 CALLBUG(MVMEPROM_EXIT) 367 /* NOTREACHED */ 368 3691: 370 /* 371 * Determine if this board has a VMEchip2 372 */ 373 btst #1,0xfff4202e | VMEchip2 presence detect 374 jne 2f | Jump if it doesn't exist. 375 376 /* 377 * Disable all interrupts from VMEchip2. This is especially 378 * useful when the kernel doesn't have the VMEchip2 driver 379 * configured. If we didn't do this, then we're at the mercy 380 * of whatever VMEchip2 interrupts the ROM set up. For example, 381 * hitting the ABORT switch could kill the system... 382 */ 383 movl 0xfff40088,%d0 384 andl #0xff7fffff,%d0 | Clear 'MIEN' 385 movl %d0,0xfff40088 3862: 387 /* 388 * Determine how much onboard memory is installed 389 */ 390 movql #0x07,%d0 391 andb 0xfff42024,%d0 392 ASRELOC(Ldramsize1x2,%a0) 393 movl %a0@(%d0:w:4),%d1 | Lookup the size 394 jeq Lmemcquery | Assume a MEMC chip if this is zero. 395 jra Lis1xx_common 396 397 .data 398 .even 399 /* 400 * Table of DRAM register size values -> actual size in bytes 401 */ 402ASLOCAL(Ldramsize1x2) 403 .long 0x00100000 404 .long 0x00200000 405 .long 0x00000000 406 .long 0x00400000 407 .long 0x00400000 408 .long 0x00800000 409 .long 0x00000000 410 .long 0x01000000 411 412L1x2jump: 413 .ascii "You must remove the jumper from pins 15-16 of J22 (mvme162)" 414 .ascii "or pins 1-2\015\012" 415 .ascii "J11 (mvme162-LX) first! See NetBSD/mvme68k FAQ for details." 416Le1x2jump: 417 .even 418 419 .text 420#endif 421 422#if defined(MVME167) || defined(MVME177) 423Linit1x7: 424 /* MVME-167 - 68040 CPU/MMU/FPU */ 425 /* MVME-177 - 68060 CPU/MMU/FPU */ 426 427 /* 428 * Verify the user has removed the GPIO#0 jumper... 429 */ 430 movel #0x00000001,%d0 431 andl 0xfff40088,%d0 | Clear == jumper installed 432 jne 1f | Ok. 433 434 movl #Le1x7jump,%sp@- 435 movl #L1x7jump,%sp@- 436 CALLBUG(MVMEPROM_OUTSTRCRLF) 437 addql #8,%sp | clean up stack after call 438 439 CALLBUG(MVMEPROM_EXIT) 440 /* NOTREACHED */ 441 4421: 443 /* 444 * Disable all interrupts from VMEchip2. This is especially 445 * useful when the kernel doesn't have the VMEchip2 driver 446 * configured. If we didn't do this, then we're at the mercy 447 * of whatever VMEchip2 interrupts the ROM set up. For example, 448 * hitting the ABORT switch could kill the system... 449 */ 450 movl 0xfff40088,%d0 451 andl #0xff7fffff,%d0 | Clear 'MIEN' 452 movl %d0,0xfff40088 453 454 .data 455 .even 456L1x7jump: 457 .ascii "You must remove the jumper from pins 1-2 of J1!\015\012" 458 .ascii "See NetBSD/mvme68k FAQ for details." 459Le1x7jump: 460 .even 461 462 .text 463#endif 464 465#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 466Lmemcquery: 467 /* 468 * Figure out the size of onboard DRAM by querying 469 * the memory controller ASIC(s) 470 */ 471 lea 0xfff43008,%a0 | MEMC040/MEMECC Controller #1 472 jbsr memc040read 473 movl %d0,%d1 474 475 lea 0xfff43108,%a0 | MEMC040/MEMECC Controller #2 476 jbsr memc040read 477 addl %d0,%d1 478 479Lis1xx_common: 480 /* Save our ethernet address */ 481 RELOC(mvme_ea, %a0) 482 lea 0xfffc1f2c,%a1 483 movb %a1@+,%a0@+ 484 movb %a1@+,%a0@+ 485 movb %a1@+,%a0@+ 486 movb %a1@+,%a0@+ 487 movb %a1@+,%a0@+ 488 movb %a1@,%a0@ 489 490 /* 491 * Fix up the physical addresses of the onboard 492 * I/O registers. 493 */ 494 RELOC(intiobase_phys, %a0); 495 movl #INTIOBASE1xx,%a0@ 496 RELOC(intiotop_phys, %a0); 497 movl #INTIOTOP1xx,%a0@ 498 499 /* 500 * Initialise first physical memory segment with onboard RAM details 501 */ 502 RELOC(phys_seg_list, %a0) 503 movl %a5,%a0@ | phys_seg_list[0].ps_start 504 movl %d1,%a0@(4) | phys_seg_list[0].ps_end 505 clrl %a0@(8) | phys_seg_list[0].ps_startpage 506 507 /* offboard RAM */ 508 clrl %a0@(0x0c) | phys_seg_list[1].ps_start 509 movl #PAGE_SIZE-1,%d0 510 addl 0xfffc0000,%d0 | Start of offboard segment 511 andl #-PAGE_SIZE,%d0 | Round up to page boundary 512 jbeq Ldone1xx | Jump if none defined 513 movl #PAGE_SIZE,%d1 | Note: implicit '+1' 514 addl 0xfffc0004,%d1 | End of offboard segment 515 andl #-PAGE_SIZE,%d1 | Round up to page boundary 516 cmpl %d1,%d0 | Quick and dirty validity check 517 jbcs Lramsave1xx | Yup, looks good. 518 movel %a0@(4),%d1 | Just use onboard RAM otherwise 519 jbra Ldone1xx 520 521Lramsave1xx: 522 movl %d0,%a0@(0x0c) | phys_seg_list[1].ps_start 523 movl %d1,%a0@(0x10) | phys_seg_list[1].ps_end 524 clrl %a0@(0x14) | phys_seg_list[1].ps_startpage 525 526 /* 527 * Offboard RAM needs to be cleared to zero to initialise parity 528 * on most VMEbus RAM cards. Without this, some cards will buserr 529 * when first read. 530 */ 531 movel %d0,%a0 | offboard start address again. 532Lramclr1xx: 533 clrl %a0@+ | zap a word 534 cmpl %a0,%d1 | reached end? 535 jbne Lramclr1xx 536 537Ldone1xx: 538 moveq #PGSHIFT,%d2 539 lsrl %d2,%d1 | convert to page (click) number 540 RELOC(maxmem, %a0) 541 movl %d1,%a0@ | save as maxmem 542 543 /* FALLTHROUGH to Lstart1 */ 544#endif 545 546 547Lstart1: 548/* initialize source/destination control registers for movs */ 549 moveq #FC_USERD,%d0 | user space 550 movc %d0,%sfc | as source 551 movc %d0,%dfc | and destination of transfers 552/* 553 * configure kernel and lwp0 VA space so we can get going 554 */ 555#if NKSYMS || defined(DDB) || defined(LKM) 556 RELOC(esym,%a0) | end of static kernel text/data syms 557 movl %a0@,%d2 558 jne Lstart2 559#endif 560 movl #_C_LABEL(end),%d2 | end of static kernel text/data 561Lstart2: 562 addl #PAGE_SIZE-1,%d2 563 andl #PG_FRAME,%d2 | round to a page 564 movl %d2,%a4 565 addl %a5,%a4 | convert to PA 566 pea %a5@ | firstpa 567 pea %a4@ | nextpa 568 RELOC(pmap_bootstrap,%a0) 569 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 570 addql #8,%sp 571 572/* 573 * Enable the MMU. 574 * Since the kernel is mapped logical == physical, we just turn it on. 575 */ 576 RELOC(Sysseg_pa, %a0) | system segment table addr 577 movl %a0@,%d1 | read value (a PA) 578 RELOC(mmutype, %a0) 579 cmpl #MMU_68040,%a0@ | 68040? 580 jne Lmotommu1 | no, skip 581 .long 0x4e7b1807 | movc d1,srp 582 jra Lstploaddone 583Lmotommu1: 584 RELOC(protorp, %a0) 585 movl #0x80000202,%a0@ | nolimit + share global + 4 byte PTEs 586 movl %d1,%a0@(4) | + segtable address 587 pmove %a0@,%srp | load the supervisor root pointer 588 movl #0x80000002,%a0@ | reinit upper half for CRP loads 589Lstploaddone: 590 RELOC(mmutype, %a0) 591 cmpl #MMU_68040,%a0@ | 68040? 592 jne Lmotommu2 | no, skip 593 moveq #0,%d0 | ensure TT regs are disabled 594 .long 0x4e7b0004 | movc d0,itt0 595 .long 0x4e7b0005 | movc d0,itt1 596 .long 0x4e7b0006 | movc d0,dtt0 597 .long 0x4e7b0007 | movc d0,dtt1 598 .word 0xf4d8 | cinva bc 599 .word 0xf518 | pflusha 600 movl #0x8000,%d0 601 .long 0x4e7b0003 | movc d0,tc 602#ifdef M68060 603 RELOC(cputype, %a0) 604 cmpl #CPU_68060,%a0@ | 68060? 605 jne Lnot060cache 606 movl #1,%d0 607 .long 0x4e7b0808 | movcl d0,pcr 608 movl #0xa0808000,%d0 609 movc %d0,%cacr | enable store buffer, both caches 610 jmp Lenab1 611Lnot060cache: 612#endif 613 movl #0x80008000,%d0 614 movc %d0,%cacr | turn on both caches 615 jmp Lenab1 616Lmotommu2: 617 movl #0x82c0aa00,%sp@- | value to load TC with 618 pmove %sp@,%tc | load it 619 620/* 621 * Should be running mapped from this point on 622 */ 623Lenab1: 624/* Point the CPU VBR at our vector table */ 625 movc %vbr,%d0 | Preserve Bug's VBR address 626 movl %d0,_ASM_LABEL(bug_vbr) 627 movl #_C_LABEL(vectab),%d0 | get our VBR address 628 movc %d0,%vbr 629 lea _ASM_LABEL(tmpstk),%sp | temporary stack 630/* call final pmap setup */ 631 jbsr _C_LABEL(pmap_bootstrap_finalize) 632/* set kernel stack, user SP */ 633 movl _C_LABEL(lwp0uarea),%a1 | get lwp0 uarea 634 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 635 movl #USRSTACK-4,%a2 636 movl %a2,%usp | init user SP 637 tstl _C_LABEL(fputype) | Have an FPU? 638 jeq Lenab2 | No, skip. 639 clrl %a1@(PCB_FPCTX) | ensure null FP context 640 movl %a1,%sp@- 641 jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) 642 addql #4,%sp 643Lenab2: 644 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 645 jeq Ltbia040 | yes, cache already on 646 pflusha 647 movl #CACHE_ON,%d0 648 movc %d0,%cacr | clear cache(s) 649 jra Lenab3 650Ltbia040: 651 .word 0xf518 652Lenab3: 653/* 654 * final setup for C code: 655 * Create a fake exception frame so that cpu_lwp_fork() can copy it. 656 * main() nevers returns; we exit to user mode from a forked process 657 * later on. 658 */ 659 jbsr _C_LABEL(mvme68k_init) | additional pre-main initialization 660 movw #PSL_LOWIPL,%sr | lower SPL 661 clrw %sp@- | vector offset/frame type 662 clrl %sp@- | PC - filled in by "execve" 663 movw #PSL_USER,%sp@- | in user mode 664 clrl %sp@- | stack adjust count and padding 665 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 666 lea _C_LABEL(lwp0),%a0 | save pointer to frame 667 movl %sp,%a0@(L_MD_REGS) | in lwp0.l_md.md_regs 668 669 jra _C_LABEL(main) | main() 670 671#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 672/* 673 * Probe for a memory controller ASIC (MEMC040 or MEMECC) at the 674 * address in a0. If found, return the size in bytes of any RAM 675 * controlled by the ASIC in d0. Otherwise return zero. 676 */ 677ASLOCAL(memc040read) 678 moveml %d1-%d2/%a1-%a2,%sp@- | save scratch regs 679 movc %vbr,%d2 | Save vbr 680 RELOC(vectab,%a2) | Install our own vectab, temporarily 681 movc %a2,%vbr 682 ASRELOC(Lmemc040berr,%a1) | get address of bus error handler 683 movl %a2@(8),%sp@- | Save current bus error handler addr 684 movl %a1,%a2@(8) | Install our own handler 685 movl %sp,%d0 | Save current stack pointer value 686 movql #0x07,%d1 687 andb %a0@,%d1 | Access MEMC040/MEMECC 688 movl #0x400000,%d0 689 lsll %d1,%d0 | Convert to memory size, in bytes 690Lmemc040ret: 691 movc %d2,%vbr | Restore original vbr 692 movl %sp@+,%a2@(8) | Restore original bus error handler 693 moveml %sp@+,%d1-%d2/%a1-%a2 694 rts 695/* 696 * If the memory controller doesn't exist, we get a bus error trying 697 * to access a0@ above. Control passes here, where we flag 'no bytes', 698 * ditch the exception frame and return as normal. 699 */ 700Lmemc040berr: 701 movl %d0,%sp | Get rid of the exception frame 702 movql #0,%d0 | No ASIC at this location, then! 703 jbra Lmemc040ret | Done 704#endif 705 706/* 707 * Trap/interrupt vector routines 708 */ 709#include <m68k/m68k/trap_subr.s> 710 711#if defined(M68040) || defined(M68060) 712ENTRY_NOPROFILE(addrerr4060) 713 clrl %sp@- | stack adjust count 714 moveml #0xFFFF,%sp@- | save user registers 715 movl %usp,%a0 | save the user SP 716 movl %a0,%sp@(FR_SP) | in the savearea 717 movl %sp@(FR_HW+8),%sp@- 718 clrl %sp@- | dummy code 719 movl #T_ADDRERR,%sp@- | mark address error 720 jra _ASM_LABEL(faultstkadj) | and deal with it 721#endif 722 723#if defined(M68060) 724ENTRY_NOPROFILE(buserr60) 725 clrl %sp@- | stack adjust count 726 moveml #0xFFFF,%sp@- | save user registers 727 movl %usp,%a0 | save the user SP 728 movl %a0,%sp@(FR_SP) | in the savearea 729 movel %sp@(FR_HW+12),%d0 | FSLW 730 btst #2,%d0 | branch prediction error? 731 jeq Lnobpe 732 movc %cacr,%d2 733 orl #IC60_CABC,%d2 | clear all branch cache entries 734 movc %d2,%cacr 735 movl %d0,%d1 736 andl #0x7ffd,%d1 737 jeq _ASM_LABEL(faultstkadjnotrap2) 738Lnobpe: 739| we need to adjust for misaligned addresses 740 movl %sp@(FR_HW+8),%d1 | grab VA 741 btst #27,%d0 | check for mis-aligned access 742 jeq Lberr3 | no, skip 743 addl #28,%d1 | yes, get into next page 744 | operand case: 3, 745 | instruction case: 4+12+12 746 andl #PG_FRAME,%d1 | and truncate 747Lberr3: 748 movl %d1,%sp@- 749 movl %d0,%sp@- | code is FSLW now. 750 andw #0x1f80,%d0 751 jeq Lberr60 | it is a bus error 752 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 753 jra _ASM_LABEL(faultstkadj) | and deal with it 754Lberr60: 755 tstl _C_LABEL(nofault) | catch bus error? 756 jeq Lisberr | no, handle as usual 757 movl _C_LABEL(nofault),%sp@- | yes, 758 jbsr _C_LABEL(longjmp) | longjmp(nofault) 759 /* NOTREACHED */ 760#endif 761#if defined(M68040) 762ENTRY_NOPROFILE(buserr40) 763 clrl %sp@- | stack adjust count 764 moveml #0xFFFF,%sp@- | save user registers 765 movl %usp,%a0 | save the user SP 766 movl %a0,%sp@(FR_SP) | in the savearea 767 movl %sp@(FR_HW+20),%d1 | get fault address 768 moveq #0,%d0 769 movw %sp@(FR_HW+12),%d0 | get SSW 770 btst #11,%d0 | check for mis-aligned 771 jeq Lbe1stpg | no skip 772 addl #3,%d1 | get into next page 773 andl #PG_FRAME,%d1 | and truncate 774Lbe1stpg: 775 movl %d1,%sp@- | pass fault address. 776 movl %d0,%sp@- | pass SSW as code 777 btst #10,%d0 | test ATC 778 jeq Lberr40 | it is a bus error 779 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 780 jra _ASM_LABEL(faultstkadj) | and deal with it 781Lberr40: 782 tstl _C_LABEL(nofault) | catch bus error? 783 jeq Lisberr | no, handle as usual 784 movl _C_LABEL(nofault),%sp@- | yes, 785 jbsr _C_LABEL(longjmp) | longjmp(nofault) 786 /* NOTREACHED */ 787#endif 788 789#if defined(M68020) || defined(M68030) 790ENTRY_NOPROFILE(busaddrerr2030) 791 clrl %sp@- | stack adjust count 792 moveml #0xFFFF,%sp@- | save user registers 793 movl %usp,%a0 | save the user SP 794 movl %a0,%sp@(FR_SP) | in the savearea 795 moveq #0,%d0 796 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 797 btst #12,%d0 | RB set? 798 jeq LbeX0 | no, test RC 799 bset #14,%d0 | yes, must set FB 800 movw %d0,%sp@(FR_HW+10) | for hardware too 801LbeX0: 802 btst #13,%d0 | RC set? 803 jeq LbeX1 | no, skip 804 bset #15,%d0 | yes, must set FC 805 movw %d0,%sp@(FR_HW+10) | for hardware too 806LbeX1: 807 btst #8,%d0 | data fault? 808 jeq Lbe0 | no, check for hard cases 809 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 810 jra Lbe10 | thats it 811Lbe0: 812 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 813 jne Lbe4 | yes, go handle 814 movl %sp@(FR_HW+2),%d1 | no, can use save PC 815 btst #14,%d0 | FB set? 816 jeq Lbe3 | no, try FC 817 addql #4,%d1 | yes, adjust address 818 jra Lbe10 | done 819Lbe3: 820 btst #15,%d0 | FC set? 821 jeq Lbe10 | no, done 822 addql #2,%d1 | yes, adjust address 823 jra Lbe10 | done 824Lbe4: 825 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 826 btst #15,%d0 | FC set? 827 jeq Lbe10 | no, all done 828 subql #2,%d1 | yes, adjust address 829Lbe10: 830 movl %d1,%sp@- | push fault VA 831 movl %d0,%sp@- | and padded SSW 832 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 833 andw #0x0FFF,%d0 | clear out frame format 834 cmpw #12,%d0 | address error vector? 835 jeq Lisaerr | yes, go to it 836 movl %d1,%a0 | fault address 837 movl %sp@,%d0 | function code from ssw 838 btst #8,%d0 | data fault? 839 jne Lbe10a 840 movql #1,%d0 | user program access FC 841 | (we dont separate data/program) 842 btst #5,%sp@(FR_HW+8) | supervisor mode? 843 jeq Lbe10a | if no, done 844 movql #5,%d0 | else supervisor program access 845Lbe10a: 846 ptestr %d0,%a0@,#7 | do a table search 847 pmove %psr,%sp@ | save result 848 movb %sp@,%d1 849 btst #2,%d1 | invalid (incl. limit viol. and berr)? 850 jeq Lmightnotbemerr | no -> wp check 851 btst #7,%d1 | is it MMU table berr? 852 jne Lisberr1 | yes, needs not be fast. 853Lismerr: 854 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 855 jra _ASM_LABEL(faultstkadj) | and deal with it 856Lmightnotbemerr: 857 btst #3,%d1 | write protect bit set? 858 jeq Lisberr1 | no: must be bus error 859 movl %sp@,%d0 | ssw into low word of d0 860 andw #0xc0,%d0 | Write protect is set on page: 861 cmpw #0x40,%d0 | was it read cycle? 862 jne Lismerr | no, was not WPE, must be MMU fault 863 jra Lisberr1 | real bus err needs not be fast. 864Lisaerr: 865 movl #T_ADDRERR,%sp@- | mark address error 866 jra _ASM_LABEL(faultstkadj) | and deal with it 867Lisberr1: 868 clrw %sp@ | re-clear pad word 869 tstl _C_LABEL(nofault) | catch bus error? 870 jeq Lisberr | no, handle as usual 871 movl _C_LABEL(nofault),%sp@- | yes, 872 jbsr _C_LABEL(longjmp) | longjmp(nofault) 873 /* NOTREACHED */ 874#endif /* M68020 || M68030 */ 875 876Lisberr: | also used by M68040/60 877 movl #T_BUSERR,%sp@- | mark bus error 878 jra _ASM_LABEL(faultstkadj) | and deal with it 879 880/* 881 * FP exceptions. 882 */ 883ENTRY_NOPROFILE(fpfline) 884#if defined(M68040) 885 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 886 jne Lfp_unimp | no, skip FPSP 887 cmpw #0x202c,%sp@(6) | format type 2? 888 jne _C_LABEL(illinst) | no, not an FP emulation 889#ifdef FPSP 890 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 891#else 892 clrl %sp@- | stack adjust count 893 moveml #0xFFFF,%sp@- | save registers 894 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 895 jra _ASM_LABEL(fault) | do it 896#endif 897Lfp_unimp: 898#endif /* M68040 */ 899 jra _C_LABEL(illinst) 900 901ENTRY_NOPROFILE(fpunsupp) 902#if defined(M68040) 903 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 904 jne Lfp_unsupp | No, skip FPSP 905#ifdef FPSP 906 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 907#else 908 clrl %sp@- | stack adjust count 909 moveml #0xFFFF,%sp@- | save registers 910 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 911 jra _ASM_LABEL(fault) | do it 912#endif 913Lfp_unsupp: 914#endif /* M68040 */ 915 jra _C_LABEL(illinst) 916 917/* 918 * Handles all other FP coprocessor exceptions. 919 * Note that since some FP exceptions generate mid-instruction frames 920 * and may cause signal delivery, we need to test for stack adjustment 921 * after the trap call. 922 */ 923ENTRY_NOPROFILE(fpfault) 924 clrl %sp@- | stack adjust count 925 moveml #0xFFFF,%sp@- | save user registers 926 movl %usp,%a0 | and save 927 movl %a0,%sp@(FR_SP) | the user stack pointer 928 clrl %sp@- | no VA arg 929 movl _C_LABEL(curpcb),%a0 | current pcb 930 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 931 fsave %a0@ | save state 932#if defined(M68040) || defined(M68060) 933 /* always null state frame on 68040, 68060 */ 934 cmpl #FPU_68040,_C_LABEL(fputype) 935 jge Lfptnull 936#endif 937 tstb %a0@ | null state frame? 938 jeq Lfptnull | yes, safe 939 clrw %d0 | no, need to tweak BIU 940 movb %a0@(1),%d0 | get frame size 941 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 942Lfptnull: 943 fmovem %fpsr,%sp@- | push fpsr as code argument 944 frestore %a0@ | restore state 945 movl #T_FPERR,%sp@- | push type arg 946 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 947 948 949/* 950 * Other exceptions only cause four and six word stack frame and require 951 * no post-trap stack adjustment. 952 */ 953 954ENTRY_NOPROFILE(badtrap) 955 moveml #0xC0C0,%sp@- | save scratch regs 956 movw %sp@(22),%sp@- | push exception vector info 957 clrw %sp@- 958 movl %sp@(22),%sp@- | and PC 959 jbsr _C_LABEL(straytrap) | report 960 addql #8,%sp | pop args 961 moveml %sp@+,#0x0303 | restore regs 962 jra _ASM_LABEL(rei) | all done 963 964ENTRY_NOPROFILE(trap0) 965 clrl %sp@- | stack adjust count 966 moveml #0xFFFF,%sp@- | save user registers 967 movl %usp,%a0 | save the user SP 968 movl %a0,%sp@(FR_SP) | in the savearea 969 movl %d0,%sp@- | push syscall number 970 jbsr _C_LABEL(syscall) | handle it 971 addql #4,%sp | pop syscall arg 972 tstl _C_LABEL(astpending) | AST pending? 973 jne Lrei1 | Yup, go deal with it. 974 movl %sp@(FR_SP),%a0 | grab and restore 975 movl %a0,%usp | user SP 976 moveml %sp@+,#0x7FFF | restore most registers 977 addql #8,%sp | pop SP and stack adjust 978 rte 979 980/* 981 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 982 * cachectl(command, addr, length) 983 * command in d0, addr in a1, length in d1 984 */ 985ENTRY_NOPROFILE(trap12) 986 movl _C_LABEL(curlwp),%a0 987 movl %a0@(L_PROC),%sp@- | push current proc pointer 988 movl %d1,%sp@- | push length 989 movl %a1,%sp@- | push addr 990 movl %d0,%sp@- | push command 991 jbsr _C_LABEL(cachectl1) | do it 992 lea %sp@(16),%sp | pop args 993 jra _ASM_LABEL(rei) | all done 994 995/* 996 * Trace (single-step) trap. Kernel-mode is special. 997 * User mode traps are simply passed on to trap(). 998 */ 999ENTRY_NOPROFILE(trace) 1000 clrl %sp@- | stack adjust count 1001 moveml #0xFFFF,%sp@- 1002 moveq #T_TRACE,%d0 1003 1004 | Check PSW and see what happen. 1005 | T=0 S=0 (should not happen) 1006 | T=1 S=0 trace trap from user mode 1007 | T=0 S=1 trace trap on a trap instruction 1008 | T=1 S=1 trace trap from system mode (kernel breakpoint) 1009 1010 movw %sp@(FR_HW),%d1 | get PSW 1011 notw %d1 | XXX no support for T0 on 680[234]0 1012 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 1013 jeq Lkbrkpt | yes, kernel breakpoint 1014 jra _ASM_LABEL(fault) | no, user-mode fault 1015 1016/* 1017 * Trap 15 is used for: 1018 * - GDB breakpoints (in user programs) 1019 * - KGDB breakpoints (in the kernel) 1020 * - trace traps for SUN binaries (not fully supported yet) 1021 * User mode traps are simply passed to trap(). 1022 */ 1023ENTRY_NOPROFILE(trap15) 1024 clrl %sp@- | stack adjust count 1025 moveml #0xFFFF,%sp@- 1026 moveq #T_TRAP15,%d0 1027 movw %sp@(FR_HW),%d1 | get PSW 1028 andw #PSL_S,%d1 | from system mode? 1029 jne Lkbrkpt | yes, kernel breakpoint 1030 jra _ASM_LABEL(fault) | no, user-mode fault 1031 1032Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type) 1033 | Save the system sp rather than the user sp. 1034 movw #PSL_HIGHIPL,%sr | lock out interrupts 1035 lea %sp@(FR_SIZE),%a6 | Save stack pointer 1036 movl %a6,%sp@(FR_SP) | from before trap 1037 1038 | If were are not on tmpstk switch to it. 1039 | (so debugger can change the stack pointer) 1040 movl %a6,%d1 1041 cmpl #_ASM_LABEL(tmpstk),%d1 1042 jls Lbrkpt2 | already on tmpstk 1043 | Copy frame to the temporary stack 1044 movl %sp,%a0 | a0=src 1045 lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst 1046 movl %a1,%sp | sp=new frame 1047 movql #FR_SIZE,%d1 1048Lbrkpt1: 1049 movl %a0@+,%a1@+ 1050 subql #4,%d1 1051 jbgt Lbrkpt1 1052 1053Lbrkpt2: 1054 | Call the trap handler for the kernel debugger. 1055 | Do not call trap() to do it, so that we can 1056 | set breakpoints in trap() if we want. We know 1057 | the trap type is either T_TRACE or T_BREAKPOINT. 1058 | If we have both DDB and KGDB, let KGDB see it first, 1059 | because KGDB will just return 0 if not connected. 1060 | Save args in d2, a2 1061 movl %d0,%d2 | trap type 1062 movl %sp,%a2 | frame ptr 1063#ifdef KGDB 1064 | Let KGDB handle it (if connected) 1065 movl %a2,%sp@- | push frame ptr 1066 movl %d2,%sp@- | push trap type 1067 jbsr _C_LABEL(kgdb_trap) | handle the trap 1068 addql #8,%sp | pop args 1069 cmpl #0,%d0 | did kgdb handle it? 1070 jne Lbrkpt3 | yes, done 1071#endif 1072#ifdef DDB 1073 | Let DDB handle it 1074 movl %a2,%sp@- | push frame ptr 1075 movl %d2,%sp@- | push trap type 1076 jbsr _C_LABEL(kdb_trap) | handle the trap 1077 addql #8,%sp | pop args 1078#endif 1079 /* Sun 3 drops into PROM here. */ 1080Lbrkpt3: 1081 | The stack pointer may have been modified, or 1082 | data below it modified (by kgdb push call), 1083 | so push the hardware frame at the current sp 1084 | before restoring registers and returning. 1085 1086 movl %sp@(FR_SP),%a0 | modified sp 1087 lea %sp@(FR_SIZE),%a1 | end of our frame 1088 movl %a1@-,%a0@- | copy 2 longs with 1089 movl %a1@-,%a0@- | ... predecrement 1090 movl %a0,%sp@(FR_SP) | sp = h/w frame 1091 moveml %sp@+,#0x7FFF | restore all but sp 1092 movl %sp@,%sp | ... and sp 1093 rte | all done 1094 1095/* 1096 * Use common m68k sigreturn routine. 1097 */ 1098#include <m68k/m68k/sigreturn.s> 1099 1100/* 1101 * Interrupt handlers. 1102 * 1103 * For auto-vectored interrupts, the CPU provides the 1104 * vector 0x18+level. 1105 * 1106 * intrhand_autovec is the entry point for auto-vectored 1107 * interrupts. 1108 * 1109 * For vectored interrupts, we pull the pc, evec, and exception frame 1110 * and pass them to the vectored interrupt dispatcher. The vectored 1111 * interrupt dispatcher will deal with strays. 1112 * 1113 * intrhand_vectored is the entry point for vectored interrupts. 1114 */ 1115 1116#define INTERRUPT_SAVEREG moveml #0xC0C0,%sp@- 1117#define INTERRUPT_RESTOREREG moveml %sp@+,#0x0303 1118 1119ENTRY_NOPROFILE(intrhand_autovec) 1120 addql #1,_C_LABEL(interrupt_depth) 1121 INTERRUPT_SAVEREG 1122 lea %sp@(16),%a1 | get pointer to frame 1123 movl %a1,%sp@- 1124 jbsr _C_LABEL(isrdispatch_autovec) | call dispatcher 1125 addql #4,%sp 1126 jbra Lintrhand_exit 1127 1128ENTRY_NOPROFILE(intrhand_vectored) 1129 addql #1,_C_LABEL(interrupt_depth) 1130 INTERRUPT_SAVEREG 1131 lea %sp@(16),%a1 | get pointer to frame 1132 movl %a1,%sp@- 1133 movw %sr,%d0 1134 bfextu %d0,21,3,%d0 | Get current ipl 1135 movl %d0,%sp@- | Push it 1136 jbsr _C_LABEL(isrdispatch_vectored) | call dispatcher 1137 addql #8,%sp 1138Lintrhand_exit: 1139 INTERRUPT_RESTOREREG 1140 subql #1,_C_LABEL(interrupt_depth) 1141 1142 /* FALLTHROUGH to rei */ 1143 1144#undef INTERRUPT_SAVEREG 1145#undef INTERRUPT_RESTOREREG 1146 1147/* 1148 * Emulation of VAX REI instruction. 1149 * 1150 * This code deals with checking for and servicing ASTs 1151 * (profiling, scheduling). 1152 * After identifing that we need an AST we drop the IPL to allow device 1153 * interrupts. 1154 * 1155 * This code is complicated by the fact that sendsig may have been called 1156 * necessitating a stack cleanup. 1157 */ 1158ASENTRY_NOPROFILE(rei) 1159 tstl _C_LABEL(astpending) | AST pending? 1160 jeq Ldorte | Nope. Just return. 1161 btst #5,%sp@ | Returning to kernel mode? 1162 jne Ldorte | Yup. Can't do ASTs 1163 movw #PSL_LOWIPL,%sr | lower SPL 1164 clrl %sp@- | stack adjust 1165 moveml #0xFFFF,%sp@- | save all registers 1166 movl %usp,%a1 | including 1167 movl %a1,%sp@(FR_SP) | the users SP 1168Lrei1: clrl %sp@- | VA == none 1169 clrl %sp@- | code == none 1170 movl #T_ASTFLT,%sp@- | type == async system trap 1171 pea %sp@(12) | fp == address of trap frame 1172 jbsr _C_LABEL(trap) | go handle it 1173 lea %sp@(16),%sp | pop value args 1174 movl %sp@(FR_SP),%a0 | restore user SP 1175 movl %a0,%usp | from save area 1176 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 1177 jne Laststkadj | yes, go to it 1178 moveml %sp@+,#0x7FFF | no, restore most user regs 1179 addql #8,%sp | toss SP and stack adjust 1180Ldorte: rte | and do real RTE 1181 1182Laststkadj: 1183 lea %sp@(FR_HW),%a1 | pointer to HW frame 1184 addql #8,%a1 | source pointer 1185 movl %a1,%a0 | source 1186 addw %d0,%a0 | + hole size = dest pointer 1187 movl %a1@-,%a0@- | copy 1188 movl %a1@-,%a0@- | 8 bytes 1189 movl %a0,%sp@(FR_SP) | new SSP 1190 moveml %sp@+,#0x7FFF | restore user registers 1191 movl %sp@,%sp | and our SP 1192 rte | and do real RTE 1193 1194/* 1195 * Use common m68k sigcode. 1196 */ 1197#include <m68k/m68k/sigcode.s> 1198#ifdef COMPAT_SUNOS 1199#include <m68k/m68k/sunos_sigcode.s> 1200#endif 1201#ifdef COMPAT_SVR4 1202#include <m68k/m68k/svr4_sigcode.s> 1203#endif 1204 1205/* 1206 * Primitives 1207 */ 1208 1209/* 1210 * Use common m68k support routines. 1211 */ 1212#include <m68k/m68k/support.s> 1213 1214/* 1215 * Use common m68k process/lwp switch and context save subroutines. 1216 */ 1217#define FPCOPROC /* XXX: Temp. Reqd. */ 1218#include <m68k/m68k/switch_subr.s> 1219 1220 1221#if defined(M68040) || defined(M68060) 1222ENTRY(suline) 1223 movl %sp@(4),%a0 | address to write 1224 movl _C_LABEL(curpcb),%a1 | current pcb 1225 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 1226 movl %sp@(8),%a1 | address of line 1227 movl %a1@+,%d0 | get lword 1228 movsl %d0,%a0@+ | put lword 1229 nop | sync 1230 movl %a1@+,%d0 | get lword 1231 movsl %d0,%a0@+ | put lword 1232 nop | sync 1233 movl %a1@+,%d0 | get lword 1234 movsl %d0,%a0@+ | put lword 1235 nop | sync 1236 movl %a1@+,%d0 | get lword 1237 movsl %d0,%a0@+ | put lword 1238 nop | sync 1239 moveq #0,%d0 | indicate no fault 1240 jra Lsldone 1241Lslerr: 1242 moveq #-1,%d0 1243Lsldone: 1244 movl _C_LABEL(curpcb),%a1 | current pcb 1245 clrl %a1@(PCB_ONFAULT) | clear fault address 1246 rts 1247#endif 1248 1249 1250ENTRY(ecacheon) 1251 rts 1252 1253ENTRY(ecacheoff) 1254 rts 1255 1256/* 1257 * Get callers current SP value. 1258 * Note that simply taking the address of a local variable in a C function 1259 * doesn't work because callee saved registers may be outside the stack frame 1260 * defined by A6 (e.g. GCC generated code). 1261 */ 1262ENTRY_NOPROFILE(getsp) 1263 movl %sp,%d0 | get current SP 1264 addql #4,%d0 | compensate for return address 1265 movl %d0,%a0 1266 rts 1267 1268ENTRY_NOPROFILE(getsfc) 1269 movc %sfc,%d0 1270 movl %d0,%a0 1271 rts 1272 1273ENTRY_NOPROFILE(getdfc) 1274 movc %dfc,%d0 1275 movl %d0,%a0 1276 rts 1277 1278/* 1279 * Load a new user segment table pointer. 1280 */ 1281ENTRY(loadustp) 1282 movl %sp@(4),%d0 | new USTP 1283 moveq #PGSHIFT, %d1 1284 lsll %d1,%d0 | convert to addr 1285#if defined(M68040) || defined(M68060) 1286 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1287 jne LmotommuC | no, skip 1288 .word 0xf518 | pflusha 1289 .long 0x4e7b0806 | movc d0,urp 1290#ifdef M68060 1291 cmpl #CPU_68060,_C_LABEL(cputype) 1292 jne Lldno60 1293 movc %cacr,%d0 1294 orl #IC60_CUBC,%d0 | clear user branch cache entries 1295 movc %d0,%cacr 1296Lldno60: 1297#endif 1298 rts 1299LmotommuC: 1300#endif 1301 pflusha | flush entire TLB 1302 lea _C_LABEL(protorp),%a0 | CRP prototype 1303 movl %d0,%a0@(4) | stash USTP 1304 pmove %a0@,%crp | load root pointer 1305 movl #CACHE_CLR,%d0 1306 movc %d0,%cacr | invalidate cache(s) 1307 rts 1308 1309ENTRY(ploadw) 1310#ifdef M68030 1311#if defined(M68040) || defined(M68060) 1312 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1313 jeq Lploadwskp | yes, skip 1314#endif 1315 movl %sp@(4),%a0 | address to load 1316 ploadw #1,%a0@ | pre-load translation 1317Lploadwskp: 1318#endif 1319 rts 1320 1321ENTRY(getsr) 1322 moveq #0,%d0 1323 movw %sr,%d0 1324 rts 1325 1326/* 1327 * _delay(unsigned N) 1328 * 1329 * Delay for at least (N/1024) microseconds. 1330 * This routine depends on the variable: delay_divisor 1331 * which should be set based on the CPU clock rate. 1332 */ 1333ENTRY_NOPROFILE(_delay) 1334 | d0 = arg = (usecs << 10) 1335 movl %sp@(4),%d0 1336 | d1 = delay_divisor 1337 movl _C_LABEL(delay_divisor),%d1 1338 jra L_delay /* Jump into the loop! */ 1339 1340 /* 1341 * Align the branch target of the loop to a half-line (8-byte) 1342 * boundary to minimize cache effects. This guarantees both 1343 * that there will be no prefetch stalls due to cache line burst 1344 * operations and that the loop will run from a single cache 1345 * half-line. 1346 */ 1347#ifdef __ELF__ 1348 .align 8 1349#else 1350 .align 3 1351#endif 1352L_delay: 1353 subl %d1,%d0 1354 jgt L_delay 1355 rts 1356 1357/* 1358 * Save and restore 68881 state. 1359 */ 1360ENTRY(m68881_save) 1361 movl %sp@(4),%a0 | save area pointer 1362 fsave %a0@ | save state 1363#if defined(M68020) || defined(M68030) || defined(M68040) 1364#if defined(M68060) 1365 cmpl #FPU_68060,_C_LABEL(fputype) 1366 jeq Lm68060fpsave 1367#endif 1368Lm68881fpsave: 1369 tstb %a0@ | null state frame? 1370 jeq Lm68881sdone | yes, all done 1371 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1372 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1373Lm68881sdone: 1374 rts 1375#endif 1376#if defined(M68060) 1377Lm68060fpsave: 1378 tstb %a0@(2) | null state frame? 1379 jeq Lm68060sdone | yes, all done 1380 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1381 fmovem %fpcr,%a0@(FPF_FPCR) | save FP control registers 1382 fmovem %fpsr,%a0@(FPF_FPSR) 1383 fmovem %fpi,%a0@(FPF_FPI) 1384Lm68060sdone: 1385 rts 1386#endif 1387 1388ENTRY(m68881_restore) 1389 movl %sp@(4),%a0 | save area pointer 1390#if defined(M68020) || defined(M68030) || defined(M68040) 1391#if defined(M68060) 1392 cmpl #FPU_68060,_C_LABEL(fputype) 1393 jeq Lm68060fprestore 1394#endif 1395Lm68881fprestore: 1396 tstb %a0@ | null state frame? 1397 jeq Lm68881rdone | yes, easy 1398 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1399 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1400Lm68881rdone: 1401 frestore %a0@ | restore state 1402 rts 1403#endif 1404#if defined(M68060) 1405Lm68060fprestore: 1406 tstb %a0@(2) | null state frame? 1407 jeq Lm68060fprdone | yes, easy 1408 fmovem %a0@(FPF_FPCR),%fpcr | restore FP control registers 1409 fmovem %a0@(FPF_FPSR),%fpsr 1410 fmovem %a0@(FPF_FPI),%fpi 1411 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1412Lm68060fprdone: 1413 frestore %a0@ | restore state 1414 rts 1415#endif 1416 1417/* 1418 * Handle the nitty-gritty of rebooting the machine. 1419 * Basically we just turn off the MMU, restore the Bug's initial VBR 1420 * and either return to Bug or jump through the ROM reset vector 1421 * depending on how the system was halted. 1422 */ 1423ENTRY_NOPROFILE(doboot) 1424 movw #PSL_HIGHIPL,%sr 1425 movl _C_LABEL(boothowto),%d1 | load howto 1426 movl %sp@(4),%d2 | arg 1427 movl _ASM_LABEL(bug_vbr),%d3 | Fetch Bug's original VBR value 1428 movl _C_LABEL(machineid),%d4 | What type of board is this? 1429 movl #CACHE_OFF,%d0 1430#if defined(M68040) || defined(M68060) 1431 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/68060? 1432 jne Lnocache0 | no, skip 1433 .word 0xf4f8 | cpusha bc - push and invalidate caches 1434 nop 1435 movl #CACHE40_OFF,%d0 1436#endif 1437Lnocache0: 1438 movc %d0,%cacr | disable on-chip cache(s) 1439 1440#if defined(M68040) || defined(M68060) 1441 cmpl #MMU_68040,_C_LABEL(mmutype) 1442 jne LmotommuF 1443 movql #0,%d0 1444 movc %d0,%cacr 1445 .long 0x4e7b0003 | movc d0,tc 1446 jra Lbootcommon 1447LmotommuF: 1448#endif 1449 clrl %sp@- | value for pmove to TC (turn off MMU) 1450 pmove %sp@,%tc | disable MMU 1451 addql #4,%sp 1452 1453Lbootcommon: 1454 /* 1455 * MMU Switched off by now, so relocate all absolute references 1456 */ 1457 ASRELOC(tmpstk, %sp) | physical SP in case of NMI 1458 movc %d3,%vbr | Restore Bug's VBR 1459 andl #RB_SBOOT, %d1 | mask off 1460 jbne Lsboot | sboot? 1461 /* NOT sboot */ 1462 tstl %d2 | autoboot? 1463 jbeq Ldoreset | yes! 1464 CALLBUG(MVMEPROM_EXIT) | return to bug 1465 /* NOTREACHED */ 1466 1467Ldoreset: 1468 movl #0xff800000,%a0 | Bug's reset vector address 1469 movl %a0@+, %a7 | get SP 1470 movl %a0@, %a0 | get PC 1471 jmp %a0@ | go! 1472 1473Lsboot: /* sboot */ 1474 tstl %d2 | autoboot? 1475 jbeq 1f | yes! 1476 jmp 0x4000 | back to sboot 14771: jmp 0x400a | tell sboot to reboot us 1478 1479 1480/* 1481 * Misc. global variables. 1482 */ 1483 .data 1484 1485GLOBAL(machineid) 1486 .long MVME_147 | default to MVME_147 1487 1488GLOBAL(mmutype) 1489 .long MMU_68030 | default to MMU_68030 1490 1491GLOBAL(cputype) 1492 .long CPU_68030 | default to CPU_68030 1493 1494GLOBAL(fputype) 1495 .long FPU_68882 | default to FPU_68882 1496 1497GLOBAL(protorp) 1498 .long 0,0 | prototype root pointer 1499 1500/* 1501 * Information from first stage boot program 1502 */ 1503GLOBAL(bootpart) 1504 .long 0 1505GLOBAL(bootdevlun) 1506 .long 0 1507GLOBAL(bootctrllun) 1508 .long 0 1509GLOBAL(bootaddr) 1510 .long 0 1511 1512GLOBAL(intiobase) 1513 .long 0 | KVA of base of internal IO space 1514 1515GLOBAL(intiolimit) 1516 .long 0 | KVA of end of internal IO space 1517 1518GLOBAL(intiobase_phys) 1519 .long 0 | PA of board's I/O registers 1520 1521GLOBAL(intiotop_phys) 1522 .long 0 | PA of top of board's I/O registers 1523 1524/* 1525 * interrupt counters. 1526 * XXXSCW: Will go away soon; kept here to keep vmstat happy 1527 */ 1528GLOBAL(intrnames) 1529 .asciz "spur" 1530 .asciz "lev1" 1531 .asciz "lev2" 1532 .asciz "lev3" 1533 .asciz "lev4" 1534 .asciz "clock" 1535 .asciz "lev6" 1536 .asciz "nmi" 1537 .asciz "statclock" 1538GLOBAL(eintrnames) 1539 .even 1540 1541GLOBAL(intrcnt) 1542 .long 0,0,0,0,0,0,0,0,0,0 1543GLOBAL(eintrcnt) 1544