1 /* $NetBSD: machdep.c,v 1.78 2002/08/25 20:21:37 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 Shin Takemura, All rights reserved. 5 * Copyright (c) 1999-2001 SATO Kazumi, All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * Copyright (c) 1988 University of Utah. 34 * Copyright (c) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department, The Mach Operating System project at 40 * Carnegie-Mellon University and Ralph Campbell. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * from: Utah Hdr: machdep.c 1.63 91/04/24 71 * 72 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 73 */ 74 75 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 76 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.78 2002/08/25 20:21:37 thorpej Exp $"); 77 78 #include "opt_vr41xx.h" 79 #include "opt_tx39xx.h" 80 #include "opt_boot_standalone.h" 81 #include "opt_spec_platform.h" 82 #include "biconsdev.h" 83 #include "fs_mfs.h" 84 #include "opt_ddb.h" 85 #include "opt_kgdb.h" 86 #include "opt_rtc_offset.h" 87 #include "fs_nfs.h" 88 #include "opt_kloader.h" 89 #include "opt_kloader_kernel_path.h" 90 #include "debug_hpc.h" 91 #include "opt_md.h" 92 93 #include <sys/param.h> 94 #include <sys/systm.h> 95 #include <sys/kernel.h> 96 #include <sys/user.h> 97 #include <sys/buf.h> 98 #include <sys/reboot.h> 99 #include <sys/mount.h> 100 #include <sys/boot_flag.h> 101 102 #include <uvm/uvm_extern.h> 103 104 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 105 #include <dev/cons.h> /* cntab access (cpu_reboot) */ 106 107 #include <machine/psl.h> 108 #include <machine/sysconf.h> 109 #include <machine/platid.h> 110 #include <machine/platid_mask.h> 111 #include <machine/kloader.h> 112 #include <machine/debug.h> 113 114 #ifdef KGDB 115 #include <sys/kgdb.h> 116 #endif 117 118 #ifdef DDB 119 #include <machine/db_machdep.h> 120 #include <ddb/db_sym.h> 121 #include <ddb/db_extern.h> 122 #ifndef DB_ELFSIZE 123 #error Must define DB_ELFSIZE! 124 #endif 125 #define ELFSIZE DB_ELFSIZE 126 #include <sys/exec_elf.h> 127 #endif 128 129 #if NBICONSDEV > 0 130 #include <sys/conf.h> 131 #include <dev/hpc/biconsvar.h> 132 #include <dev/hpc/bicons.h> 133 #define biconscnpollc nullcnpollc 134 cons_decl(bicons); 135 static struct consdev bicons __attribute((__unused__)) = cons_init(bicons); 136 static int __bicons_enable; 137 #define DPRINTF(arg) { if (__bicons_enable) printf arg; } 138 #else /* NBICONSDEV > 0 */ 139 #define DPRINTF(arg) 140 #endif /* NBICONSDEV > 0 */ 141 142 #ifdef NFS 143 #include <nfs/rpcv2.h> 144 #include <nfs/nfsproto.h> 145 #include <nfs/nfs.h> 146 #include <nfs/nfsmount.h> 147 #endif 148 149 #ifdef MEMORY_DISK_DYNAMIC 150 #include <dev/md.h> 151 #endif 152 153 /* the following is used externally (sysctl_hw) */ 154 extern char cpu_model[]; 155 char cpu_name[40]; /* set cpu depend xx_init() */ 156 157 struct cpu_info cpu_info_store; /* only one cpu */ 158 int cpuspeed = 1; /* approx # instr per usec. */ 159 160 /* CPU core switch table */ 161 struct platform platform; 162 #ifdef VR41XX 163 extern void vr_init(void); 164 #endif 165 #ifdef TX39XX 166 extern void tx_init(void); 167 #endif 168 169 /* boot environment */ 170 static struct bootinfo bi_copy; 171 struct bootinfo *bootinfo; 172 char booted_kernel[128]; 173 extern void makebootdev(const char *); 174 #ifdef KLOADER 175 #if !defined(KLOADER_KERNEL_PATH) 176 #define KLOADER_KERNEL_PATH "/netbsd" 177 #endif /* !KLOADER_KERNEL_PATH */ 178 static char kernel_path[] = KLOADER_KERNEL_PATH; 179 #endif /* KLOADER */ 180 181 /* maps for VM objects */ 182 struct vm_map *exec_map; 183 struct vm_map *mb_map; 184 struct vm_map *phys_map; 185 186 /* physical memory */ 187 int physmem; /* max supported memory, changes to actual */ 188 int mem_cluster_cnt; 189 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 190 191 /* 192 * safepri is a safe priority for sleep to set for a spin-wait 193 * during autoconfiguration or after a panic. 194 * Used as an argument to splx(). 195 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 196 * disables mips1 FPU interrupts. 197 */ 198 int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 199 200 void mach_init(int, char *[], struct bootinfo *); 201 202 #ifdef DEBUG 203 /* stacktrace code violates prototypes to get callee's registers */ 204 extern void stacktrace(void); /*XXX*/ 205 #endif 206 207 /* 208 * Do all the stuff that locore normally does before calling main(). 209 * Process arguments passed to us by the boot loader. 210 * Return the first page address following the system. 211 */ 212 void 213 mach_init(int argc, char *argv[], struct bootinfo *bi) 214 { 215 /* 216 * this routines stack is never polluted since stack pointer 217 * is lower than kernel text segment, and at exiting, stack pointer 218 * is changed to proc0. 219 */ 220 #ifdef KLOADER 221 struct kloader_bootinfo kbi; 222 #endif 223 extern struct user *proc0paddr; 224 extern char edata[], end[]; 225 #ifdef DDB 226 extern caddr_t esym; 227 #endif 228 caddr_t kernend, v; 229 unsigned size; 230 char *cp; 231 int i; 232 233 /* clear the BSS segment */ 234 #ifdef DDB 235 size_t symbolsz = 0; 236 Elf_Ehdr *eh = (void *)end; 237 if (memcmp(eh->e_ident, ELFMAG, SELFMAG) == 0 && 238 eh->e_ident[EI_CLASS] == ELFCLASS) { 239 esym = end; 240 if (eh->e_entry != 0) { 241 /* pbsdboot */ 242 symbolsz = eh->e_entry; 243 } else { 244 /* hpcboot */ 245 Elf_Shdr *sh = (void *)(end + eh->e_shoff); 246 for(i = 0; i < eh->e_shnum; i++, sh++) 247 if (sh->sh_offset > 0 && 248 (sh->sh_offset + sh->sh_size) > symbolsz) 249 symbolsz = sh->sh_offset + sh->sh_size; 250 } 251 esym += symbolsz; 252 kernend = (caddr_t)mips_round_page(esym); 253 bzero(edata, end - edata); 254 } else 255 #endif /* DDB */ 256 { 257 kernend = (caddr_t)mips_round_page(end); 258 memset(edata, 0, kernend - edata); 259 } 260 261 #if defined(BOOT_STANDALONE) 262 #if !defined (SPEC_PLATFORM) || SPEC_PLATFORM == 1 263 #error specify SPEC_PLATFORM=platid_mask_MACH_xxx_yyy in BOOT_STANDALONE case. 264 #error see platid_mask.c for platid_mask_MACH_xxx_yyy. 265 #else 266 memcpy(&platid, &SPEC_PLATFORM, sizeof(platid)); 267 #endif 268 #endif /* defined(BOOT_STANDALONE) && defined(SPEC_PLATFORM) */ 269 /* 270 * Arguments are set up by boot loader. 271 */ 272 if (bi && bi->magic == BOOTINFO_MAGIC) { 273 memset(&bi_copy, 0, sizeof(struct bootinfo)); 274 memcpy(&bi_copy, bi, min(bi->length, sizeof(struct bootinfo))); 275 bootinfo = &bi_copy; 276 if (bootinfo->platid_cpu != 0) { 277 platid.dw.dw0 = bootinfo->platid_cpu; 278 } 279 if (bootinfo->platid_machine != 0) { 280 platid.dw.dw1 = bootinfo->platid_machine; 281 } 282 } 283 /* copy boot parameter for kloader */ 284 #ifdef KLOADER 285 kloader_bootinfo_set(&kbi, argc, argv, bi, FALSE); 286 #endif 287 288 /* 289 * CPU core Specific Function Hooks 290 */ 291 #if defined(VR41XX) && defined(TX39XX) 292 if (platid_match(&platid, &platid_mask_CPU_MIPS_VR_41XX)) 293 vr_init(); 294 else if (platid_match(&platid, &platid_mask_CPU_MIPS_TX_3900) || 295 platid_match(&platid, &platid_mask_CPU_MIPS_TX_3920)) 296 tx_init(); 297 #elif defined(VR41XX) 298 vr_init(); 299 #elif defined(TX39XX) 300 tx_init(); 301 #else 302 #error "define TX39XX and/or VR41XX" 303 #endif 304 305 #if NBICONSDEV > 0 306 /* 307 * bicons don't need actual device initialize. only bootinfo needed. 308 */ 309 __bicons_enable = (bicons_init(&bicons) == 0); 310 if (__bicons_enable) 311 cn_tab = &bicons; 312 #endif 313 314 /* Initialize frame buffer (to steal DMA buffer, stay here.) */ 315 #ifdef HPC_DEBUG_LCD 316 dbg_lcd_test(); 317 #endif 318 (*platform.fb_init)(&kernend); 319 kernend = (caddr_t)mips_round_page(kernend); 320 321 /* 322 * Set the VM page size. 323 */ 324 uvmexp.pagesize = NBPG; /* Notify the VM system of our page size. */ 325 uvm_setpagesize(); 326 327 /* 328 * Copy exception-dispatch code down to exception vector. 329 * Initialize locore-function vector. 330 * Clear out the I and D caches. 331 */ 332 mips_vector_init(); 333 intr_init(); 334 335 #ifdef DEBUG 336 /* 337 * Look at arguments passed to us and compute boothowto. 338 */ 339 if (bootinfo) { 340 DPRINTF(("Bootinfo. available, ")); 341 } 342 DPRINTF(("args: ")); 343 for (i = 0; i < argc; i++) { 344 DPRINTF(("%s ", argv[i])); 345 } 346 DPRINTF(("\n")); 347 DPRINTF(("platform ID: %08lx %08lx\n", platid.dw.dw0, platid.dw.dw1)); 348 #endif /* DEBUG */ 349 350 #ifndef RTC_OFFSET 351 /* 352 * rtc_offset from bootinfo.timezone set by pbsdboot.exe 353 */ 354 if (rtc_offset == 0 && bootinfo 355 && bootinfo->timezone > (-12*60) 356 && bootinfo->timezone <= (12*60)) 357 rtc_offset = bootinfo->timezone; 358 #endif /* RTC_OFFSET */ 359 360 /* Compute bootdev */ 361 makebootdev("wd0"); /* default boot device */ 362 363 boothowto = 0; 364 #ifdef KADB 365 boothowto |= RB_KDB; 366 #endif 367 strncpy(booted_kernel, argv[0], sizeof(booted_kernel)); 368 booted_kernel[sizeof(booted_kernel)-1] = 0; 369 for (i = 1; i < argc; i++) { 370 for (cp = argv[i]; *cp; cp++) { 371 switch (*cp) { 372 case 'h': /* XXX, serial console */ 373 bootinfo->bi_cnuse |= BI_CNUSE_SERIAL; 374 break; 375 376 case 'b': 377 /* boot device: -b=sd0 etc. */ 378 #ifdef NFS 379 if (strcmp(cp+2, "nfs") == 0) 380 mountroot = nfs_mountroot; 381 else 382 makebootdev(cp+2); 383 #else /* NFS */ 384 makebootdev(cp+2); 385 #endif /* NFS */ 386 cp += strlen(cp); 387 break; 388 default: 389 BOOT_FLAG(*cp, boothowto); 390 break; 391 } 392 } 393 } 394 #ifdef MFS 395 /* 396 * Check to see if a mini-root was loaded into memory. It resides 397 * at the start of the next page just after the end of BSS. 398 */ 399 if (boothowto & RB_MINIROOT) { 400 size_t fssz; 401 fssz = round_page(mfs_initminiroot(kernend)); 402 #ifdef MEMORY_DISK_DYNAMIC 403 md_root_setconf((caddr_t)kernend, fssz); 404 #endif /* MEMORY_DISK_DYNAMIC */ 405 kernend += fssz; 406 } 407 #endif /* MFS */ 408 409 #ifdef DDB 410 /* init symbols if present */ 411 if (esym) 412 ddb_init(symbolsz, &end, esym); 413 #endif /* DDB */ 414 /* 415 * Alloc u pages for proc0 stealing KSEG0 memory. 416 */ 417 proc0.p_addr = proc0paddr = (struct user *)kernend; 418 proc0.p_md.md_regs = 419 (struct frame *)((caddr_t)kernend + UPAGES * PAGE_SIZE) - 1; 420 memset(kernend, 0, UPAGES * PAGE_SIZE); 421 curpcb = &proc0.p_addr->u_pcb; 422 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 423 424 kernend += UPAGES * PAGE_SIZE; 425 426 /* Initialize console and KGDB serial port. */ 427 (*platform.cons_init)(); 428 429 #if defined(DDB) || defined(KGDB) 430 if (boothowto & RB_KDB) { 431 #ifdef DDB 432 Debugger(); 433 #endif /* DDB */ 434 #ifdef KGDB 435 kgdb_debug_init = 1; 436 kgdb_connect(1); 437 #endif /* KGDB */ 438 } 439 #endif /* DDB || KGDB */ 440 441 /* Find physical memory regions. */ 442 (*platform.mem_init)((paddr_t)kernend - MIPS_KSEG0_START); 443 /* 444 * Clear currently unused D-RAM area 445 * (For reboot Windows CE clearly) 446 */ 447 { 448 u_int32_t sp; 449 __asm__ __volatile__("move %0, $29" : "=r"(sp)); 450 KDASSERT(sp > KERNBASE + 0x400); 451 memset((void *)(KERNBASE + 0x400), 0, sp - (KERNBASE + 0x400)); 452 } 453 454 printf("mem_cluster_cnt = %d\n", mem_cluster_cnt); 455 physmem = 0; 456 for (i = 0; i < mem_cluster_cnt; i++) { 457 printf("mem_clusters[%d] = {0x%lx,0x%lx}\n", i, 458 (paddr_t)mem_clusters[i].start, 459 (paddr_t)mem_clusters[i].size); 460 physmem += atop(mem_clusters[i].size); 461 } 462 463 /* Cluster 0 is always the kernel, which doesn't get loaded. */ 464 for (i = 1; i < mem_cluster_cnt; i++) { 465 paddr_t start, size; 466 467 start = (paddr_t)mem_clusters[i].start; 468 size = (paddr_t)mem_clusters[i].size; 469 470 printf("loading 0x%lx,0x%lx\n", start, size); 471 472 memset((void *)MIPS_PHYS_TO_KSEG1(start), 0, size); 473 474 uvm_page_physload(atop(start), atop(start + size), 475 atop(start), atop(start + size), 476 VM_FREELIST_DEFAULT); 477 } 478 479 /* 480 * Initialize error message buffer (at end of core). 481 */ 482 mips_init_msgbuf(); 483 484 /* 485 * Compute the size of system data structures. pmap_bootstrap() 486 * needs some of this information. 487 */ 488 size = (unsigned)allocsys(NULL, NULL); 489 490 /* 491 * Initialize the virtual memory system. 492 */ 493 pmap_bootstrap(); 494 495 /* 496 * Allocate space for system data structures. These data structures 497 * are allocated here instead of cpu_startup() because physical 498 * memory is directly addressable. We don't have to map these into 499 * virtual address space. 500 */ 501 v = (caddr_t)uvm_pageboot_alloc(size); 502 if ((allocsys(v, NULL) - v) != size) 503 panic("mach_init: table size inconsistency"); 504 } 505 506 /* 507 * Machine-dependent startup code. 508 * allocate memory for variable-sized tables, initialize cpu. 509 */ 510 void 511 cpu_startup() 512 { 513 u_int i, base, residual; 514 vaddr_t minaddr, maxaddr; 515 vsize_t size; 516 char pbuf[9]; 517 #ifdef DEBUG 518 extern int pmapdebug; 519 int opmapdebug = pmapdebug; 520 521 pmapdebug = 0; 522 #endif 523 524 /* 525 * Good {morning,afternoon,evening,night}. 526 */ 527 printf(version); 528 sprintf(cpu_model, "%s (%s)", platid_name(&platid), cpu_name); 529 printf("%s\n", cpu_model); 530 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 531 printf("total memory = %s\n", pbuf); 532 if (bootverbose) { 533 /* show again when verbose mode */ 534 printf("total memory banks = %d\n", mem_cluster_cnt); 535 for (i = 0; i < mem_cluster_cnt; i++) { 536 printf("memory bank %d = 0x%08lx %ldKB(0x%08lx)\n", i, 537 (paddr_t)mem_clusters[i].start, 538 (paddr_t)mem_clusters[i].size/1024, 539 (paddr_t)mem_clusters[i].size); 540 } 541 } 542 543 /* 544 * Allocate virtual address space for file I/O buffers. 545 * Note they are different than the array of headers, 'buf', 546 * and usually occupy more virtual memory than physical. 547 */ 548 size = MAXBSIZE * nbuf; 549 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 550 NULL, UVM_UNKNOWN_OFFSET, 0, 551 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 552 UVM_ADV_NORMAL, 0)) != 0) 553 panic("cpu_startup: cannot allocate VM for buffers"); 554 555 minaddr = (vaddr_t)buffers; 556 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { 557 bufpages = btoc(MAXBSIZE) * nbuf; /* do not overallocate RAM */ 558 } 559 base = bufpages / nbuf; 560 residual = bufpages % nbuf; 561 562 /* now allocate RAM for buffers */ 563 for (i = 0; i < nbuf; i++) { 564 vsize_t curbufsize; 565 vaddr_t curbuf; 566 struct vm_page *pg; 567 568 /* 569 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 570 * that MAXBSIZE space, we allocate and map (base+1) pages 571 * for the first "residual" buffers, and then we allocate 572 * "base" pages for the rest. 573 */ 574 curbuf = (vaddr_t)buffers + (i * MAXBSIZE); 575 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 576 577 while (curbufsize) { 578 pg = uvm_pagealloc(NULL, 0, NULL, 0); 579 if (pg == NULL) 580 panic("cpu_startup: not enough memory for " 581 "buffer cache"); 582 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 583 VM_PROT_READ|VM_PROT_WRITE); 584 curbuf += PAGE_SIZE; 585 curbufsize -= PAGE_SIZE; 586 } 587 } 588 pmap_update(pmap_kernel()); 589 590 /* 591 * Allocate a submap for exec arguments. This map effectively 592 * limits the number of processes exec'ing at any time. 593 */ 594 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 595 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 596 597 /* 598 * Allocate a submap for physio 599 */ 600 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 601 VM_PHYS_SIZE, 0, FALSE, NULL); 602 603 /* 604 * No need to allocate an mbuf cluster submap. Mbuf clusters 605 * are allocated via the pool allocator, and we use KSEG to 606 * map those pages. 607 */ 608 609 #ifdef DEBUG 610 pmapdebug = opmapdebug; 611 #endif 612 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 613 printf("avail memory = %s\n", pbuf); 614 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 615 printf("using %u buffers containing %s of memory\n", nbuf, pbuf); 616 617 /* 618 * Set up buffers, so they can be used to read disk labels. 619 */ 620 bufinit(); 621 } 622 623 void 624 cpu_reboot(int howto, char *bootstr) 625 { 626 627 /* take a snap shot before clobbering any registers */ 628 if (curproc) 629 savectx((struct user *)curpcb); 630 631 #ifdef DEBUG 632 if (panicstr) 633 stacktrace(); 634 #endif 635 636 /* If system is cold, just halt. */ 637 if (cold) { 638 howto |= RB_HALT; 639 goto haltsys; 640 } 641 642 /* If "always halt" was specified as a boot flag, obey. */ 643 if ((boothowto & RB_HALT) != 0) { 644 howto |= RB_HALT; 645 } 646 647 #ifdef KLOADER 648 if ((howto & RB_HALT) == 0) { 649 if (howto & RB_STRING) 650 kloader_reboot_setup(bootstr); 651 else 652 kloader_reboot_setup(kernel_path); 653 } 654 #endif 655 656 boothowto = howto; 657 if ((howto & RB_NOSYNC) == 0) { 658 /* 659 * Synchronize the disks.... 660 */ 661 vfs_shutdown(); 662 663 /* 664 * If we've been adjusting the clock, the todr 665 * will be out of synch; adjust it now. 666 */ 667 resettodr(); 668 } 669 670 /* Disable interrupts. */ 671 splhigh(); 672 673 /* If rebooting and a dump is requested do it. */ 674 if (howto & RB_DUMP) 675 dumpsys(); 676 677 haltsys: 678 679 /* run any shutdown hooks */ 680 doshutdownhooks(); 681 682 /* Finally, halt/reboot the system. */ 683 if (howto & RB_HALT) { 684 printf("halted.\n"); 685 } else { 686 #ifdef KLOADER 687 kloader_reboot(); 688 /* NOTREACHED */ 689 #endif 690 } 691 692 (*platform.reboot)(howto, bootstr); 693 while(1) 694 ; 695 /*NOTREACHED*/ 696 } 697 698 void 699 consinit() 700 { 701 /* platform.cons_init() do it */ 702 } 703