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