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