machdep.c revision 1.24
1/* $OpenBSD: machdep.c,v 1.24 2000/03/23 09:59:54 art Exp $ */ 2 3/* 4 * Copyright (c) 1999-2000 Michael Shalayeff 5 * 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Michael Shalayeff. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#undef BTLBDEBUG 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/signalvar.h> 39#include <sys/kernel.h> 40#include <sys/map.h> 41#include <sys/proc.h> 42#include <sys/buf.h> 43#include <sys/reboot.h> 44#include <sys/device.h> 45#include <sys/conf.h> 46#include <sys/file.h> 47#include <sys/timeout.h> 48#include <sys/malloc.h> 49#include <sys/mbuf.h> 50#include <sys/msgbuf.h> 51#include <sys/ioctl.h> 52#include <sys/tty.h> 53#include <sys/user.h> 54#include <sys/exec.h> 55#include <sys/sysctl.h> 56#include <sys/core.h> 57#include <sys/kcore.h> 58#include <sys/extent.h> 59#ifdef SYSVMSG 60#include <sys/msg.h> 61#endif 62#ifdef SYSVSEM 63#include <sys/sem.h> 64#endif 65#ifdef SYSVSHM 66#include <sys/shm.h> 67#endif 68 69#include <sys/mount.h> 70#include <sys/syscallargs.h> 71 72#include <vm/vm.h> 73#include <vm/vm_kern.h> 74#include <uvm/uvm_page.h> 75#include <uvm/uvm.h> 76 77#include <dev/cons.h> 78 79#include <machine/pdc.h> 80#include <machine/iomod.h> 81#include <machine/psl.h> 82#include <machine/reg.h> 83#include <machine/cpufunc.h> 84#include <machine/autoconf.h> 85#include <machine/kcore.h> 86 87#ifdef COMPAT_HPUX 88#include <compat/hpux/hpux.h> 89#endif 90 91#ifdef DDB 92#include <machine/db_machdep.h> 93#include <ddb/db_access.h> 94#include <ddb/db_sym.h> 95#include <ddb/db_extern.h> 96#endif 97 98#include <hppa/dev/cpudevs.h> 99#include <hppa/dev/cpudevs_data.h> 100 101/* 102 * Patchable buffer cache parameters 103 */ 104int nswbuf = 0; 105#ifdef NBUF 106int nbuf = NBUF; 107#else 108int nbuf = 0; 109#endif 110#ifdef BUFPAGES 111int bufpages = BUFPAGES; 112#else 113int bufpages = 0; 114#endif 115 116/* 117 * Different kinds of flags used throughout the kernel. 118 */ 119int cold = 1; /* unset when engine is up to go */ 120int msgbufmapped; /* set when safe to use msgbuf */ 121 122/* 123 * things to kill 124 */ 125int icache_stride; 126int dcache_stride; 127int dcache_line_mask; 128 129/* 130 * things to not kill 131 */ 132volatile u_int8_t *machine_ledaddr; 133int machine_ledword, machine_leds; 134 135/* 136 * CPU params (should be the same for all cpus in the system) 137 */ 138struct pdc_cache pdc_cache PDC_ALIGNMENT; 139struct pdc_btlb pdc_btlb PDC_ALIGNMENT; 140 /* w/ a little deviation should be the same for all installed cpus */ 141u_int cpu_ticksnum, cpu_ticksdenom, cpu_hzticks; 142 /* exported info */ 143char machine[] = MACHINE_ARCH; 144char cpu_model[128]; 145#ifdef COMPAT_HPUX 146int cpu_model_hpux; /* contains HPUX_SYSCONF_CPU* kind of value */ 147#endif 148 149dev_t bootdev; 150int totalphysmem, resvmem, physmem, esym; 151 152/* 153 * Things for MI glue to stick on. 154 */ 155struct user *proc0paddr; 156long mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; 157struct extent *hppa_ex; 158 159vm_map_t exec_map = NULL; 160vm_map_t mb_map = NULL; 161vm_map_t phys_map = NULL; 162 163 164void delay_init __P((void)); 165static __inline void fall __P((int, int, int, int, int)); 166void dumpsys __P((void)); 167void hpmc_dump __P((void)); 168 169/* 170 * wide used hardware params 171 */ 172struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; 173struct pdc_coproc pdc_coproc PDC_ALIGNMENT; 174struct pdc_coherence pdc_coherence PDC_ALIGNMENT; 175 176#ifdef DEBUG 177int sigdebug = 0xff; 178pid_t sigpid = 0; 179#define SDB_FOLLOW 0x01 180#endif 181 182 183void 184hppa_init(start) 185 paddr_t start; 186{ 187 extern int kernel_text; 188 vaddr_t v, vstart, vend; 189 register int error; 190 int hptsize; /* size of HPT table if supported */ 191 192 boothowto |= RB_SINGLE; /* XXX always go into single-user while debug */ 193 194 pdc_init(); /* init PDC iface, so we can call em easy */ 195 196 cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; 197 delay_init(); /* calculate cpu clock ratio */ 198 199 /* cache parameters */ 200 if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, 201 &pdc_cache)) < 0) { 202#ifdef DEBUG 203 printf("WARNING: PDC_CACHE error %d\n", error); 204#endif 205 } 206 207 /* XXX these gonna die */ 208 dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; 209 dcache_stride = pdc_cache.dc_stride; 210 icache_stride = pdc_cache.ic_stride; 211 212 /* cache coherence params (pbably available for 8k only) */ 213 error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, 214 &pdc_coherence, 1, 1, 1, 1); 215#ifdef DEBUG 216 printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", 217 pdc_coherence.ia_cst, pdc_coherence.da_cst, 218 pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); 219#endif 220 221 /* setup hpmc handler */ 222 { 223 extern u_int hpmc_v; /* from locore.s */ 224 register u_int *p = &hpmc_v; 225 226 if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) 227 *p = 0; /* XXX nop is more appropriate? */ 228 229 p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); 230 } 231 232 /* BTLB params */ 233 if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, 234 PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) 235 panic("WARNING: PDC_BTLB error %d", error); 236 237 /* purge TLBs and caches */ 238 if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL) < 0) 239 printf("WARNING: BTLB purge failed\n"); 240 241 ptlball(); 242 fcacheall(); 243 244 totalphysmem = PAGE0->imm_max_mem / NBPG; 245 resvmem = ((vaddr_t)&kernel_text) / NBPG; 246 247 /* calculate HPT size */ 248 for (hptsize = 1; hptsize < totalphysmem; hptsize *= 2); 249 mtctl(hptsize - 1, CR_HPTMASK); 250 251 if (pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) && 252 !pdc_hwtlb.min_size && !pdc_hwtlb.max_size) { 253 printf("WARNING: no HPT support, fine!\n"); 254 hptsize = 0; 255 } else { 256 if (hptsize > pdc_hwtlb.max_size) 257 hptsize = pdc_hwtlb.max_size; 258 else if (hptsize < pdc_hwtlb.min_size) 259 hptsize = pdc_hwtlb.min_size; 260 /* have to reload after adjustment */ 261 mtctl(hptsize - 1, CR_HPTMASK); 262 } 263 264 /* we hope this won't fail */ 265 hppa_ex = extent_create("mem", 0x0, 0xffffffff, M_DEVBUF, 266 (caddr_t)mem_ex_storage, sizeof(mem_ex_storage), 267 EX_NOCOALESCE|EX_NOWAIT); 268 if (extent_alloc_region(hppa_ex, 0, (vaddr_t)PAGE0->imm_max_mem, 269 EX_NOWAIT)) 270 panic("cannot reserve main memory"); 271 272 vstart = hppa_round_page(start); 273 vend = VM_MAX_KERNEL_ADDRESS; 274 275 /* 276 * Now allocate kernel dynamic variables 277 */ 278 279 /* buffer cache parameters */ 280#ifndef BUFCACHEPERCENT 281#define BUFCACHEPERCENT 10 282#endif /* BUFCACHEPERCENT */ 283 if (bufpages == 0) 284 bufpages = totalphysmem / 100 * 285 (totalphysmem <= 0x1000? 5 : BUFCACHEPERCENT); 286 287 if (nbuf == 0) 288 nbuf = bufpages < 16? 16 : bufpages; 289 290 /* Restrict to at most 70% filled kvm */ 291 if (nbuf * MAXBSIZE > 292 (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) * 7 / 10) 293 nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / 294 MAXBSIZE * 7 / 10; 295 296 /* More buffer pages than fits into the buffers is senseless. */ 297 if (bufpages > nbuf * MAXBSIZE / CLBYTES) 298 bufpages = nbuf * MAXBSIZE / CLBYTES; 299 300 if (nswbuf == 0) { 301 nswbuf = (nbuf / 2) &~ 1; 302 if (nswbuf > 256) 303 nswbuf = 256; 304 } 305 306 v = vstart; 307#define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num)) 308 309#ifdef REAL_CLISTS 310 valloc(cfree, struct cblock, nclist); 311#endif 312 313 valloc(timeouts, struct timeout, ntimeout); 314 valloc(buf, struct buf, nbuf); 315 316#ifdef SYSVSHM 317 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 318#endif 319#ifdef SYSVSEM 320 valloc(sema, struct semid_ds, seminfo.semmni); 321 valloc(sem, struct sem, seminfo.semmns); 322 /* This is pretty disgusting! */ 323 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 324#endif 325#ifdef SYSVMSG 326 valloc(msgpool, char, msginfo.msgmax); 327 valloc(msgmaps, struct msgmap, msginfo.msgseg); 328 valloc(msghdrs, struct msg, msginfo.msgtql); 329 valloc(msqids, struct msqid_ds, msginfo.msgmni); 330#endif 331#undef valloc 332 333 v = hppa_round_page(v); 334 bzero ((void *)vstart, (v - vstart)); 335 vstart = v; 336 337 pmap_bootstrap(&vstart, &vend); 338 physmem = totalphysmem - btoc(vstart); 339 340 /* alloc msgbuf */ 341 if (!(msgbufp = (void *)pmap_steal_memory(MSGBUFSIZE, NULL, NULL))) 342 panic("cannot allocate msgbuf"); 343 msgbufmapped = 1; 344 345 /* Turn on the HW TLB assist */ 346 if (hptsize) { 347 u_int hpt; 348 349 mfctl(CR_VTOP, hpt); 350 if ((error = pdc_call((iodcio_t)pdc, 0, PDC_TLB, 351 PDC_TLB_CONFIG, &pdc_hwtlb, hpt, hptsize, 352 PDC_TLB_CURRPDE)) < 0) { 353#ifdef DEBUG 354 printf("WARNING: HPT init error %d\n", error); 355#endif 356 } else { 357#ifdef PMAPDEBUG 358 printf("HPT: %d entries @ 0x%x\n", 359 hptsize / sizeof(struct hpt_entry), hpt); 360#endif 361 } 362 } 363 364 /* locate coprocessors and SFUs */ 365 if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, 366 &pdc_coproc)) < 0) 367 printf("WARNING: PDC_COPROC error %d\n", error); 368 else { 369#ifdef DEBUG 370 printf("pdc_coproc: %x, %x\n", pdc_coproc.ccr_enable, 371 pdc_coproc.ccr_present); 372#endif 373 mtctl(pdc_coproc.ccr_enable & CCR_MASK, CR_CCR); 374 } 375 376 /* they say PDC_COPROC might turn fault light on */ 377 pdc_call((iodcio_t)pdc, PDC_CHASSIS, PDC_CHASSIS_DISP, 378 PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); 379 380#ifdef DDB 381 ddb_init(); 382#endif 383} 384 385void 386cpu_startup() 387{ 388 struct pdc_model pdc_model PDC_ALIGNMENT; 389 vaddr_t minaddr, maxaddr; 390 vsize_t size; 391 int base, residual; 392 int err, i; 393#ifdef DEBUG 394 extern int pmapdebug; 395 int opmapdebug = pmapdebug; 396 397 pmapdebug = 0; 398#endif 399 400 /* good night */ 401 printf(version); 402 403 /* identify system type */ 404 if ((err = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, 405 &pdc_model)) < 0) { 406#ifdef DEBUG 407 printf("WARNING: PDC_MODEL error %d\n", err); 408#endif 409 } else { 410 const char *p, *q; 411 i = pdc_model.hvers >> 4; 412 p = hppa_mod_info(HPPA_TYPE_BOARD, i); 413 switch (pdc_model.arch_rev) { 414 default: 415 case 0: 416 q = "1.0"; 417#ifdef COMPAT_HPUX 418 cpu_model_hpux = HPUX_SYSCONF_CPUPA10; 419#endif 420 break; 421 case 4: 422 q = "1.1"; 423#ifdef COMPAT_HPUX 424 cpu_model_hpux = HPUX_SYSCONF_CPUPA11; 425#endif 426 break; 427 case 8: 428 q = "2.0"; 429#ifdef COMPAT_HPUX 430 cpu_model_hpux = HPUX_SYSCONF_CPUPA20; 431#endif 432 break; 433 } 434 435 if (p) 436 sprintf(cpu_model, "HP9000/%s PA-RISC %s", p, q); 437 else 438 sprintf(cpu_model, "HP9000/(UNKNOWN %x) PA-RISC %s", 439 i, q); 440 printf("%s\n", cpu_model); 441 } 442 443 printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n", 444 ctob(totalphysmem), ctob(resvmem), ctob(physmem)); 445 446 /* 447 * Kludge for STI graphics, which may have rom outside the IO space 448 */ 449#include "sti.h" 450#if NSTI > 0 451 { 452 vaddr_t addr = PAGE0->pd_resv2[1]; 453 454 /* reserve virtual address space for the sti rom */ 455 if (addr && addr < 0xf0000000 && 456 uvm_map(kernel_map, &addr, 0x1000000, NULL, 457 UVM_UNKNOWN_OFFSET, UVM_MAPFLAG(UVM_PROT_NONE, 458 UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 459 UVM_FLAG_FIXED)) != KERN_SUCCESS) 460 printf("WARNING: don't have space for stinger @0x%x\n", 461 addr); 462 } 463#endif 464 465 /* 466 * Now allocate buffers proper. They are different than the above 467 * in that they usually occupy more virtual memory than physical. 468 */ 469 size = MAXBSIZE * nbuf; 470 if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), 471 NULL, UVM_UNKNOWN_OFFSET, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, 472 UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != KERN_SUCCESS) 473 panic("cpu_startup: cannot allocate VM for buffers"); 474 minaddr = (vaddr_t)buffers; 475 base = bufpages / nbuf; 476 residual = bufpages % nbuf; 477 for (i = 0; i < nbuf; i++) { 478 vsize_t curbufsize; 479 vaddr_t curbuf; 480 struct vm_page *pg; 481 482 /* 483 * First <residual> buffers get (base+1) physical pages 484 * allocated for them. The rest get (base) physical pages. 485 * 486 * The rest of each buffer occupies virtual space, 487 * but has no physical memory allocated for it. 488 */ 489 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 490 curbufsize = CLBYTES * ((i < residual) ? (base+1) : base); 491 492 while (curbufsize) { 493 if ((pg = uvm_pagealloc(NULL, 0, NULL, 0)) == NULL) 494 panic("cpu_startup: not enough memory for " 495 "buffer cache"); 496 pmap_enter(kernel_map->pmap, curbuf, 497 VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE, 498 TRUE, VM_PROT_READ|VM_PROT_WRITE); 499 curbuf += PAGE_SIZE; 500 curbufsize -= PAGE_SIZE; 501 } 502 } 503 504 /* 505 * Allocate a submap for exec arguments. This map effectively 506 * limits the number of processes exec'ing at any time. 507 */ 508 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 509 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 510 511 /* 512 * Allocate a submap for physio 513 */ 514 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 515 VM_PHYS_SIZE, 0, FALSE, NULL); 516 517 /* 518 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 519 * we use the more space efficient malloc in place of kmem_alloc. 520 */ 521 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 522 M_MBUF, M_NOWAIT); 523 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 524 mb_map = uvm_km_suballoc(kernel_map, (vaddr_t *)&mbutl, &maxaddr, 525 VM_MBUF_SIZE, VM_MAP_INTRSAFE, FALSE, NULL); 526 527 /* 528 * Initialize timeouts 529 */ 530 timeout_init(); 531 532#ifdef DEBUG 533 pmapdebug = opmapdebug; 534#endif 535 printf("avail mem = %ld\n", ptoa(uvmexp.free)); 536 printf("using %d buffers containing %d bytes of memory\n", 537 nbuf, bufpages * CLBYTES); 538 539 /* 540 * Set up buffers, so they can be used to read disk labels. 541 */ 542 bufinit(); 543 544 /* 545 * Configure the system. 546 */ 547 if (boothowto & RB_CONFIG) { 548#ifdef BOOT_CONFIG 549 user_config(); 550#else 551 printf("kernel does not support -c; continuing..\n"); 552#endif 553 } 554 configure(); 555} 556 557/* 558 * compute cpu clock ratio such as: 559 * cpu_ticksnum / cpu_ticksdenom = t + delta 560 * delta -> 0 561 */ 562void 563delay_init(void) 564{ 565 register u_int num, denom, delta, mdelta; 566 567 mdelta = UINT_MAX; 568 for (denom = 1; denom < 1000; denom++) { 569 num = (PAGE0->mem_10msec * denom) / 10000; 570 delta = num * 10000 / denom - PAGE0->mem_10msec; 571 if (!delta) { 572 cpu_ticksdenom = denom; 573 cpu_ticksnum = num; 574 break; 575 } else if (delta < mdelta) { 576 cpu_ticksdenom = denom; 577 cpu_ticksnum = num; 578 } 579 } 580} 581 582void 583delay(us) 584 u_int us; 585{ 586 register u_int start, end, n; 587 588 mfctl(CR_ITMR, start); 589 while (us) { 590 n = min(1000, us); 591 end = start + n * cpu_ticksnum / cpu_ticksdenom; 592 593 /* N.B. Interval Timer may wrap around */ 594 if (end < start) 595 do 596 mfctl(CR_ITMR, start); 597 while (start > end); 598 599 do 600 mfctl(CR_ITMR, start); 601 while (start < end); 602 603 us -= n; 604 mfctl(CR_ITMR, start); 605 } 606} 607 608static __inline void 609fall(c_base, c_count, c_loop, c_stride, data) 610 int c_base, c_count, c_loop, c_stride, data; 611{ 612 register int loop; 613 614 for (; c_count--; c_base += c_stride) 615 for (loop = c_loop; loop--; ) 616 if (data) 617 fdce(0, c_base); 618 else 619 fice(0, c_base); 620} 621 622void 623fcacheall() 624{ 625 /* 626 * Flush the instruction, then data cache. 627 */ 628 fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, 629 pdc_cache.ic_stride, 0); 630 sync_caches(); 631 fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, 632 pdc_cache.dc_stride, 1); 633 sync_caches(); 634} 635 636void 637ptlball() 638{ 639 register pa_space_t sp; 640 register int i, j, k; 641 642 /* instruction TLB */ 643 sp = pdc_cache.it_sp_base; 644 for (i = 0; i < pdc_cache.it_sp_count; i++) { 645 register vaddr_t off = pdc_cache.it_off_base; 646 for (j = 0; j < pdc_cache.it_off_count; j++) { 647 for (k = 0; k < pdc_cache.it_loop; k++) 648 pitlbe(sp, off); 649 off += pdc_cache.it_off_stride; 650 } 651 sp += pdc_cache.it_sp_stride; 652 } 653 654 /* data TLB */ 655 sp = pdc_cache.dt_sp_base; 656 for (i = 0; i < pdc_cache.dt_sp_count; i++) { 657 register vaddr_t off = pdc_cache.dt_off_base; 658 for (j = 0; j < pdc_cache.dt_off_count; j++) { 659 for (k = 0; k < pdc_cache.dt_loop; k++) 660 pdtlbe(sp, off); 661 off += pdc_cache.dt_off_stride; 662 } 663 sp += pdc_cache.dt_sp_stride; 664 } 665} 666 667int 668btlb_insert(space, va, pa, lenp, prot) 669 pa_space_t space; 670 vaddr_t va; 671 paddr_t pa; 672 vsize_t *lenp; 673 u_int prot; 674{ 675 static u_int32_t mask; 676 register vsize_t len; 677 register int error, i; 678 679 /* align size */ 680 for (len = pdc_btlb.min_size << PGSHIFT; len < *lenp; len <<= 1); 681 len >>= PGSHIFT; 682 i = ffs(~mask) - 1; 683 if (len > pdc_btlb.max_size || i < 0) { 684#ifdef BTLBDEBUG 685 printf("btln_insert: too big (%u < %u < %u)\n", 686 pdc_btlb.min_size, len, pdc_btlb.max_size); 687#endif 688 return -(ENOMEM); 689 } 690 691 mask |= 1 << i; 692 pa >>= PGSHIFT; 693 va >>= PGSHIFT; 694 /* check address alignment */ 695 if (pa & (len - 1)) 696 printf("WARNING: BTLB address misaligned\n"); 697 698 /* ensure IO space is uncached */ 699 if ((pa & 0xF0000) == 0xF0000) 700 prot |= TLB_UNCACHEABLE; 701 702#ifdef BTLBDEBUG 703 printf("btlb_insert(%d): %x:%x=%x[%x,%x]\n", i, space, va, pa, len, prot); 704#endif 705 if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB,PDC_BTLB_INSERT, 706 space, va, pa, len, prot, i)) < 0) { 707#ifdef BTLBDEBUG 708 printf("WARNING: BTLB insert failed (%d)\n", error); 709#endif 710 return -(EINVAL); 711 } 712 *lenp = len << PGSHIFT; 713 714 return i; 715} 716 717int waittime = -1; 718 719void 720boot(howto) 721 int howto; 722{ 723 if (cold) 724 /* XXX howto |= RB_HALT */; 725 else { 726 boothowto = howto | (boothowto & RB_HALT); 727 728 if (!(howto & RB_NOSYNC) && waittime < 0) { 729 extern struct proc proc0; 730 731 /* protect against curproc->p_stats refs in sync XXX */ 732 if (curproc == NULL) 733 curproc = &proc0; 734 735 waittime = 0; 736 vfs_shutdown(); 737 if ((howto & RB_TIMEBAD) == 0) 738 resettodr(); 739 else 740 printf("WARNING: not updating battery clock\n"); 741 } 742 } 743 744 /* XXX probably save howto into stable storage */ 745 746 splhigh(); 747 748 if ((howto & (RB_DUMP /* | RB_HALT */)) == RB_DUMP) 749 dumpsys(); 750 751 doshutdownhooks(); 752 753 if (howto & RB_HALT) { 754 printf("System halted!\n"); 755 __asm __volatile("stwas %0, 0(%1)" 756 :: "r" (CMD_STOP), "r" (LBCAST_ADDR + iomod_command)); 757 } else { 758 printf("rebooting..."); 759 DELAY(1000000); 760 __asm __volatile("stwas %0, 0(%1)" 761 :: "r" (CMD_RESET), "r" (LBCAST_ADDR + iomod_command)); 762 } 763 764 for(;;); /* loop while bus reset is comming up */ 765 /* NOTREACHED */ 766} 767 768u_long dumpmag = 0x8fca0101; /* magic number */ 769int dumpsize = 0; /* pages */ 770long dumplo = 0; /* blocks */ 771 772/* 773 * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. 774 */ 775int 776cpu_dumpsize() 777{ 778 int size; 779 780 size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); 781 if (roundup(size, dbtob(1)) != dbtob(1)) 782 return -1; 783 784 return 1; 785} 786 787/* 788 * Called from HPMC handler in locore 789 */ 790void 791hpmc_dump() 792{ 793 794} 795 796int 797cpu_dump() 798{ 799 long buf[dbtob(1) / sizeof (long)]; 800 kcore_seg_t *segp; 801 cpu_kcore_hdr_t *cpuhdrp; 802 803 segp = (kcore_seg_t *)buf; 804 cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; 805 806 /* 807 * Generate a segment header. 808 */ 809 CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 810 segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); 811 812 /* 813 * Add the machine-dependent header info 814 */ 815 /* nothing for now */ 816 817 return (bdevsw[major(dumpdev)].d_dump) 818 (dumpdev, dumplo, (caddr_t)buf, dbtob(1)); 819} 820 821/* 822 * Dump the kernel's image to the swap partition. 823 */ 824#define BYTES_PER_DUMP NBPG 825 826void 827dumpsys() 828{ 829 int psize, bytes, i, n; 830 register caddr_t maddr; 831 register daddr_t blkno; 832 register int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 833 register int error; 834 835 /* Save registers 836 savectx(&dumppcb); */ 837 838 if (dumpsize == 0) 839 dumpconf(); 840 if (dumplo <= 0) { 841 printf("\ndump to dev %x not possible\n", dumpdev); 842 return; 843 } 844 printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo); 845 846 psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 847 printf("dump "); 848 if (psize == -1) { 849 printf("area unavailable\n"); 850 return; 851 } 852 853 if (!(error = cpu_dump())) { 854 855 bytes = ctob(physmem); 856 maddr = NULL; 857 blkno = dumplo + cpu_dumpsize(); 858 dump = bdevsw[major(dumpdev)].d_dump; 859 /* TODO block map the whole physical memory */ 860 for (i = 0; i < bytes; i += n) { 861 862 /* Print out how many MBs we are to go. */ 863 n = bytes - i; 864 if (n && (n % (1024*1024)) == 0) 865 printf("%d ", n / (1024 * 1024)); 866 867 /* Limit size for next transfer. */ 868 869 if (n > BYTES_PER_DUMP) 870 n = BYTES_PER_DUMP; 871 872 if ((error = (*dump)(dumpdev, blkno, maddr, n))) 873 break; 874 maddr += n; 875 blkno += btodb(n); 876 } 877 } 878 879 switch (error) { 880 case ENXIO: printf("device bad\n"); break; 881 case EFAULT: printf("device not ready\n"); break; 882 case EINVAL: printf("area improper\n"); break; 883 case EIO: printf("i/o error\n"); break; 884 case EINTR: printf("aborted from console\n"); break; 885 case 0: printf("succeeded\n"); break; 886 default: printf("error %d\n", error); break; 887 } 888} 889 890/* bcopy(), error on fault */ 891int 892kcopy(from, to, size) 893 const void *from; 894 void *to; 895 size_t size; 896{ 897 register u_int oldh = curproc->p_addr->u_pcb.pcb_onfault; 898 899 curproc->p_addr->u_pcb.pcb_onfault = (u_int)©_on_fault; 900 bcopy(from, to, size); 901 curproc->p_addr->u_pcb.pcb_onfault = oldh; 902 903 return 0; 904} 905 906int 907copystr(src, dst, size, lenp) 908 const void *src; 909 void *dst; 910 size_t size; 911 size_t *lenp; 912{ 913 return spstrcpy(HPPA_SID_KERNEL, src, HPPA_SID_KERNEL, dst, size, lenp); 914} 915 916int 917copyinstr(src, dst, size, lenp) 918 const void *src; 919 void *dst; 920 size_t size; 921 size_t *lenp; 922{ 923 return spstrcpy(curproc->p_addr->u_pcb.pcb_space, src, 924 HPPA_SID_KERNEL, dst, size, lenp); 925} 926 927 928int 929copyoutstr(src, dst, size, lenp) 930 const void *src; 931 void *dst; 932 size_t size; 933 size_t *lenp; 934{ 935 return spstrcpy(HPPA_SID_KERNEL, src, 936 curproc->p_addr->u_pcb.pcb_space, dst, size, lenp); 937} 938 939 940int 941copyin(src, dst, size) 942 const void *src; 943 void *dst; 944 size_t size; 945{ 946 return spcopy(curproc->p_addr->u_pcb.pcb_space, src, 947 HPPA_SID_KERNEL, dst, size); 948} 949 950int 951copyout(src, dst, size) 952 const void *src; 953 void *dst; 954 size_t size; 955{ 956 return spcopy(HPPA_SID_KERNEL, src, 957 curproc->p_addr->u_pcb.pcb_space, dst, size); 958} 959 960/* 961 * Set registers on exec. 962 */ 963void 964setregs(p, pack, stack, retval) 965 register struct proc *p; 966 struct exec_package *pack; 967 u_long stack; 968 register_t *retval; 969{ 970 register struct trapframe *tf = p->p_md.md_regs; 971 /* register struct pcb *pcb = &p->p_addr->u_pcb; */ 972#ifdef DEBUG 973 /*extern int pmapdebug;*/ 974 /*pmapdebug = 13;*/ 975 printf("setregs(%p, %p, %x, %p), ep=%x, cr30=%x\n", 976 p, pack, stack, retval, pack->ep_entry, tf->tf_cr30); 977#endif 978 979 tf->tf_iioq_tail = 4 + 980 (tf->tf_iioq_head = pack->ep_entry | HPPA_PC_PRIV_USER); 981 tf->tf_rp = 0; 982 tf->tf_arg0 = (u_long)PS_STRINGS; 983 tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */ 984 985 /* setup terminal stack frame */ 986 stack += HPPA_FRAME_SIZE; 987 suword((caddr_t)(stack + HPPA_FRAME_PSP), 0); 988 tf->tf_sp = stack; 989 990 retval[1] = 0; 991} 992 993/* 994 * Send an interrupt to process. 995 */ 996void 997sendsig(catcher, sig, mask, code, type, val) 998 sig_t catcher; 999 int sig, mask; 1000 u_long code; 1001 int type; 1002 union sigval val; 1003{ 1004 struct proc *p = curproc; 1005 1006#ifdef DEBUG 1007 if ((sigdebug | SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) 1008 printf("sendsig: %s[%d] sig %d catcher %p\n", 1009 p->p_comm, p->p_pid, sig, catcher); 1010#endif 1011 1012 /* TODO send signal */ 1013} 1014 1015int 1016sys_sigreturn(p, v, retval) 1017 struct proc *p; 1018 void *v; 1019 register_t *retval; 1020{ 1021 /* TODO sigreturn */ 1022 return EINVAL; 1023} 1024 1025/* 1026 * machine dependent system variables. 1027 */ 1028int 1029cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 1030 int *name; 1031 u_int namelen; 1032 void *oldp; 1033 size_t *oldlenp; 1034 void *newp; 1035 size_t newlen; 1036 struct proc *p; 1037{ 1038 dev_t consdev; 1039 /* all sysctl names at this level are terminal */ 1040 if (namelen != 1) 1041 return (ENOTDIR); /* overloaded */ 1042 switch (name[0]) { 1043 case CPU_CONSDEV: 1044 if (cn_tab != NULL) 1045 consdev = cn_tab->cn_dev; 1046 else 1047 consdev = NODEV; 1048 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 1049 sizeof consdev)); 1050 default: 1051 return (EOPNOTSUPP); 1052 } 1053 /* NOTREACHED */ 1054} 1055 1056 1057/* 1058 * consinit: 1059 * initialize the system console. 1060 */ 1061void 1062consinit() 1063{ 1064 static int initted; 1065 1066 if (!initted) { 1067 initted++; 1068 cninit(); 1069 } 1070} 1071