1 /* $NetBSD: machdep.c,v 1.3 2002/04/23 12:41:06 kleink Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "opt_compat_netbsd.h" 35 #include "opt_mvmetype.h" 36 #include "opt_ddb.h" 37 38 #include <sys/param.h> 39 #include <sys/buf.h> 40 #include <sys/conf.h> 41 #include <sys/device.h> 42 #include <sys/exec.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 #include <sys/map.h> 46 #include <sys/mbuf.h> 47 #include <sys/mount.h> 48 #include <sys/msgbuf.h> 49 #include <sys/proc.h> 50 #include <sys/reboot.h> 51 #include <sys/syscallargs.h> 52 #include <sys/syslog.h> 53 #include <sys/systm.h> 54 #include <sys/user.h> 55 56 #include <uvm/uvm_extern.h> 57 58 #include <sys/sysctl.h> 59 60 #include <net/netisr.h> 61 62 #include <machine/autoconf.h> 63 #include <machine/bat.h> 64 #include <machine/bootinfo.h> 65 #include <machine/bus.h> 66 #include <machine/intr.h> 67 #include <machine/pmap.h> 68 #include <machine/platform.h> 69 #include <machine/powerpc.h> 70 #include <machine/trap.h> 71 72 #include <dev/cons.h> 73 74 #if 0 75 #include "vga.h" 76 #if (NVGA > 0) 77 #include <dev/ic/mc6845reg.h> 78 #include <dev/ic/pcdisplayvar.h> 79 #include <dev/ic/vgareg.h> 80 #include <dev/ic/vgavar.h> 81 #endif 82 83 #include "pckbc.h" 84 #if (NPCKBC > 0) 85 #include <dev/isa/isareg.h> 86 #include <dev/ic/i8042reg.h> 87 #include <dev/ic/pckbcvar.h> 88 #endif 89 #endif 90 91 #include "com.h" 92 #if (NCOM > 0) 93 #include <sys/termios.h> 94 #include <dev/ic/comreg.h> 95 #include <dev/ic/comvar.h> 96 void comsoft(void); 97 #endif 98 99 #ifdef DDB 100 #include <machine/db_machdep.h> 101 #include <ddb/db_extern.h> 102 #endif 103 104 void initppc(u_long, u_long, void *); 105 void dumpsys(void); 106 void strayintr(int); 107 int lcsplx(int); 108 109 /* Our exported CPU info; we have only one right now. */ 110 struct cpu_info cpu_info_store; 111 112 /* 113 * Global variables used here and there 114 */ 115 struct vm_map *exec_map = NULL; 116 struct vm_map *mb_map = NULL; 117 struct vm_map *phys_map = NULL; 118 119 struct mvmeppc_bootinfo bootinfo; 120 121 char machine[] = MACHINE; /* machine */ 122 char machine_arch[] = MACHINE_ARCH; /* machine architecture */ 123 124 struct pcb *curpcb; 125 struct pmap *curpm; 126 struct proc *fpuproc; 127 128 extern struct user *proc0paddr; 129 130 struct bat battable[16]; 131 132 vaddr_t mvmeppc_intr_reg; /* PReP-compatible interrupt vector register */ 133 134 struct mem_region physmemr, availmemr; 135 136 paddr_t msgbuf_paddr; 137 vaddr_t msgbuf_vaddr; 138 139 paddr_t avail_end; /* XXX temporary */ 140 141 void install_extint(void (*)(void)); 142 143 144 void 145 initppc(startkernel, endkernel, btinfo) 146 u_long startkernel, endkernel; 147 void *btinfo; 148 { 149 extern int trapcode, trapsize; 150 extern int alitrap, alisize; 151 extern int dsitrap, dsisize; 152 extern int isitrap, isisize; 153 extern int decrint, decrsize; 154 extern int tlbimiss, tlbimsize; 155 extern int tlbdlmiss, tlbdlmsize; 156 extern int tlbdsmiss, tlbdsmsize; 157 #ifdef DDB 158 extern int ddblow, ddbsize; 159 extern void *startsym, *endsym; 160 #endif 161 int exc, scratch; 162 163 /* 164 * Copy bootinfo. 165 */ 166 memcpy(&bootinfo, btinfo, sizeof(bootinfo)); 167 168 /* 169 * Figure out the board family/type. 170 */ 171 ident_platform(); 172 173 if (platform == NULL) { 174 extern void _mvmeppc_unsup_board(const char *, const char *); 175 char msg[80]; 176 177 sprintf(msg, "Unsupported model: MVME%04x", 178 bootinfo.bi_modelnumber); 179 _mvmeppc_unsup_board(msg, &msg[strlen(msg)]); 180 /* NOTREACHED */ 181 } 182 183 /* 184 * Set memory region 185 */ 186 physmemr.start = 0; 187 physmemr.size = bootinfo.bi_memsize & ~PGOFSET; 188 availmemr.start = (endkernel + PGOFSET) & ~PGOFSET; 189 availmemr.size = bootinfo.bi_memsize - availmemr.start; 190 avail_end = physmemr.start + physmemr.size; /* XXX temporary */ 191 192 /* 193 * Set CPU clock 194 */ 195 { 196 extern u_long ticks_per_sec, ns_per_tick; 197 198 ticks_per_sec = bootinfo.bi_clocktps; 199 ns_per_tick = 1000000000 / ticks_per_sec; 200 } 201 202 proc0.p_addr = proc0paddr; 203 memset(proc0.p_addr, 0, sizeof *proc0.p_addr); 204 205 curpcb = &proc0paddr->u_pcb; 206 207 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel(); 208 209 /* 210 * boothowto 211 */ 212 boothowto = bootinfo.bi_boothowto; 213 214 /* 215 * Initialize BAT registers to unmapped to not generate 216 * overlapping mappings below. 217 */ 218 asm volatile ("mtibatu 0,%0" :: "r"(0)); 219 asm volatile ("mtibatu 1,%0" :: "r"(0)); 220 asm volatile ("mtibatu 2,%0" :: "r"(0)); 221 asm volatile ("mtibatu 3,%0" :: "r"(0)); 222 asm volatile ("mtdbatu 0,%0" :: "r"(0)); 223 asm volatile ("mtdbatu 1,%0" :: "r"(0)); 224 asm volatile ("mtdbatu 2,%0" :: "r"(0)); 225 asm volatile ("mtdbatu 3,%0" :: "r"(0)); 226 227 /* 228 * Set up initial BAT table 229 */ 230 /* map the lowest 256 MB area */ 231 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 232 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 233 234 /* map the PCI/ISA I/O 256 MB area */ 235 battable[MVMEPPC_PHYS_BASE_IO >> 28].batl = 236 BATL(MVMEPPC_PHYS_BASE_IO, BAT_I|BAT_G, BAT_PP_RW); 237 battable[MVMEPPC_PHYS_BASE_IO >> 28].batu = 238 BATU(MVMEPPC_KVA_BASE_IO, BAT_BL_256M, BAT_Vs); 239 240 /* map the PCI/ISA MEMORY 256 MB area */ 241 battable[MVMEPPC_PHYS_BASE_MEM >> 28].batl = 242 BATL(MVMEPPC_PHYS_BASE_MEM, BAT_I|BAT_G, BAT_PP_RW); 243 battable[MVMEPPC_PHYS_BASE_MEM >> 28].batu = 244 BATU(MVMEPPC_KVA_BASE_MEM, BAT_BL_256M, BAT_Vs); 245 246 /* 247 * Now setup fixed bat registers 248 */ 249 asm volatile ("mtibatl 0,%0; mtibatu 0,%1" 250 :: "r"(battable[0].batl), "r"(battable[0].batu)); 251 asm volatile ("mtdbatl 0,%0; mtdbatu 0,%1" 252 :: "r"(battable[0].batl), "r"(battable[0].batu)); 253 254 asm volatile ("mtdbatl 2,%0; mtdbatu 1,%1" 255 :: "r"(battable[MVMEPPC_PHYS_BASE_IO >> 28].batl), 256 "r"(battable[MVMEPPC_PHYS_BASE_IO >> 28].batu)); 257 asm volatile ("mtdbatl 3,%0; mtdbatu 2,%1" 258 :: "r"(battable[MVMEPPC_PHYS_BASE_MEM >> 28].batl), 259 "r"(battable[MVMEPPC_PHYS_BASE_MEM >> 28].batu)); 260 261 asm volatile ("sync; isync"); 262 263 /* 264 * Set up trap vectors 265 */ 266 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) 267 switch (exc) { 268 default: 269 memcpy((void *)exc, &trapcode, (size_t)&trapsize); 270 break; 271 case EXC_EXI: 272 /* 273 * This one is (potentially) installed during autoconf 274 */ 275 break; 276 case EXC_ALI: 277 memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize); 278 break; 279 case EXC_DSI: 280 memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize); 281 break; 282 case EXC_ISI: 283 memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize); 284 break; 285 case EXC_DECR: 286 memcpy((void *)EXC_DECR, &decrint, (size_t)&decrsize); 287 break; 288 case EXC_IMISS: 289 memcpy((void *)EXC_IMISS, &tlbimiss, 290 (size_t)&tlbimsize); 291 break; 292 case EXC_DLMISS: 293 memcpy((void *)EXC_DLMISS, &tlbdlmiss, 294 (size_t)&tlbdlmsize); 295 break; 296 case EXC_DSMISS: 297 memcpy((void *)EXC_DSMISS, &tlbdsmiss, 298 (size_t)&tlbdsmsize); 299 break; 300 #ifdef DDB 301 case EXC_PGM: 302 case EXC_TRC: 303 case EXC_BPT: 304 memcpy((void *)exc, &ddblow, (size_t)&ddbsize); 305 break; 306 #endif 307 } 308 309 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 310 311 #ifdef DEBUG 312 /* 313 * i386 port says, that this shouldn't be here, 314 * but I really think the console should be initialized 315 * as early as possible. 316 */ 317 consinit(); 318 #endif 319 320 /* 321 * external interrupt handler install 322 */ 323 install_extint(platform->ext_intr); 324 325 /* 326 * Now enable translation (and machine checks/recoverable interrupts). 327 */ 328 asm volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 329 : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 330 331 /* 332 * Set the page size. 333 */ 334 uvm_setpagesize(); 335 336 /* 337 * Initialize pmap module. 338 */ 339 pmap_bootstrap(startkernel, endkernel, NULL); 340 341 #ifdef DDB 342 ddb_init((int)((u_long)endsym - (u_long)startsym), startsym, endsym); 343 344 if (boothowto & RB_KDB) 345 Debugger(); 346 #endif 347 } 348 349 void 350 mem_regions(mem, avail) 351 struct mem_region **mem, **avail; 352 { 353 354 *mem = &physmemr; 355 *avail = &availmemr; 356 } 357 358 void 359 install_extint(handler) 360 void (*handler)(void); 361 { 362 extern u_char extint[]; 363 extern u_long extsize; 364 extern u_long extint_call; 365 u_long offset = (u_long)handler - (u_long)&extint_call; 366 int omsr, msr; 367 368 #ifdef DIAGNOSTIC 369 if (offset > 0x1ffffff) 370 panic("install_extint: too far away"); 371 #endif 372 asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 373 : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE)); 374 extint_call = (extint_call & 0xfc000003) | offset; 375 memcpy((void *)EXC_EXI, &extint, (size_t)&extsize); 376 __syncicache((void *)&extint_call, sizeof extint_call); 377 __syncicache((void *)EXC_EXI, (int)&extsize); 378 asm volatile ("mtmsr %0" :: "r"(omsr)); 379 } 380 381 /* 382 * Machine dependent startup code. 383 */ 384 void 385 cpu_startup() 386 { 387 int sz, i; 388 caddr_t v; 389 vaddr_t minaddr, maxaddr; 390 int base, residual; 391 char pbuf[9]; 392 393 proc0.p_addr = proc0paddr; 394 v = (caddr_t)proc0paddr + USPACE; 395 396 /* 397 * Mapping PReP-compatible interrput vector register. 398 */ 399 if (!(mvmeppc_intr_reg = uvm_km_valloc(kernel_map, round_page(NBPG)))) 400 panic("startup: no room for interrupt register"); 401 pmap_enter(pmap_kernel(), mvmeppc_intr_reg, MVMEPPC_INTR_REG, 402 VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 403 pmap_update(pmap_kernel()); 404 405 /* 406 * Initialize error message buffer (at end of core). 407 */ 408 if (!(msgbuf_vaddr = uvm_km_alloc(kernel_map, round_page(MSGBUFSIZE)))) 409 panic("startup: no room for message buffer"); 410 for (i = 0; i < btoc(MSGBUFSIZE); i++) 411 pmap_enter(pmap_kernel(), msgbuf_vaddr + i * NBPG, 412 msgbuf_paddr + i * NBPG, VM_PROT_READ|VM_PROT_WRITE, 413 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 414 pmap_update(pmap_kernel()); 415 initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE)); 416 417 printf("%s", version); 418 419 printf("Model: %s\n", platform->model); 420 printf("Core Speed: %dMHz, Bus Speed: %dMHz\n", 421 bootinfo.bi_mpuspeed/1000000, bootinfo.bi_busspeed/1000000); 422 423 cpu_identify(NULL, 0); 424 425 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 426 printf("total memory = %s\n", pbuf); 427 428 /* 429 * Find out how much space we need, allocate it, 430 * and then give everything true virtual addresses. 431 */ 432 sz = (int)allocsys(NULL, NULL); 433 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0) 434 panic("startup: no room for tables"); 435 if (allocsys(v, NULL) - v != sz) 436 panic("startup: table size inconsistency"); 437 438 /* 439 * Now allocate buffers proper. They are different than the above 440 * in that they usually occupy more virtual memory than physical. 441 */ 442 sz = MAXBSIZE * nbuf; 443 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(sz), 444 NULL, UVM_UNKNOWN_OFFSET, 0, 445 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 446 UVM_ADV_NORMAL, 0)) != 0) 447 panic("startup: cannot allocate VM for buffers"); 448 minaddr = (vaddr_t)buffers; 449 base = bufpages / nbuf; 450 residual = bufpages % nbuf; 451 if (base >= MAXBSIZE) { 452 /* Don't want to alloc more physical mem than ever needed */ 453 base = MAXBSIZE; 454 residual = 0; 455 } 456 for (i = 0; i < nbuf; i++) { 457 vsize_t curbufsize; 458 vaddr_t curbuf; 459 struct vm_page *pg; 460 461 /* 462 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 463 * that MAXBSIZE space, we allocate and map (base+1) pages 464 * for the first "residual" buffers, and then we allocate 465 * "base" pages for the rest. 466 */ 467 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 468 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 469 470 while (curbufsize) { 471 pg = uvm_pagealloc(NULL, 0, NULL, 0); 472 if (pg == NULL) 473 panic("startup: not enough memory for " 474 "buffer cache"); 475 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 476 VM_PROT_READ | VM_PROT_WRITE); 477 curbuf += PAGE_SIZE; 478 curbufsize -= PAGE_SIZE; 479 } 480 } 481 pmap_update(kernel_map->pmap); 482 483 /* 484 * Allocate a submap for exec arguments. This map effectively 485 * limits the number of processes exec'ing at any time. 486 */ 487 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 488 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 489 490 /* 491 * Allocate a submap for physio 492 */ 493 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 494 VM_PHYS_SIZE, 0, FALSE, NULL); 495 496 #ifndef PMAP_MAP_POOLPAGE 497 /* 498 * We need to allocate an mbuf cluster submap if the pool 499 * allocater isn't using direct-mapped pool pages. 500 */ 501 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 502 nmbclusters * mclbytes, VM_MAP_INTRSAFE, 503 FALSE, NULL); 504 #endif 505 506 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 507 printf("avail memory = %s\n", pbuf); 508 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 509 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 510 511 /* 512 * Set up the buffers. 513 */ 514 bufinit(); 515 516 /* 517 * Now allow hardware interrupts. 518 */ 519 { 520 int msr; 521 522 splraise(-1); 523 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 524 : "=r"(msr) : "K"(PSL_EE)); 525 } 526 527 mvmeppc_bus_space_init(); 528 } 529 530 /* 531 * consinit 532 * Initialize system console. 533 */ 534 void 535 consinit() 536 { 537 static int initted = 0; 538 539 if (initted) 540 return; 541 initted = 1; 542 543 #if 0 544 545 #if (NPFB > 0) 546 if (!strcmp(consinfo->devname, "fb")) { 547 pfb_cnattach(consinfo->addr); 548 #if (NPCKBC > 0) 549 pckbc_cnattach(&mvmeppc_isa_io_space_tag, IO_KBD, KBCMDP, 550 PCKBC_KBD_SLOT); 551 #endif 552 return; 553 } 554 #endif 555 556 #if (NVGA > 0) || (NGTEN > 0) 557 if (!strcmp(consinfo->devname, "vga")) { 558 #if (NGTEN > 0) 559 if (!gten_cnattach(&mvmeppc_mem_space_tag)) 560 goto dokbd; 561 #endif 562 #if (NVGA > 0) 563 if (!vga_cnattach(&mvmeppc_io_space_tag, &mvmeppc_mem_space_tag, 564 -1, 1)) 565 goto dokbd; 566 #endif 567 dokbd: 568 #if (NPCKBC > 0) 569 pckbc_cnattach(&mvmeppc_isa_io_space_tag, IO_KBD, KBCMDP, 570 PCKBC_KBD_SLOT); 571 #endif 572 return; 573 } 574 #endif /* PC | VGA */ 575 576 #endif 577 578 #if (NCOM > 0) 579 if (!strcmp(bootinfo.bi_consoledev, "PC16550")) { 580 bus_space_tag_t tag = &mvmeppc_isa_io_bs_tag; 581 bus_addr_t caddr[2] = {0x3f8, 0x2f8}; 582 int rv; 583 rv = comcnattach(tag, caddr[bootinfo.bi_consolechan], 584 bootinfo.bi_consolespeed, COM_FREQ, 585 bootinfo.bi_consolecflag); 586 if (rv) 587 panic("can't init serial console"); 588 589 return; 590 } 591 #endif 592 panic("invalid console device %s", bootinfo.bi_consoledev); 593 } 594 595 void 596 dumpsys() 597 { 598 599 printf("dumpsys: TBD\n"); 600 } 601 602 /* 603 * Soft networking interrupts. 604 */ 605 void 606 softnet() 607 { 608 extern volatile int netisr; 609 int isr; 610 611 isr = netisr; 612 netisr = 0; 613 614 #define DONETISR(bit, fn) do { \ 615 if (isr & (1 << bit)) \ 616 fn(); \ 617 } while (0) 618 619 #include <net/netisr_dispatch.h> 620 621 #undef DONETISR 622 } 623 624 /* 625 * Soft tty interrupts. 626 */ 627 void 628 softserial() 629 { 630 631 #if (NCOM > 0) 632 comsoft(); 633 #endif 634 } 635 636 /* 637 * Stray interrupts. 638 */ 639 void 640 strayintr(irq) 641 int irq; 642 { 643 644 log(LOG_ERR, "stray interrupt %d\n", irq); 645 } 646 647 /* 648 * Halt or reboot the machine after syncing/dumping according to howto. 649 */ 650 void 651 cpu_reboot(howto, what) 652 int howto; 653 char *what; 654 { 655 static int syncing; 656 657 if (cold) { 658 howto |= RB_HALT; 659 goto halt_sys; 660 } 661 662 boothowto = howto; 663 if ((howto & RB_NOSYNC) == 0 && syncing == 0) { 664 syncing = 1; 665 vfs_shutdown(); /* sync */ 666 resettodr(); /* set wall clock */ 667 } 668 669 /* Disable intr */ 670 splhigh(); 671 672 /* Do dump if requested */ 673 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 674 dumpsys(); 675 676 halt_sys: 677 doshutdownhooks(); 678 679 if (howto & RB_HALT) { 680 printf("\n"); 681 printf("The operating system has halted.\n"); 682 printf("Please press any key to reboot.\n\n"); 683 cnpollc(1); /* for proper keyboard command handling */ 684 cngetc(); 685 cnpollc(0); 686 } 687 688 printf("rebooting...\n\n"); 689 690 #if 0 691 (*platform->reset)(); 692 #endif 693 694 for (;;) 695 continue; 696 /* NOTREACHED */ 697 } 698 699 /* 700 * lcsplx() is called from locore; it is an open-coded version of 701 * splx() differing in that it returns the previous priority level. 702 */ 703 int 704 lcsplx(ipl) 705 int ipl; 706 { 707 int oldcpl; 708 709 __asm__ volatile("sync; eieio\n"); /* reorder protect */ 710 oldcpl = cpl; 711 cpl = ipl; 712 if (ipending & ~ipl) 713 do_pending_int(); 714 __asm__ volatile("sync; eieio\n"); /* reorder protect */ 715 716 return (oldcpl); 717 } 718