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