Annotation of sys/arch/hppa64/hppa64/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.7 2007/06/06 17:15:12 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
! 16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include <sys/param.h>
! 21: #include <sys/systm.h>
! 22: #include <sys/signalvar.h>
! 23: #include <sys/kernel.h>
! 24: #include <sys/proc.h>
! 25: #include <sys/buf.h>
! 26: #include <sys/reboot.h>
! 27: #include <sys/device.h>
! 28: #include <sys/conf.h>
! 29: #include <sys/file.h>
! 30: #include <sys/timeout.h>
! 31: #include <sys/malloc.h>
! 32: #include <sys/mbuf.h>
! 33: #include <sys/msgbuf.h>
! 34: #include <sys/ioctl.h>
! 35: #include <sys/tty.h>
! 36: #include <sys/user.h>
! 37: #include <sys/exec.h>
! 38: #include <sys/sysctl.h>
! 39: #include <sys/core.h>
! 40: #include <sys/kcore.h>
! 41: #include <sys/extent.h>
! 42: #ifdef SYSVMSG
! 43: #include <sys/msg.h>
! 44: #endif
! 45:
! 46: #include <sys/mount.h>
! 47: #include <sys/syscallargs.h>
! 48:
! 49: #include <uvm/uvm.h>
! 50: #include <uvm/uvm_page.h>
! 51:
! 52: #include <dev/cons.h>
! 53: #include <dev/clock_subr.h>
! 54:
! 55: #include <machine/pdc.h>
! 56: #include <machine/iomod.h>
! 57: #include <machine/psl.h>
! 58: #include <machine/reg.h>
! 59: #include <machine/autoconf.h>
! 60: #include <machine/kcore.h>
! 61:
! 62: #ifdef COMPAT_HPUX
! 63: #include <compat/hpux/hpux.h>
! 64: #endif
! 65:
! 66: #ifdef DDB
! 67: #include <machine/db_machdep.h>
! 68: #include <ddb/db_access.h>
! 69: #include <ddb/db_sym.h>
! 70: #include <ddb/db_extern.h>
! 71: #endif
! 72:
! 73: #include <hppa/dev/cpudevs.h>
! 74:
! 75: /*
! 76: * Patchable buffer cache parameters
! 77: */
! 78: #ifndef BUFCACHEPERCENT
! 79: #define BUFCACHEPERCENT 10
! 80: #endif /* BUFCACHEPERCENT */
! 81:
! 82: #ifdef BUFPAGES
! 83: int bufpages = BUFPAGES;
! 84: #else
! 85: int bufpages = 0;
! 86: #endif
! 87: int bufcachepercent = BUFCACHEPERCENT;
! 88:
! 89: /*
! 90: * Different kinds of flags used throughout the kernel.
! 91: */
! 92: int cold = 1; /* unset when engine is up to go */
! 93: extern int msgbufmapped; /* set when safe to use msgbuf */
! 94:
! 95: /*
! 96: * cache configuration, for most machines is the same
! 97: * numbers, so it makes sense to do defines w/ numbers depending
! 98: * on configured cpu types in the kernel
! 99: */
! 100: int icache_stride, icache_line_mask;
! 101: int dcache_stride, dcache_line_mask;
! 102:
! 103: /*
! 104: * things to not kill
! 105: */
! 106: volatile u_int8_t *machine_ledaddr;
! 107: int machine_ledword, machine_leds;
! 108: struct cpu_info cpu0_info;
! 109:
! 110: /*
! 111: * CPU params (should be the same for all cpus in the system)
! 112: */
! 113: struct pdc_cache pdc_cache PDC_ALIGNMENT;
! 114: struct pdc_model pdc_model PDC_ALIGNMENT;
! 115:
! 116: /* w/ a little deviation should be the same for all installed cpus */
! 117: u_int cpu_ticksnum, cpu_ticksdenom;
! 118:
! 119: /* exported info */
! 120: char machine[] = MACHINE;
! 121: char cpu_model[128];
! 122: int cpu_hvers;
! 123: enum hppa_cpu_type cpu_type;
! 124: const char *cpu_typename;
! 125: u_int fpu_version;
! 126: #ifdef COMPAT_HPUX
! 127: int cpu_model_hpux; /* contains HPUX_SYSCONF_CPU* kind of value */
! 128: #endif
! 129:
! 130: dev_t bootdev;
! 131: int physmem, resvmem, resvphysmem, esym;
! 132: paddr_t avail_end;
! 133:
! 134: /*
! 135: * Things for MI glue to stick on.
! 136: */
! 137: struct user *proc0paddr;
! 138: long mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(32) / sizeof(long)];
! 139: struct extent *hppa_ex;
! 140:
! 141: struct vm_map *exec_map = NULL;
! 142: struct vm_map *phys_map = NULL;
! 143: /* Virtual page frame for /dev/mem (see mem.c) */
! 144: vaddr_t vmmap;
! 145:
! 146: void delay_init(void);
! 147: static __inline void fall(int, int, int, int, int);
! 148: void dumpsys(void);
! 149: void hpmc_dump(void);
! 150: void cpuid(void);
! 151:
! 152: /*
! 153: * wide used hardware params
! 154: */
! 155: struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT;
! 156: struct pdc_coproc pdc_coproc PDC_ALIGNMENT;
! 157: struct pdc_coherence pdc_coherence PDC_ALIGNMENT;
! 158: struct pdc_spidb pdc_spidbits PDC_ALIGNMENT;
! 159: struct pdc_model pdc_model PDC_ALIGNMENT;
! 160:
! 161: #ifdef DEBUG
! 162: int sigdebug = 0;
! 163: pid_t sigpid = 0;
! 164: #define SDB_FOLLOW 0x01
! 165: #endif
! 166:
! 167: int
! 168: hppa_cpuspeed(int *mhz)
! 169: {
! 170: *mhz = PAGE0->mem_10msec / 10000;
! 171:
! 172: return (0);
! 173: }
! 174:
! 175: void
! 176: hppa_init(start)
! 177: paddr_t start;
! 178: {
! 179: extern int kernel_text;
! 180: int error;
! 181:
! 182: mtctl((long)&cpu0_info, 24);
! 183:
! 184: pdc_init(); /* init PDC iface, so we can call em easy */
! 185:
! 186: delay_init(); /* calculate cpu clock ratio */
! 187:
! 188: cpuid();
! 189:
! 190: /* cache parameters */
! 191: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT,
! 192: &pdc_cache)) < 0) {
! 193: #ifdef DEBUG
! 194: printf("WARNING: PDC_CACHE error %d\n", error);
! 195: #endif
! 196: }
! 197:
! 198: dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1;
! 199: dcache_stride = pdc_cache.dc_stride;
! 200: icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1;
! 201: icache_stride = pdc_cache.ic_stride;
! 202:
! 203: /* cache coherence params (pbably available for 8k only) */
! 204: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS,
! 205: &pdc_coherence, 1, 1, 1, 1);
! 206: #ifdef DEBUG
! 207: printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n",
! 208: pdc_coherence.ia_cst, pdc_coherence.da_cst,
! 209: pdc_coherence.ita_cst, pdc_coherence.dta_cst, error);
! 210: #endif
! 211: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB,
! 212: &pdc_spidbits, 0, 0, 0, 0);
! 213: printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error);
! 214:
! 215: #if 0
! 216: TODO hpmc/toc/pfr
! 217: /* setup hpmc handler */
! 218: {
! 219: extern u_int hpmc_v[]; /* from locore.s */
! 220: register u_int *p = hpmc_v;
! 221:
! 222: if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p))
! 223: *p = 0x08000240;
! 224:
! 225: p[6] = (u_int)&hpmc_dump;
! 226: p[7] = 32;
! 227: p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]);
! 228: }
! 229:
! 230: {
! 231: extern u_int hppa_toc[], hppa_toc_end[];
! 232: register u_int cksum, *p;
! 233:
! 234: for (cksum = 0, p = hppa_toc; p < hppa_toc_end; p++)
! 235: cksum += *p;
! 236:
! 237: *p = cksum;
! 238: PAGE0->ivec_toc = (u_int)&hppa_toc[0];
! 239: PAGE0->ivec_toclen = (hppa_toc_end - hppa_toc + 1) * 4;
! 240: }
! 241:
! 242: {
! 243: extern u_int hppa_pfr[], hppa_pfr_end[];
! 244: register u_int cksum, *p;
! 245:
! 246: for (cksum = 0, p = hppa_pfr; p < hppa_pfr_end; p++)
! 247: cksum += *p;
! 248:
! 249: *p = cksum;
! 250: PAGE0->ivec_mempf = (u_int)&hppa_pfr[0];
! 251: PAGE0->ivec_mempflen = (hppa_pfr_end - hppa_pfr + 1) * 4;
! 252: }
! 253: #endif
! 254: avail_end = trunc_page(PAGE0->imm_max_mem);
! 255: if (avail_end > 0x4000000)
! 256: avail_end = 0x4000000;
! 257: physmem = btoc(avail_end);
! 258: resvmem = btoc(((vaddr_t)&kernel_text));
! 259:
! 260: /* we hope this won't fail */
! 261: hppa_ex = extent_create("mem", 0, HPPA_PHYSMAP, M_DEVBUF,
! 262: (caddr_t)mem_ex_storage, sizeof(mem_ex_storage),
! 263: EX_NOCOALESCE|EX_NOWAIT);
! 264: if (extent_alloc_region(hppa_ex, 0, (vaddr_t)PAGE0->imm_max_mem,
! 265: EX_NOWAIT))
! 266: panic("cannot reserve main memory");
! 267:
! 268: #ifdef SYSVMSG
! 269: {
! 270: vaddr_t v;
! 271:
! 272: v = round_page(start);
! 273: #define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num))
! 274: valloc(msgpool, char, msginfo.msgmax);
! 275: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 276: valloc(msghdrs, struct msg, msginfo.msgtql);
! 277: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 278: #undef valloc
! 279: v = round_page(v);
! 280: bzero ((void *)start, (v - start));
! 281: start = v;
! 282: }
! 283: #endif
! 284: /* sets resvphysmem */
! 285: pmap_bootstrap(start);
! 286:
! 287: /* space has been reserved in pmap_bootstrap() */
! 288: msgbufp = (struct msgbuf *)((vaddr_t)ptoa(physmem) -
! 289: round_page(MSGBUFSIZE));
! 290: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 291: msgbufmapped = 1;
! 292:
! 293: /* they say PDC_COPROC might turn fault light on */
! 294: pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP,
! 295: PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0);
! 296:
! 297: cpu_cpuspeed = &hppa_cpuspeed;
! 298:
! 299: #ifdef DDB
! 300: ddb_init();
! 301: if (boothowto & RB_KDB)
! 302: Debugger();
! 303: #endif
! 304: ptlball();
! 305: ficacheall();
! 306: fdcacheall();
! 307: printf("out\n");
! 308: }
! 309:
! 310: void
! 311: cpuid()
! 312: {
! 313: extern u_int fpu_enable;
! 314: struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT;
! 315: int error;
! 316:
! 317: /* identify system type */
! 318: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO,
! 319: &pdc_model)) < 0) {
! 320: #ifdef DEBUG
! 321: printf("WARNING: PDC_MODEL error %d\n", error);
! 322: #endif
! 323: pdc_model.hvers = 0;
! 324: }
! 325:
! 326: bzero(&pdc_cpuid, sizeof(pdc_cpuid));
! 327: if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID,
! 328: &pdc_cpuid, 0, 0, 0, 0) >= 0) {
! 329:
! 330: /* patch for old 8200 */
! 331: if (pdc_cpuid.version == HPPA_CPU_PCXU &&
! 332: pdc_cpuid.revision > 0x0d)
! 333: pdc_cpuid.version = HPPA_CPU_PCXUP;
! 334:
! 335: cpu_type = pdc_cpuid.version;
! 336: }
! 337:
! 338: /* locate coprocessors and SFUs */
! 339: bzero(&pdc_coproc, sizeof(pdc_coproc));
! 340: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT,
! 341: &pdc_coproc, 0, 0, 0, 0)) < 0)
! 342: printf("WARNING: PDC_COPROC error %d\n", error);
! 343: else {
! 344: printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n",
! 345: pdc_coproc.ccr_enable, pdc_coproc.ccr_present,
! 346: pdc_coproc.fpu_model, pdc_coproc.fpu_revision);
! 347: fpu_enable = pdc_coproc.ccr_enable & 0xc0;
! 348:
! 349: /* a kludge to detect PCXW */
! 350: if (pdc_coproc.fpu_model == HPPA_FPU_PCXW)
! 351: cpu_type = HPPA_CPU_PCXW;
! 352: }
! 353:
! 354: if (!cpu_type)
! 355: printf("WARNING: UNKNOWN CPU TYPE; GOOD LUCK\n");
! 356: cpu_typename = hppa_mod_info(HPPA_TYPE_CPU, cpu_type);
! 357:
! 358: if (pdc_model.arch_rev != 8)
! 359: panic("CANNOT RUN 64BIT KERNEL on 32BIT CPU");
! 360:
! 361: {
! 362: const char *p;
! 363: char buf[32];
! 364:
! 365: cpu_hvers = pdc_model.hvers >> 4;
! 366: if (!cpu_hvers) {
! 367: p = "(UNKNOWN)";
! 368: } else {
! 369: p = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers);
! 370: if (!p) {
! 371: snprintf(buf, sizeof buf, "(UNKNOWN 0x%x)",
! 372: cpu_hvers);
! 373: p = buf;
! 374: }
! 375: }
! 376:
! 377: snprintf(cpu_model, sizeof cpu_model,
! 378: "HP 9000/%s PA-RISC 2.0", p);
! 379: }
! 380: #ifdef DEBUG
! 381: printf("%s\n", cpu_model);
! 382: #endif
! 383: }
! 384:
! 385: void
! 386: cpu_startup(void)
! 387: {
! 388: vaddr_t minaddr, maxaddr;
! 389:
! 390: /*
! 391: * psychodelic kingdom come
! 392: * ... run, run, run
! 393: * psychodelic kings and queens
! 394: * join me in this one love dream
! 395: */
! 396: printf("%s%s\n", version, cpu_model);
! 397: printf("real mem = %u (%u reserved for PROM, %u used by OpenBSD)\n",
! 398: ctob(physmem), ctob(resvmem), ctob(resvphysmem - resvmem));
! 399:
! 400: /*
! 401: * Determine how many buffers to allocate.
! 402: * We allocate bufcachepercent% of memory for buffer space.
! 403: */
! 404: if (bufpages == 0)
! 405: bufpages = physmem * bufcachepercent / 100;
! 406:
! 407: /* Restrict to at most 25% filled kvm */
! 408: if (bufpages >
! 409: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 410: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 411: PAGE_SIZE / 4;
! 412:
! 413: printf("here3\n");
! 414: /*
! 415: * Allocate a submap for exec arguments. This map effectively
! 416: * limits the number of processes exec'ing at any time.
! 417: */
! 418: minaddr = vm_map_min(kernel_map);
! 419: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 420: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 421:
! 422: printf("here4\n");
! 423: /*
! 424: * Allocate a submap for physio
! 425: */
! 426: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 427: VM_PHYS_SIZE, 0, FALSE, NULL);
! 428:
! 429: printf("here5\n");
! 430: printf("avail mem = %lu\n", ptoa(uvmexp.free));
! 431:
! 432: /*
! 433: * Set up buffers, so they can be used to read disk labels.
! 434: */
! 435: bufinit();
! 436: vmmap = uvm_km_valloc_wait(kernel_map, NBPG);
! 437:
! 438: printf("here6\n");
! 439: /*
! 440: * Configure the system.
! 441: */
! 442: if (boothowto & RB_CONFIG) {
! 443: #ifdef BOOT_CONFIG
! 444: user_config();
! 445: #else
! 446: printf("kernel does not support -c; continuing..\n");
! 447: #endif
! 448: }
! 449: printf("here7\n");
! 450: }
! 451:
! 452: /*
! 453: * initialize the system time from the time of day clock
! 454: */
! 455: void
! 456: inittodr(t)
! 457: time_t t;
! 458: {
! 459: struct pdc_tod tod PDC_ALIGNMENT;
! 460: int error, tbad = 0;
! 461:
! 462: if (t < 12*SECYR) {
! 463: printf ("WARNING: preposterous time in file system");
! 464: t = 6*SECYR + 186*SECDAY + SECDAY/2;
! 465: tbad = 1;
! 466: }
! 467:
! 468: if ((error = pdc_call((iodcio_t)pdc,
! 469: 1, PDC_TOD, PDC_TOD_READ, &tod, 0, 0, 0, 0, 0)))
! 470: printf("clock: failed to fetch (%d)\n", error);
! 471:
! 472: time.tv_sec = tod.sec;
! 473: time.tv_usec = tod.usec;
! 474:
! 475: if (!tbad) {
! 476: u_long dt;
! 477:
! 478: dt = (time.tv_sec < t)? t - time.tv_sec : time.tv_sec - t;
! 479:
! 480: if (dt < 2 * SECDAY)
! 481: return;
! 482: printf("WARNING: clock %s %ld days",
! 483: time.tv_sec < t? "lost" : "gained", dt / SECDAY);
! 484: }
! 485:
! 486: printf (" -- CHECK AND RESET THE DATE!\n");
! 487: }
! 488:
! 489: /*
! 490: * reset the time of day clock to the value in time
! 491: */
! 492: void
! 493: resettodr()
! 494: {
! 495: int error;
! 496:
! 497: if ((error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_WRITE,
! 498: time.tv_sec, time.tv_usec)))
! 499: printf("clock: failed to save (%d)\n", error);
! 500: }
! 501:
! 502: /*
! 503: * compute cpu clock ratio such as:
! 504: * cpu_ticksnum / cpu_ticksdenom = t + delta
! 505: * delta -> 0
! 506: */
! 507: void
! 508: delay_init(void)
! 509: {
! 510: u_long num, denom, delta, mdelta;
! 511:
! 512: mdelta = ULONG_MAX;
! 513: for (denom = 1; denom < 1000; denom++) {
! 514: num = (PAGE0->mem_10msec * denom) / 10000;
! 515: delta = num * 10000 / denom - PAGE0->mem_10msec;
! 516: if (!delta) {
! 517: cpu_ticksdenom = denom;
! 518: cpu_ticksnum = num;
! 519: break;
! 520: } else if (delta < mdelta) {
! 521: cpu_ticksdenom = denom;
! 522: cpu_ticksnum = num;
! 523: mdelta = delta;
! 524: }
! 525: }
! 526: printf("nom=%lu denom=%lu\n", cpu_ticksnum, cpu_ticksdenom);
! 527: }
! 528:
! 529: void
! 530: delay(us)
! 531: u_int us;
! 532: {
! 533: u_long start, end, n;
! 534:
! 535: start = mfctl(CR_ITMR);
! 536: while (us) {
! 537: n = min(1000, us);
! 538: end = start + n * cpu_ticksnum / cpu_ticksdenom;
! 539:
! 540: /* N.B. Interval Timer may wrap around */
! 541: if (end < start)
! 542: do
! 543: start = mfctl(CR_ITMR);
! 544: while (start > end);
! 545:
! 546: do
! 547: start = mfctl(CR_ITMR);
! 548: while (start < end);
! 549:
! 550: us -= n;
! 551: }
! 552: }
! 553:
! 554: static __inline void
! 555: fall(c_base, c_count, c_loop, c_stride, data)
! 556: int c_base, c_count, c_loop, c_stride, data;
! 557: {
! 558: int loop;
! 559:
! 560: for (; c_count--; c_base += c_stride)
! 561: for (loop = c_loop; loop--; )
! 562: if (data)
! 563: __asm __volatile("fdce 0(%%sr0,%0)"
! 564: :: "r" (c_base));
! 565: else
! 566: __asm __volatile("fice 0(%%sr0,%0)"
! 567: :: "r" (c_base));
! 568: }
! 569:
! 570: void
! 571: ficacheall(void)
! 572: {
! 573: /*
! 574: * Flush the instruction, then data cache.
! 575: */
! 576: fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop,
! 577: pdc_cache.ic_stride, 0);
! 578: sync_caches();
! 579: }
! 580:
! 581: void
! 582: fdcacheall(void)
! 583: {
! 584: fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop,
! 585: pdc_cache.dc_stride, 1);
! 586: sync_caches();
! 587: }
! 588:
! 589: void
! 590: ptlball(void)
! 591: {
! 592: register pa_space_t sp;
! 593: register int i, j, k;
! 594:
! 595: /* instruction TLB */
! 596: sp = pdc_cache.it_sp_base;
! 597: for (i = 0; i < pdc_cache.it_sp_count; i++) {
! 598: register vaddr_t off = pdc_cache.it_off_base;
! 599: for (j = 0; j < pdc_cache.it_off_count; j++) {
! 600: for (k = 0; k < pdc_cache.it_loop; k++)
! 601: pitlb(sp, off);
! 602: off += pdc_cache.it_off_stride;
! 603: }
! 604: sp += pdc_cache.it_sp_stride;
! 605: }
! 606:
! 607: /* data TLB */
! 608: sp = pdc_cache.dt_sp_base;
! 609: for (i = 0; i < pdc_cache.dt_sp_count; i++) {
! 610: register vaddr_t off = pdc_cache.dt_off_base;
! 611: for (j = 0; j < pdc_cache.dt_off_count; j++) {
! 612: for (k = 0; k < pdc_cache.dt_loop; k++)
! 613: pdtlb(sp, off);
! 614: off += pdc_cache.dt_off_stride;
! 615: }
! 616: sp += pdc_cache.dt_sp_stride;
! 617: }
! 618: }
! 619:
! 620: void
! 621: boot(howto)
! 622: int howto;
! 623: {
! 624: /* If system is cold, just halt. */
! 625: if (cold) {
! 626: /* (Unless the user explicitly asked for reboot.) */
! 627: if ((howto & RB_USERREQ) == 0)
! 628: howto |= RB_HALT;
! 629: } else {
! 630:
! 631: boothowto = howto | (boothowto & RB_HALT);
! 632:
! 633: if (!(howto & RB_NOSYNC)) {
! 634: vfs_shutdown();
! 635: /*
! 636: * If we've been adjusting the clock, the todr
! 637: * will be out of synch; adjust it now unless
! 638: * the system was sitting in ddb.
! 639: */
! 640: if ((howto & RB_TIMEBAD) == 0)
! 641: resettodr();
! 642: else
! 643: printf("WARNING: not updating battery clock\n");
! 644: }
! 645:
! 646: /* XXX probably save howto into stable storage */
! 647:
! 648: splhigh();
! 649:
! 650: if (howto & RB_DUMP)
! 651: dumpsys();
! 652:
! 653: doshutdownhooks();
! 654: }
! 655:
! 656: /* in case we came on powerfail interrupt */
! 657: if (cold_hook)
! 658: (*cold_hook)(HPPA_COLD_COLD);
! 659:
! 660: if (howto & RB_HALT) {
! 661: if (howto & RB_POWERDOWN && cold_hook) {
! 662: printf("Powering off...");
! 663: DELAY(2000000);
! 664: (*cold_hook)(HPPA_COLD_OFF);
! 665: DELAY(1000000);
! 666: }
! 667:
! 668: printf("System halted!\n");
! 669: DELAY(2000000);
! 670: __asm __volatile("stwas %0, 0(%1)"
! 671: :: "r" (CMD_STOP), "r" (HPPA_LBCAST + iomod_command));
! 672: } else {
! 673: printf("rebooting...");
! 674: DELAY(2000000);
! 675: __asm __volatile(".export hppa_reset, entry\n\t"
! 676: ".label hppa_reset");
! 677: __asm __volatile("stwas %0, 0(%1)"
! 678: :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command));
! 679: }
! 680:
! 681: for(;;); /* loop while bus reset is comming up */
! 682: /* NOTREACHED */
! 683: }
! 684:
! 685: u_long dumpmag = 0x8fca0101; /* magic number */
! 686: int dumpsize = 0; /* pages */
! 687: long dumplo = 0; /* blocks */
! 688:
! 689: /*
! 690: * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
! 691: */
! 692: int
! 693: cpu_dumpsize(void)
! 694: {
! 695: int size;
! 696:
! 697: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
! 698: if (roundup(size, dbtob(1)) != dbtob(1))
! 699: return -1;
! 700:
! 701: return 1;
! 702: }
! 703:
! 704: /*
! 705: * Called from HPMC handler in locore
! 706: */
! 707: void
! 708: hpmc_dump(void)
! 709: {
! 710: printf("HPMC\n");
! 711:
! 712: cold = 0;
! 713: boot(RB_NOSYNC);
! 714: }
! 715:
! 716: int
! 717: cpu_dump(void)
! 718: {
! 719: long buf[dbtob(1) / sizeof (long)];
! 720: kcore_seg_t *segp;
! 721: cpu_kcore_hdr_t *cpuhdrp;
! 722:
! 723: segp = (kcore_seg_t *)buf;
! 724: cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)];
! 725:
! 726: /*
! 727: * Generate a segment header.
! 728: */
! 729: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 730: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
! 731:
! 732: /*
! 733: * Add the machine-dependent header info
! 734: */
! 735: /* nothing for now */
! 736:
! 737: return (bdevsw[major(dumpdev)].d_dump)
! 738: (dumpdev, dumplo, (caddr_t)buf, dbtob(1));
! 739: }
! 740:
! 741: /*
! 742: * Dump the kernel's image to the swap partition.
! 743: */
! 744: #define BYTES_PER_DUMP NBPG
! 745:
! 746: void
! 747: dumpsys(void)
! 748: {
! 749: int psize, bytes, i, n;
! 750: caddr_t maddr;
! 751: daddr64_t blkno;
! 752: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 753: int error;
! 754:
! 755: /* Save registers
! 756: savectx(&dumppcb); */
! 757:
! 758: if (dumpsize == 0)
! 759: dumpconf();
! 760: if (dumplo <= 0) {
! 761: printf("\ndump to dev %x not possible\n", dumpdev);
! 762: return;
! 763: }
! 764: printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
! 765:
! 766: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
! 767: printf("dump ");
! 768: if (psize == -1) {
! 769: printf("area unavailable\n");
! 770: return;
! 771: }
! 772:
! 773: if (!(error = cpu_dump())) {
! 774:
! 775: bytes = ctob(physmem);
! 776: maddr = NULL;
! 777: blkno = dumplo + cpu_dumpsize();
! 778: dump = bdevsw[major(dumpdev)].d_dump;
! 779: for (i = 0; i < bytes; i += n) {
! 780:
! 781: /* Print out how many MBs we are to go. */
! 782: n = bytes - i;
! 783: if (n && (n % (1024*1024)) == 0)
! 784: printf("%d ", n / (1024 * 1024));
! 785:
! 786: /* Limit size for next transfer. */
! 787: if (n > BYTES_PER_DUMP)
! 788: n = BYTES_PER_DUMP;
! 789:
! 790: if ((error = (*dump)(dumpdev, blkno, maddr, n)))
! 791: break;
! 792: maddr += n;
! 793: blkno += btodb(n);
! 794: }
! 795: }
! 796:
! 797: switch (error) {
! 798: case ENXIO: printf("device bad\n"); break;
! 799: case EFAULT: printf("device not ready\n"); break;
! 800: case EINVAL: printf("area improper\n"); break;
! 801: case EIO: printf("i/o error\n"); break;
! 802: case EINTR: printf("aborted from console\n"); break;
! 803: case 0: printf("succeeded\n"); break;
! 804: default: printf("error %d\n", error); break;
! 805: }
! 806: }
! 807:
! 808: /* bcopy(), error on fault */
! 809: int
! 810: kcopy(from, to, size)
! 811: const void *from;
! 812: void *to;
! 813: size_t size;
! 814: {
! 815: return spcopy(HPPA_SID_KERNEL, from, HPPA_SID_KERNEL, to, size);
! 816: }
! 817:
! 818: int
! 819: copystr(src, dst, size, lenp)
! 820: const void *src;
! 821: void *dst;
! 822: size_t size;
! 823: size_t *lenp;
! 824: {
! 825: return spstrcpy(HPPA_SID_KERNEL, src, HPPA_SID_KERNEL, dst, size, lenp);
! 826: }
! 827:
! 828: int
! 829: copyinstr(src, dst, size, lenp)
! 830: const void *src;
! 831: void *dst;
! 832: size_t size;
! 833: size_t *lenp;
! 834: {
! 835: return spstrcpy(curproc->p_addr->u_pcb.pcb_space, src,
! 836: HPPA_SID_KERNEL, dst, size, lenp);
! 837: }
! 838:
! 839:
! 840: int
! 841: copyoutstr(src, dst, size, lenp)
! 842: const void *src;
! 843: void *dst;
! 844: size_t size;
! 845: size_t *lenp;
! 846: {
! 847: return spstrcpy(HPPA_SID_KERNEL, src,
! 848: curproc->p_addr->u_pcb.pcb_space, dst, size, lenp);
! 849: }
! 850:
! 851:
! 852: int
! 853: copyin(src, dst, size)
! 854: const void *src;
! 855: void *dst;
! 856: size_t size;
! 857: {
! 858: return spcopy(curproc->p_addr->u_pcb.pcb_space, src,
! 859: HPPA_SID_KERNEL, dst, size);
! 860: }
! 861:
! 862: int
! 863: copyout(src, dst, size)
! 864: const void *src;
! 865: void *dst;
! 866: size_t size;
! 867: {
! 868: return spcopy(HPPA_SID_KERNEL, src,
! 869: curproc->p_addr->u_pcb.pcb_space, dst, size);
! 870: }
! 871:
! 872: /*
! 873: * Set registers on exec.
! 874: */
! 875: void
! 876: setregs(p, pack, stack, retval)
! 877: struct proc *p;
! 878: struct exec_package *pack;
! 879: u_long stack;
! 880: register_t *retval;
! 881: {
! 882: extern paddr_t fpu_curpcb; /* from locore.S */
! 883: struct trapframe *tf = p->p_md.md_regs;
! 884: struct pcb *pcb = &p->p_addr->u_pcb;
! 885: register_t zero;
! 886:
! 887: tf->tf_flags = TFF_SYS|TFF_LAST;
! 888: tf->tf_iioq[1] = 4 +
! 889: (tf->tf_iioq[0] = pack->ep_entry | HPPA_PC_PRIV_USER);
! 890: tf->tf_rp = 0;
! 891: tf->tf_args[0] = (u_long)PS_STRINGS;
! 892: tf->tf_args[1] = tf->tf_args[2] = 0; /* XXX dynload stuff */
! 893:
! 894: /* setup terminal stack frame */
! 895: stack = (stack + 0x1f) & ~0x1f;
! 896: tf->tf_r3 = stack;
! 897: tf->tf_sp = stack += HPPA_FRAME_SIZE;
! 898: tf->tf_ret1 = stack - 16; /* ap */
! 899: zero = 0;
! 900: copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t));
! 901: copyout(&zero, (caddr_t)(stack + HPPA_FRAME_RP), sizeof(register_t));
! 902:
! 903: /* reset any of the pending FPU exceptions */
! 904: if (tf->tf_cr30 == fpu_curpcb) {
! 905: fpu_exit();
! 906: fpu_curpcb = 0;
! 907: }
! 908: pcb->pcb_fpregs[0] = ((u_int64_t)HPPA_FPU_INIT) << 32;
! 909: pcb->pcb_fpregs[1] = 0;
! 910: pcb->pcb_fpregs[2] = 0;
! 911: pcb->pcb_fpregs[3] = 0;
! 912: fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4);
! 913:
! 914: retval[1] = 0;
! 915: }
! 916:
! 917: /*
! 918: * Send an interrupt to process.
! 919: */
! 920: void
! 921: sendsig(catcher, sig, mask, code, type, val)
! 922: sig_t catcher;
! 923: int sig, mask;
! 924: u_long code;
! 925: int type;
! 926: union sigval val;
! 927: {
! 928: extern paddr_t fpu_curpcb; /* from locore.S */
! 929: extern u_int fpu_enable;
! 930: struct proc *p = curproc;
! 931: struct trapframe *tf = p->p_md.md_regs;
! 932: struct sigacts *psp = p->p_sigacts;
! 933: struct sigcontext ksc;
! 934: siginfo_t ksi;
! 935: register_t scp, sip, zero;
! 936: int sss;
! 937:
! 938: /* TODO sendsig */
! 939:
! 940: #ifdef DEBUG
! 941: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 942: printf("sendsig: %s[%d] sig %d catcher %p\n",
! 943: p->p_comm, p->p_pid, sig, catcher);
! 944: #endif
! 945:
! 946: /* flush the FPU ctx first */
! 947: if (tf->tf_cr30 == fpu_curpcb) {
! 948: mtctl(fpu_enable, CR_CCR);
! 949: fpu_save(fpu_curpcb);
! 950: /* fpu_curpcb = 0; only needed if fpregs are preset */
! 951: mtctl(0, CR_CCR);
! 952: }
! 953:
! 954: ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 955:
! 956: /*
! 957: * Allocate space for the signal handler context.
! 958: */
! 959: if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
! 960: (psp->ps_sigonstack & sigmask(sig))) {
! 961: scp = (register_t)psp->ps_sigstk.ss_sp;
! 962: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 963: } else
! 964: scp = (tf->tf_sp + 63) & ~63;
! 965:
! 966: sss = (sizeof(ksc) + 63) & ~63;
! 967: sip = 0;
! 968: if (psp->ps_siginfo & sigmask(sig)) {
! 969: sip = scp + sizeof(ksc);
! 970: sss += (sizeof(ksi) + 63) & ~63;
! 971: }
! 972:
! 973: #ifdef DEBUG
! 974: if ((tf->tf_iioq[0] & ~PAGE_MASK) == SYSCALLGATE)
! 975: printf("sendsig: interrupted syscall at 0x%x:0x%x, flags %b\n",
! 976: tf->tf_iioq[0], tf->tf_iioq[1], tf->tf_ipsw, PSL_BITS);
! 977: #endif
! 978:
! 979: ksc.sc_mask = mask;
! 980: ksc.sc_fp = scp + sss;
! 981: ksc.sc_ps = tf->tf_ipsw;
! 982: ksc.sc_pcoqh = tf->tf_iioq[0];
! 983: ksc.sc_pcoqt = tf->tf_iioq[1];
! 984: bcopy(tf, &ksc.sc_regs[0], 32*8);
! 985: ksc.sc_regs[0] = tf->tf_sar;
! 986: bcopy(p->p_addr->u_pcb.pcb_fpregs, ksc.sc_fpregs,
! 987: sizeof(ksc.sc_fpregs));
! 988:
! 989: sss += HPPA_FRAME_SIZE;
! 990: tf->tf_args[0] = sig;
! 991: tf->tf_args[1] = sip;
! 992: tf->tf_args[2] = tf->tf_r4 = scp;
! 993: tf->tf_args[3] = (register_t)catcher;
! 994: tf->tf_sp = scp + sss;
! 995: tf->tf_ipsw &= ~(PSL_N|PSL_B);
! 996: tf->tf_iioq[0] = HPPA_PC_PRIV_USER | p->p_sigcode;
! 997: tf->tf_iioq[1] = tf->tf_iioq[0] + 4;
! 998: /* disable tracing in the trapframe */
! 999:
! 1000: #ifdef DEBUG
! 1001: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1002: printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n",
! 1003: p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss);
! 1004: #endif
! 1005:
! 1006: if (copyout(&ksc, (void *)scp, sizeof(ksc)))
! 1007: sigexit(p, SIGILL);
! 1008:
! 1009: if (sip) {
! 1010: initsiginfo(&ksi, sig, code, type, val);
! 1011: if (copyout(&ksi, (void *)sip, sizeof(ksi)))
! 1012: sigexit(p, SIGILL);
! 1013: }
! 1014:
! 1015: zero = 0;
! 1016: if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE,
! 1017: sizeof(register_t)))
! 1018: sigexit(p, SIGILL);
! 1019:
! 1020: #ifdef DEBUG
! 1021: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1022: printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
! 1023: tf->tf_iioq[0], tf->tf_args[3]);
! 1024: #endif
! 1025: }
! 1026:
! 1027: int
! 1028: sys_sigreturn(p, v, retval)
! 1029: struct proc *p;
! 1030: void *v;
! 1031: register_t *retval;
! 1032: {
! 1033: extern paddr_t fpu_curpcb; /* from locore.S */
! 1034: struct sys_sigreturn_args /* {
! 1035: syscallarg(struct sigcontext *) sigcntxp;
! 1036: } */ *uap = v;
! 1037: struct sigcontext *scp, ksc;
! 1038: struct trapframe *tf = p->p_md.md_regs;
! 1039: int error;
! 1040:
! 1041: /* TODO sigreturn */
! 1042:
! 1043: scp = SCARG(uap, sigcntxp);
! 1044: #ifdef DEBUG
! 1045: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1046: printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
! 1047: #endif
! 1048:
! 1049: /* flush the FPU ctx first */
! 1050: if (tf->tf_cr30 == fpu_curpcb) {
! 1051: fpu_exit();
! 1052: fpu_curpcb = 0;
! 1053: }
! 1054:
! 1055: if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)))
! 1056: return (error);
! 1057:
! 1058: #define PSL_MBS (PSL_C|PSL_Q|PSL_P|PSL_D|PSL_I)
! 1059: #define PSL_MBZ (PSL_Y|PSL_Z|PSL_S|PSL_X|PSL_M|PSL_R)
! 1060: if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS)
! 1061: return (EINVAL);
! 1062:
! 1063: if (ksc.sc_onstack)
! 1064: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1065: else
! 1066: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 1067: p->p_sigmask = ksc.sc_mask &~ sigcantmask;
! 1068:
! 1069: tf->tf_sar = ksc.sc_regs[0];
! 1070: ksc.sc_regs[0] = tf->tf_flags;
! 1071: bcopy(&ksc.sc_regs[0], tf, 32*8);
! 1072: bcopy(ksc.sc_fpregs, p->p_addr->u_pcb.pcb_fpregs,
! 1073: sizeof(ksc.sc_fpregs));
! 1074: fdcache(HPPA_SID_KERNEL, (vaddr_t)p->p_addr->u_pcb.pcb_fpregs,
! 1075: sizeof(ksc.sc_fpregs));
! 1076:
! 1077: tf->tf_iioq[0] = ksc.sc_pcoqh;
! 1078: tf->tf_iioq[1] = ksc.sc_pcoqt;
! 1079: tf->tf_ipsw = ksc.sc_ps;
! 1080:
! 1081: #ifdef DEBUG
! 1082: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1083: printf("sigreturn(%d): returns\n", p->p_pid);
! 1084: #endif
! 1085: return (EJUSTRETURN);
! 1086: }
! 1087:
! 1088: /*
! 1089: * machine dependent system variables.
! 1090: */
! 1091: int
! 1092: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 1093: int *name;
! 1094: u_int namelen;
! 1095: void *oldp;
! 1096: size_t *oldlenp;
! 1097: void *newp;
! 1098: size_t newlen;
! 1099: struct proc *p;
! 1100: {
! 1101: dev_t consdev;
! 1102:
! 1103: /* all sysctl names at this level are terminal */
! 1104: if (namelen != 1)
! 1105: return (ENOTDIR); /* overloaded */
! 1106: switch (name[0]) {
! 1107: case CPU_CONSDEV:
! 1108: if (cn_tab != NULL)
! 1109: consdev = cn_tab->cn_dev;
! 1110: else
! 1111: consdev = NODEV;
! 1112: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 1113: sizeof consdev));
! 1114: default:
! 1115: return (EOPNOTSUPP);
! 1116: }
! 1117: /* NOTREACHED */
! 1118: }
! 1119:
! 1120:
! 1121: /*
! 1122: * consinit:
! 1123: * initialize the system console.
! 1124: */
! 1125: void
! 1126: consinit(void)
! 1127: {
! 1128: static int initted;
! 1129:
! 1130: if (!initted) {
! 1131: initted++;
! 1132: cninit();
! 1133: }
! 1134: }
! 1135:
! 1136: #ifdef DIAGNOSTIC
! 1137: void
! 1138: splassert_check(int wantipl, const char *func)
! 1139: {
! 1140: extern int cpl; /* from locoore.s */
! 1141:
! 1142: if (cpl < wantipl) {
! 1143: splassert_fail(wantipl, cpl, func);
! 1144: }
! 1145: }
! 1146: #endif
CVSweb