Annotation of sys/arch/hppa/hppa/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.164 2007/07/22 19:24:45 kettenis Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1999-2003 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: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 26: * THE POSSIBILITY OF SUCH DAMAGE.
! 27: */
! 28:
! 29: #include <sys/param.h>
! 30: #include <sys/systm.h>
! 31: #include <sys/signalvar.h>
! 32: #include <sys/kernel.h>
! 33: #include <sys/proc.h>
! 34: #include <sys/buf.h>
! 35: #include <sys/reboot.h>
! 36: #include <sys/device.h>
! 37: #include <sys/conf.h>
! 38: #include <sys/file.h>
! 39: #include <sys/timeout.h>
! 40: #include <sys/malloc.h>
! 41: #include <sys/mbuf.h>
! 42: #include <sys/msgbuf.h>
! 43: #include <sys/ioctl.h>
! 44: #include <sys/tty.h>
! 45: #include <sys/user.h>
! 46: #include <sys/exec.h>
! 47: #include <sys/sysctl.h>
! 48: #include <sys/core.h>
! 49: #include <sys/kcore.h>
! 50: #include <sys/extent.h>
! 51: #ifdef SYSVMSG
! 52: #include <sys/msg.h>
! 53: #endif
! 54:
! 55: #include <sys/mount.h>
! 56: #include <sys/syscallargs.h>
! 57:
! 58: #include <uvm/uvm.h>
! 59: #include <uvm/uvm_page.h>
! 60:
! 61: #include <dev/cons.h>
! 62:
! 63: #include <machine/pdc.h>
! 64: #include <machine/iomod.h>
! 65: #include <machine/psl.h>
! 66: #include <machine/reg.h>
! 67: #include <machine/cpufunc.h>
! 68: #include <machine/autoconf.h>
! 69: #include <machine/kcore.h>
! 70:
! 71: #ifdef COMPAT_HPUX
! 72: #include <compat/hpux/hpux.h>
! 73: #include <compat/hpux/hpux_sig.h>
! 74: #include <compat/hpux/hpux_util.h>
! 75: #include <compat/hpux/hpux_syscallargs.h>
! 76: #include <machine/hpux_machdep.h>
! 77: #endif
! 78:
! 79: #ifdef DDB
! 80: #include <machine/db_machdep.h>
! 81: #include <ddb/db_access.h>
! 82: #include <ddb/db_sym.h>
! 83: #include <ddb/db_extern.h>
! 84: #endif
! 85:
! 86: #include <hppa/dev/cpudevs.h>
! 87:
! 88: /*
! 89: * Patchable buffer cache parameters
! 90: */
! 91: #ifndef BUFCACHEPERCENT
! 92: #define BUFCACHEPERCENT 10
! 93: #endif /* BUFCACHEPERCENT */
! 94:
! 95: #ifdef BUFPAGES
! 96: int bufpages = BUFPAGES;
! 97: #else
! 98: int bufpages = 0;
! 99: #endif
! 100: int bufcachepercent = BUFCACHEPERCENT;
! 101:
! 102: /*
! 103: * Different kinds of flags used throughout the kernel.
! 104: */
! 105: int cold = 1; /* unset when engine is up to go */
! 106: extern int msgbufmapped; /* set when safe to use msgbuf */
! 107:
! 108: /*
! 109: * cache configuration, for most machines is the same
! 110: * numbers, so it makes sense to do defines w/ numbers depending
! 111: * on configured cpu types in the kernel
! 112: */
! 113: int icache_stride, icache_line_mask;
! 114: int dcache_stride, dcache_line_mask;
! 115:
! 116: /*
! 117: * things to not kill
! 118: */
! 119: volatile u_int8_t *machine_ledaddr;
! 120: int machine_ledword, machine_leds;
! 121: struct cpu_info cpu_info_primary;
! 122:
! 123: /*
! 124: * CPU params (should be the same for all cpus in the system)
! 125: */
! 126: struct pdc_cache pdc_cache PDC_ALIGNMENT;
! 127: struct pdc_btlb pdc_btlb PDC_ALIGNMENT;
! 128: struct pdc_model pdc_model PDC_ALIGNMENT;
! 129:
! 130: /* w/ a little deviation should be the same for all installed cpus */
! 131: u_int cpu_ticksnum, cpu_ticksdenom;
! 132:
! 133: /* exported info */
! 134: char machine[] = MACHINE;
! 135: char cpu_model[128];
! 136: enum hppa_cpu_type cpu_type;
! 137: const char *cpu_typename;
! 138: int cpu_hvers;
! 139: u_int fpu_version;
! 140: #ifdef COMPAT_HPUX
! 141: int cpu_model_hpux; /* contains HPUX_SYSCONF_CPU* kind of value */
! 142: #endif
! 143:
! 144: int led_blink;
! 145:
! 146: /*
! 147: * exported methods for cpus
! 148: */
! 149: int (*cpu_desidhash)(void);
! 150: int (*cpu_hpt_init)(vaddr_t hpt, vsize_t hptsize);
! 151: int (*cpu_ibtlb_ins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 152: vsize_t sz, u_int prot);
! 153: int (*cpu_dbtlb_ins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 154: vsize_t sz, u_int prot);
! 155:
! 156: dev_t bootdev;
! 157: int physmem, resvmem, resvphysmem, esym;
! 158: paddr_t avail_end;
! 159:
! 160: /*
! 161: * Things for MI glue to stick on.
! 162: */
! 163: struct user *proc0paddr;
! 164: long mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)];
! 165: struct extent *hppa_ex;
! 166:
! 167: struct vm_map *exec_map = NULL;
! 168: struct vm_map *phys_map = NULL;
! 169: /* Virtual page frame for /dev/mem (see mem.c) */
! 170: vaddr_t vmmap;
! 171:
! 172: void delay_init(void);
! 173: static __inline void fall(int, int, int, int, int);
! 174: void dumpsys(void);
! 175: void hpmc_dump(void);
! 176: void cpuid(void);
! 177: void blink_led_timeout(void *);
! 178:
! 179: /*
! 180: * wide used hardware params
! 181: */
! 182: struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT;
! 183: struct pdc_coproc pdc_coproc PDC_ALIGNMENT;
! 184: struct pdc_coherence pdc_coherence PDC_ALIGNMENT;
! 185: struct pdc_spidb pdc_spidbits PDC_ALIGNMENT;
! 186: struct pdc_model pdc_model PDC_ALIGNMENT;
! 187:
! 188: #ifdef DEBUG
! 189: int sigdebug = 0;
! 190: pid_t sigpid = 0;
! 191: #define SDB_FOLLOW 0x01
! 192: #endif
! 193:
! 194: /*
! 195: * Whatever CPU types we support
! 196: */
! 197: extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[];
! 198: extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[];
! 199: extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[];
! 200: extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[];
! 201: extern const u_int itlb_u[], itlbna_u[], dtlb_u[], dtlbna_u[], tlbd_u[];
! 202: int iibtlb_s(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 203: vsize_t sz, u_int prot);
! 204: int idbtlb_s(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 205: vsize_t sz, u_int prot);
! 206: int ibtlb_t(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 207: vsize_t sz, u_int prot);
! 208: int ibtlb_l(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 209: vsize_t sz, u_int prot);
! 210: int ibtlb_u(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 211: vsize_t sz, u_int prot);
! 212: int ibtlb_g(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 213: vsize_t sz, u_int prot);
! 214: int pbtlb_g(int i);
! 215: int pbtlb_u(int i);
! 216: int hpti_l(vaddr_t, vsize_t);
! 217: int hpti_u(vaddr_t, vsize_t);
! 218: int hpti_g(vaddr_t, vsize_t);
! 219: int desidhash_x(void);
! 220: int desidhash_s(void);
! 221: int desidhash_t(void);
! 222: int desidhash_l(void);
! 223: int desidhash_u(void);
! 224: const struct hppa_cpu_typed {
! 225: char name[8];
! 226: enum hppa_cpu_type type;
! 227: int cpuid;
! 228: int features;
! 229: int patch;
! 230: int (*desidhash)(void);
! 231: int (*dbtlbins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 232: vsize_t sz, u_int prot);
! 233: int (*ibtlbins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
! 234: vsize_t sz, u_int prot);
! 235: int (*btlbprg)(int i);
! 236: int (*hptinit)(vaddr_t hpt, vsize_t hptsize);
! 237: } cpu_types[] = {
! 238: #ifdef HP7000_CPU
! 239: { "PCXS", hpcxs, 0, 0, 3, desidhash_s, ibtlb_g, NULL, pbtlb_g},
! 240: #endif
! 241: #ifdef HP7100_CPU
! 242: { "PCXT", hpcxt, 0, HPPA_FTRS_BTLBU,
! 243: 2, desidhash_t, ibtlb_g, NULL, pbtlb_g},
! 244: #endif
! 245: #ifdef HP7200_CPU
! 246: { "PCXT'", hpcxta,HPPA_CPU_PCXT2, HPPA_FTRS_BTLBU,
! 247: 2, desidhash_t, ibtlb_g, NULL, pbtlb_g},
! 248: #endif
! 249: #ifdef HP7100LC_CPU
! 250: { "PCXL", hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
! 251: 0, desidhash_l, ibtlb_g, NULL, pbtlb_g, hpti_g},
! 252: #endif
! 253: #ifdef HP7300LC_CPU
! 254: { "PCXL2", hpcxl2,HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
! 255: 0, desidhash_l, ibtlb_g, NULL, pbtlb_g, hpti_g},
! 256: #endif
! 257: #ifdef HP8000_CPU
! 258: { "PCXU", hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B,
! 259: 4, desidhash_u, ibtlb_u, NULL, pbtlb_u },
! 260: #endif
! 261: #ifdef HP8200_CPU
! 262: { "PCXU+", hpcxu2,HPPA_CPU_PCXUP, HPPA_FTRS_W32B,
! 263: 4, desidhash_u, ibtlb_u, NULL, pbtlb_u },
! 264: #endif
! 265: #ifdef HP8500_CPU
! 266: { "PCXW", hpcxw, HPPA_CPU_PCXW, HPPA_FTRS_W32B,
! 267: 4, desidhash_u, ibtlb_u, NULL, pbtlb_u },
! 268: #endif
! 269: #ifdef HP8700_CPU
! 270: { "PCXW2", hpcxw, HPPA_CPU_PCXW2, HPPA_FTRS_W32B,
! 271: 4, desidhash_u, ibtlb_u, NULL, pbtlb_u },
! 272: #endif
! 273: { "", 0 }
! 274: };
! 275:
! 276: int
! 277: hppa_cpuspeed(int *mhz)
! 278: {
! 279: *mhz = PAGE0->mem_10msec / 10000;
! 280:
! 281: return (0);
! 282: }
! 283:
! 284: void
! 285: hppa_init(start)
! 286: paddr_t start;
! 287: {
! 288: extern u_long cpu_hzticks;
! 289: extern int kernel_text;
! 290: vaddr_t v, v1;
! 291: int error;
! 292:
! 293: pdc_init(); /* init PDC iface, so we can call em easy */
! 294:
! 295: cpu_hzticks = (PAGE0->mem_10msec * 100) / hz;
! 296: delay_init(); /* calculate cpu clock ratio */
! 297:
! 298: /* cache parameters */
! 299: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT,
! 300: &pdc_cache)) < 0) {
! 301: #ifdef DEBUG
! 302: printf("WARNING: PDC_CACHE error %d\n", error);
! 303: #endif
! 304: }
! 305:
! 306: dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1;
! 307: dcache_stride = pdc_cache.dc_stride;
! 308: icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1;
! 309: icache_stride = pdc_cache.ic_stride;
! 310:
! 311: /* cache coherence params (pbably available for 8k only) */
! 312: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS,
! 313: &pdc_coherence, 1, 1, 1, 1);
! 314: #ifdef DEBUG
! 315: printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n",
! 316: pdc_coherence.ia_cst, pdc_coherence.da_cst,
! 317: pdc_coherence.ita_cst, pdc_coherence.dta_cst, error);
! 318: #endif
! 319: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB,
! 320: &pdc_spidbits, 0, 0, 0, 0);
! 321: printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error);
! 322:
! 323: /* setup hpmc handler */
! 324: {
! 325: extern u_int hpmc_v[]; /* from locore.s */
! 326: register u_int *p = hpmc_v;
! 327:
! 328: if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p))
! 329: *p = 0x08000240;
! 330:
! 331: p[6] = (u_int)&hpmc_dump;
! 332: p[7] = 32;
! 333: p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]);
! 334: }
! 335:
! 336: {
! 337: extern u_int hppa_toc[], hppa_toc_end[];
! 338: register u_int cksum, *p;
! 339:
! 340: for (cksum = 0, p = hppa_toc; p < hppa_toc_end; p++)
! 341: cksum += *p;
! 342:
! 343: *p = cksum;
! 344: PAGE0->ivec_toc = (u_int)hppa_toc;
! 345: PAGE0->ivec_toclen = (hppa_toc_end - hppa_toc + 1) * 4;
! 346: }
! 347:
! 348: {
! 349: extern u_int hppa_pfr[], hppa_pfr_end[];
! 350: register u_int cksum, *p;
! 351:
! 352: for (cksum = 0, p = hppa_pfr; p < hppa_pfr_end; p++)
! 353: cksum += *p;
! 354:
! 355: *p = cksum;
! 356: PAGE0->ivec_mempf = (u_int)hppa_pfr;
! 357: PAGE0->ivec_mempflen = (hppa_pfr_end - hppa_pfr + 1) * 4;
! 358: }
! 359:
! 360: cpuid();
! 361: ptlball();
! 362: ficacheall();
! 363: fdcacheall();
! 364:
! 365: avail_end = trunc_page(PAGE0->imm_max_mem);
! 366: if (avail_end > SYSCALLGATE)
! 367: avail_end = SYSCALLGATE;
! 368: physmem = btoc(avail_end);
! 369: resvmem = btoc(((vaddr_t)&kernel_text));
! 370:
! 371: /* we hope this won't fail */
! 372: hppa_ex = extent_create("mem", 0x0, 0xffffffff, M_DEVBUF,
! 373: (caddr_t)mem_ex_storage, sizeof(mem_ex_storage),
! 374: EX_NOCOALESCE|EX_NOWAIT);
! 375: if (extent_alloc_region(hppa_ex, 0, (vaddr_t)PAGE0->imm_max_mem,
! 376: EX_NOWAIT))
! 377: panic("cannot reserve main memory");
! 378:
! 379: /*
! 380: * Now allocate kernel dynamic variables
! 381: */
! 382:
! 383: v1 = v = round_page(start);
! 384: #define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num))
! 385:
! 386: #ifdef SYSVMSG
! 387: valloc(msgpool, char, msginfo.msgmax);
! 388: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 389: valloc(msghdrs, struct msg, msginfo.msgtql);
! 390: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 391: #endif
! 392: #undef valloc
! 393: v = round_page(v);
! 394: bzero ((void *)v1, (v - v1));
! 395:
! 396: /* sets resvphysmem */
! 397: pmap_bootstrap(v);
! 398:
! 399: /* space has been reserved in pmap_bootstrap() */
! 400: initmsgbuf((caddr_t)(ptoa(physmem) - round_page(MSGBUFSIZE)),
! 401: round_page(MSGBUFSIZE));
! 402:
! 403: /* they say PDC_COPROC might turn fault light on */
! 404: pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP,
! 405: PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0);
! 406:
! 407: cpu_cpuspeed = &hppa_cpuspeed;
! 408: #ifdef DDB
! 409: ddb_init();
! 410: #endif
! 411: ficacheall();
! 412: fdcacheall();
! 413: }
! 414:
! 415: void
! 416: cpuid()
! 417: {
! 418: /*
! 419: * Ptrs to various tlb handlers, to be filled
! 420: * based on cpu features.
! 421: * from locore.S
! 422: */
! 423: extern u_int trap_ep_T_TLB_DIRTY[];
! 424: extern u_int trap_ep_T_DTLBMISS[];
! 425: extern u_int trap_ep_T_DTLBMISSNA[];
! 426: extern u_int trap_ep_T_ITLBMISS[];
! 427: extern u_int trap_ep_T_ITLBMISSNA[];
! 428:
! 429: extern u_int fpu_enable;
! 430: extern int cpu_fpuena;
! 431: struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT;
! 432: const struct hppa_cpu_typed *p = NULL;
! 433: u_int cpu_features;
! 434: int error;
! 435:
! 436: /* may the scientific guessing begin */
! 437: cpu_features = 0;
! 438: cpu_type = 0;
! 439:
! 440: /* identify system type */
! 441: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO,
! 442: &pdc_model)) < 0) {
! 443: #ifdef DEBUG
! 444: printf("WARNING: PDC_MODEL error %d\n", error);
! 445: #endif
! 446: pdc_model.hvers = 0;
! 447: }
! 448:
! 449: bzero(&pdc_cpuid, sizeof(pdc_cpuid));
! 450: if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID,
! 451: &pdc_cpuid, 0, 0, 0, 0) >= 0) {
! 452:
! 453: /* patch for old 8200 */
! 454: if (pdc_cpuid.version == HPPA_CPU_PCXU &&
! 455: pdc_cpuid.revision > 0x0d)
! 456: pdc_cpuid.version = HPPA_CPU_PCXUP;
! 457:
! 458: cpu_type = pdc_cpuid.version;
! 459: }
! 460:
! 461: /* locate coprocessors and SFUs */
! 462: bzero(&pdc_coproc, sizeof(pdc_coproc));
! 463: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT,
! 464: &pdc_coproc, 0, 0, 0, 0)) < 0) {
! 465: printf("WARNING: PDC_COPROC error %d\n", error);
! 466: cpu_fpuena = 0;
! 467: } else {
! 468: printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n",
! 469: pdc_coproc.ccr_enable, pdc_coproc.ccr_present,
! 470: pdc_coproc.fpu_model, pdc_coproc.fpu_revision);
! 471: fpu_enable = pdc_coproc.ccr_enable & CCR_MASK;
! 472: cpu_fpuena = 1;
! 473:
! 474: /* a kludge to detect PCXW */
! 475: if (pdc_coproc.fpu_model == HPPA_FPU_PCXW)
! 476: cpu_type = HPPA_CPU_PCXW;
! 477: }
! 478:
! 479: /* BTLB params */
! 480: if (cpu_type < HPPA_CPU_PCXU &&
! 481: (error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB,
! 482: PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) {
! 483: #ifdef DEBUG
! 484: printf("WARNING: PDC_BTLB error %d\n", error);
! 485: #endif
! 486: } else {
! 487: #ifdef BTLBDEBUG
! 488: printf("btlb info: minsz=%d, maxsz=%d\n",
! 489: pdc_btlb.min_size, pdc_btlb.max_size);
! 490: printf("btlb fixed: i=%d, d=%d, c=%d\n",
! 491: pdc_btlb.finfo.num_i,
! 492: pdc_btlb.finfo.num_d,
! 493: pdc_btlb.finfo.num_c);
! 494: printf("btlb varbl: i=%d, d=%d, c=%d\n",
! 495: pdc_btlb.vinfo.num_i,
! 496: pdc_btlb.vinfo.num_d,
! 497: pdc_btlb.vinfo.num_c);
! 498: #endif /* BTLBDEBUG */
! 499: /* purge TLBs and caches */
! 500: if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB,
! 501: PDC_BTLB_PURGE_ALL) < 0)
! 502: printf("WARNING: BTLB purge failed\n");
! 503:
! 504: if (pdc_btlb.finfo.num_c)
! 505: cpu_features |= HPPA_FTRS_BTLBU;
! 506: }
! 507:
! 508: if (!pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) &&
! 509: pdc_hwtlb.min_size && pdc_hwtlb.max_size) {
! 510: cpu_features |= HPPA_FTRS_HVT;
! 511: if (pmap_hptsize > pdc_hwtlb.max_size)
! 512: pmap_hptsize = pdc_hwtlb.max_size;
! 513: else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size)
! 514: pmap_hptsize = pdc_hwtlb.min_size;
! 515: } else {
! 516: #ifdef DEBUG
! 517: printf("WARNING: no HPT support, fine!\n");
! 518: #endif
! 519: pmap_hptsize = 0;
! 520: }
! 521:
! 522: if (cpu_type)
! 523: for (p = cpu_types; p->name[0] && p->cpuid != cpu_type; p++);
! 524: else
! 525: for (p = cpu_types;
! 526: p->name[0] && p->features != cpu_features; p++);
! 527:
! 528: if (!p->name[0]) {
! 529: printf("WARNING: UNKNOWN CPU TYPE; GOOD LUCK "
! 530: "(type 0x%x, features 0x%x)\n", cpu_type, cpu_features);
! 531: p = cpu_types;
! 532: } else if ((p->type == hpcxl || p->type == hpcxl2) && !fpu_enable) {
! 533: /* we know PCXL and PCXL2 do not exist w/o FPU */
! 534: fpu_enable = 0xc0;
! 535: cpu_fpuena = 1;
! 536: }
! 537:
! 538: /*
! 539: * TODO: HPT on 7200 is not currently supported
! 540: */
! 541: if (pmap_hptsize && p->type != hpcxl && p->type != hpcxl2)
! 542: pmap_hptsize = 0;
! 543:
! 544: cpu_type = p->type;
! 545: cpu_typename = p->name;
! 546: cpu_ibtlb_ins = p->ibtlbins;
! 547: cpu_dbtlb_ins = p->dbtlbins;
! 548: cpu_hpt_init = p->hptinit;
! 549: cpu_desidhash = p->desidhash;
! 550:
! 551: /* patch tlb handler branches */
! 552: if (p->patch) {
! 553: trap_ep_T_TLB_DIRTY [0] = trap_ep_T_TLB_DIRTY [p->patch];
! 554: trap_ep_T_DTLBMISS [0] = trap_ep_T_DTLBMISS [p->patch];
! 555: trap_ep_T_DTLBMISSNA[0] = trap_ep_T_DTLBMISSNA[p->patch];
! 556: trap_ep_T_ITLBMISS [0] = trap_ep_T_ITLBMISS [p->patch];
! 557: trap_ep_T_ITLBMISSNA[0] = trap_ep_T_ITLBMISSNA[p->patch];
! 558: }
! 559:
! 560: /* force strong ordering for now */
! 561: if (p->features & HPPA_FTRS_W32B) {
! 562: extern register_t kpsw; /* intr.c */
! 563:
! 564: kpsw |= PSL_O;
! 565: }
! 566:
! 567: {
! 568: const char *p, *q;
! 569: char buf[32];
! 570: int lev;
! 571:
! 572: lev = 0xa + (*cpu_desidhash)();
! 573: cpu_hvers = pdc_model.hvers >> 4;
! 574: if (!cpu_hvers) {
! 575: p = "(UNKNOWN)";
! 576: q = lev == 0xa? "1.0" : "1.1";
! 577: } else {
! 578: p = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers);
! 579: if (!p) {
! 580: snprintf(buf, sizeof buf, "(UNKNOWN 0x%x)",
! 581: cpu_hvers);
! 582: p = buf;
! 583: }
! 584:
! 585: switch (pdc_model.arch_rev) {
! 586: default:
! 587: case 0:
! 588: q = "1.0";
! 589: #ifdef COMPAT_HPUX
! 590: cpu_model_hpux = HPUX_SYSCONF_CPUPA10;
! 591: #endif
! 592: break;
! 593: case 4:
! 594: q = "1.1";
! 595: #ifdef COMPAT_HPUX
! 596: cpu_model_hpux = HPUX_SYSCONF_CPUPA11;
! 597: #endif
! 598: /* this one is just a 100MHz pcxl */
! 599: if (lev == 0x10)
! 600: lev = 0xc;
! 601: /* this one is a pcxl2 */
! 602: if (lev == 0x16)
! 603: lev = 0xe;
! 604: break;
! 605: case 8:
! 606: q = "2.0";
! 607: #ifdef COMPAT_HPUX
! 608: cpu_model_hpux = HPUX_SYSCONF_CPUPA20;
! 609: #endif
! 610: break;
! 611: }
! 612: }
! 613:
! 614: snprintf(cpu_model, sizeof cpu_model,
! 615: "HP 9000/%s PA-RISC %s%x", p, q, lev);
! 616: }
! 617: #ifdef DEBUG
! 618: printf("cpu: %s\n", cpu_model);
! 619: #endif
! 620: }
! 621:
! 622: void
! 623: cpu_startup(void)
! 624: {
! 625: vaddr_t minaddr, maxaddr;
! 626:
! 627: /*
! 628: * i won't understand a friend of mine,
! 629: * who sat in a room full of artificial ice,
! 630: * fogging the air w/ humid cries --
! 631: * WELCOME TO SUMMER!
! 632: */
! 633: printf(version);
! 634:
! 635: printf("%s\n", cpu_model);
! 636: printf("real mem = %u (%u reserved for PROM, %u used by OpenBSD)\n",
! 637: ctob(physmem), ctob(resvmem), ctob(resvphysmem - resvmem));
! 638:
! 639: /*
! 640: * Determine how many buffers to allocate.
! 641: * We allocate bufcachepercent% of memory for buffer space.
! 642: */
! 643: if (bufpages == 0)
! 644: bufpages = physmem * bufcachepercent / 100;
! 645:
! 646: /* Restrict to at most 25% filled kvm */
! 647: if (bufpages >
! 648: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 649: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 650: PAGE_SIZE / 4;
! 651:
! 652: /*
! 653: * Allocate a submap for exec arguments. This map effectively
! 654: * limits the number of processes exec'ing at any time.
! 655: */
! 656: minaddr = vm_map_min(kernel_map);
! 657: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 658: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 659:
! 660: /*
! 661: * Allocate a submap for physio
! 662: */
! 663: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 664: VM_PHYS_SIZE, 0, FALSE, NULL);
! 665:
! 666: printf("avail mem = %lu\n", ptoa(uvmexp.free));
! 667:
! 668: /*
! 669: * Set up buffers, so they can be used to read disk labels.
! 670: */
! 671: bufinit();
! 672: vmmap = uvm_km_valloc_wait(kernel_map, NBPG);
! 673:
! 674: /*
! 675: * Configure the system.
! 676: */
! 677: if (boothowto & RB_CONFIG) {
! 678: #ifdef BOOT_CONFIG
! 679: user_config();
! 680: #else
! 681: printf("kernel does not support -c; continuing..\n");
! 682: #endif
! 683: }
! 684: }
! 685:
! 686: /*
! 687: * compute cpu clock ratio such as:
! 688: * cpu_ticksnum / cpu_ticksdenom = t + delta
! 689: * delta -> 0
! 690: */
! 691: void
! 692: delay_init(void)
! 693: {
! 694: register u_int num, denom, delta, mdelta;
! 695:
! 696: mdelta = UINT_MAX;
! 697: for (denom = 1; denom < 1000; denom++) {
! 698: num = (PAGE0->mem_10msec * denom) / 10000;
! 699: delta = num * 10000 / denom - PAGE0->mem_10msec;
! 700: if (!delta) {
! 701: cpu_ticksdenom = denom;
! 702: cpu_ticksnum = num;
! 703: break;
! 704: } else if (delta < mdelta) {
! 705: cpu_ticksdenom = denom;
! 706: cpu_ticksnum = num;
! 707: mdelta = delta;
! 708: }
! 709: }
! 710: }
! 711:
! 712: void
! 713: delay(us)
! 714: u_int us;
! 715: {
! 716: register u_int start, end, n;
! 717:
! 718: mfctl(CR_ITMR, start);
! 719: while (us) {
! 720: n = min(1000, us);
! 721: end = start + n * cpu_ticksnum / cpu_ticksdenom;
! 722:
! 723: /* N.B. Interval Timer may wrap around */
! 724: if (end < start)
! 725: do
! 726: mfctl(CR_ITMR, start);
! 727: while (start > end);
! 728:
! 729: do
! 730: mfctl(CR_ITMR, start);
! 731: while (start < end);
! 732:
! 733: us -= n;
! 734: }
! 735: }
! 736:
! 737: static __inline void
! 738: fall(c_base, c_count, c_loop, c_stride, data)
! 739: int c_base, c_count, c_loop, c_stride, data;
! 740: {
! 741: register int loop;
! 742:
! 743: for (; c_count--; c_base += c_stride)
! 744: for (loop = c_loop; loop--; )
! 745: if (data)
! 746: fdce(0, c_base);
! 747: else
! 748: fice(0, c_base);
! 749: }
! 750:
! 751: void
! 752: ficacheall(void)
! 753: {
! 754: /*
! 755: * Flush the instruction, then data cache.
! 756: */
! 757: fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop,
! 758: pdc_cache.ic_stride, 0);
! 759: sync_caches();
! 760: }
! 761:
! 762: void
! 763: fdcacheall(void)
! 764: {
! 765: fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop,
! 766: pdc_cache.dc_stride, 1);
! 767: sync_caches();
! 768: }
! 769:
! 770: void
! 771: ptlball(void)
! 772: {
! 773: register pa_space_t sp;
! 774: register int i, j, k;
! 775:
! 776: /* instruction TLB */
! 777: sp = pdc_cache.it_sp_base;
! 778: for (i = 0; i < pdc_cache.it_sp_count; i++) {
! 779: register vaddr_t off = pdc_cache.it_off_base;
! 780: for (j = 0; j < pdc_cache.it_off_count; j++) {
! 781: for (k = 0; k < pdc_cache.it_loop; k++)
! 782: pitlbe(sp, off);
! 783: off += pdc_cache.it_off_stride;
! 784: }
! 785: sp += pdc_cache.it_sp_stride;
! 786: }
! 787:
! 788: /* data TLB */
! 789: sp = pdc_cache.dt_sp_base;
! 790: for (i = 0; i < pdc_cache.dt_sp_count; i++) {
! 791: register vaddr_t off = pdc_cache.dt_off_base;
! 792: for (j = 0; j < pdc_cache.dt_off_count; j++) {
! 793: for (k = 0; k < pdc_cache.dt_loop; k++)
! 794: pdtlbe(sp, off);
! 795: off += pdc_cache.dt_off_stride;
! 796: }
! 797: sp += pdc_cache.dt_sp_stride;
! 798: }
! 799: }
! 800:
! 801: int
! 802: hpti_g(hpt, hptsize)
! 803: vaddr_t hpt;
! 804: vsize_t hptsize;
! 805: {
! 806: return pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG,
! 807: &pdc_hwtlb, hpt, hptsize, PDC_TLB_CURRPDE);
! 808: }
! 809:
! 810: int
! 811: pbtlb_g(i)
! 812: int i;
! 813: {
! 814: return -1;
! 815: }
! 816:
! 817: int
! 818: ibtlb_g(i, sp, va, pa, sz, prot)
! 819: int i;
! 820: pa_space_t sp;
! 821: vaddr_t va;
! 822: paddr_t pa;
! 823: vsize_t sz;
! 824: u_int prot;
! 825: {
! 826: int error;
! 827:
! 828: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT,
! 829: sp, va, pa, sz, prot, i)) < 0) {
! 830: #ifdef BTLBDEBUG
! 831: printf("WARNING: BTLB insert failed (%d)\n", error);
! 832: #endif
! 833: }
! 834: return error;
! 835: }
! 836:
! 837: int
! 838: btlb_insert(space, va, pa, lenp, prot)
! 839: pa_space_t space;
! 840: vaddr_t va;
! 841: paddr_t pa;
! 842: vsize_t *lenp;
! 843: u_int prot;
! 844: {
! 845: static u_int32_t mask;
! 846: register vsize_t len;
! 847: register int error, i;
! 848:
! 849: if (!pdc_btlb.min_size && !pdc_btlb.max_size)
! 850: return -(ENXIO);
! 851:
! 852: /* align size */
! 853: for (len = pdc_btlb.min_size << PGSHIFT; len < *lenp; len <<= 1);
! 854: len >>= PGSHIFT;
! 855: i = ffs(~mask) - 1;
! 856: if (len > pdc_btlb.max_size || i < 0) {
! 857: #ifdef BTLBDEBUG
! 858: printf("btln_insert: too big (%u < %u < %u)\n",
! 859: pdc_btlb.min_size, len, pdc_btlb.max_size);
! 860: #endif
! 861: return -(ENOMEM);
! 862: }
! 863:
! 864: mask |= 1 << i;
! 865: pa >>= PGSHIFT;
! 866: va >>= PGSHIFT;
! 867: /* check address alignment */
! 868: if (pa & (len - 1)) {
! 869: #ifdef BTLBDEBUG
! 870: printf("WARNING: BTLB address misaligned pa=0x%x, len=0x%x\n",
! 871: pa, len);
! 872: #endif
! 873: return -(ERANGE);
! 874: }
! 875:
! 876: /* ensure IO space is uncached */
! 877: if ((pa & (HPPA_IOBEGIN >> PGSHIFT)) == (HPPA_IOBEGIN >> PGSHIFT))
! 878: prot |= TLB_UNCACHABLE;
! 879:
! 880: #ifdef BTLBDEBUG
! 881: printf("btlb_insert(%d): %x:%x=%x[%x,%x]\n", i, space, va, pa, len, prot);
! 882: #endif
! 883: if ((error = (*cpu_dbtlb_ins)(i, space, va, pa, len, prot)) < 0)
! 884: return -(EINVAL);
! 885: *lenp = len << PGSHIFT;
! 886:
! 887: return i;
! 888: }
! 889:
! 890: int waittime = -1;
! 891:
! 892: void
! 893: boot(howto)
! 894: int howto;
! 895: {
! 896: /* If system is cold, just halt. */
! 897: if (cold) {
! 898: /* (Unless the user explicitly asked for reboot.) */
! 899: if ((howto & RB_USERREQ) == 0)
! 900: howto |= RB_HALT;
! 901: } else {
! 902:
! 903: boothowto = howto | (boothowto & RB_HALT);
! 904:
! 905: if (!(howto & RB_NOSYNC)) {
! 906: waittime = 0;
! 907: vfs_shutdown();
! 908: /*
! 909: * If we've been adjusting the clock, the todr
! 910: * will be out of synch; adjust it now unless
! 911: * the system was sitting in ddb.
! 912: */
! 913: if ((howto & RB_TIMEBAD) == 0)
! 914: resettodr();
! 915: else
! 916: printf("WARNING: not updating battery clock\n");
! 917: }
! 918:
! 919: /* XXX probably save howto into stable storage */
! 920:
! 921: splhigh();
! 922:
! 923: if (howto & RB_DUMP)
! 924: dumpsys();
! 925:
! 926: doshutdownhooks();
! 927: }
! 928:
! 929: /* in case we came on powerfail interrupt */
! 930: if (cold_hook)
! 931: (*cold_hook)(HPPA_COLD_COLD);
! 932:
! 933: if (howto & RB_HALT) {
! 934: if (howto & RB_POWERDOWN && cold_hook) {
! 935: printf("Powering off...");
! 936: DELAY(2000000);
! 937: (*cold_hook)(HPPA_COLD_OFF);
! 938: DELAY(1000000);
! 939: }
! 940:
! 941: printf("System halted!\n");
! 942: DELAY(2000000);
! 943: __asm __volatile("stwas %0, 0(%1)"
! 944: :: "r" (CMD_STOP), "r" (HPPA_LBCAST + iomod_command));
! 945: } else {
! 946: printf("rebooting...");
! 947: DELAY(2000000);
! 948:
! 949: /* ask firmware to reset */
! 950: pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET);
! 951:
! 952: /* forcably reset module if that fails */
! 953: __asm __volatile(".export hppa_reset, entry\n\t"
! 954: ".label hppa_reset");
! 955: __asm __volatile("stwas %0, 0(%1)"
! 956: :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command));
! 957: }
! 958:
! 959: for(;;); /* loop while bus reset is comming up */
! 960: /* NOTREACHED */
! 961: }
! 962:
! 963: u_long dumpmag = 0x8fca0101; /* magic number */
! 964: int dumpsize = 0; /* pages */
! 965: long dumplo = 0; /* blocks */
! 966:
! 967: /*
! 968: * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
! 969: */
! 970: int
! 971: cpu_dumpsize(void)
! 972: {
! 973: int size;
! 974:
! 975: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
! 976: if (roundup(size, dbtob(1)) != dbtob(1))
! 977: return -1;
! 978:
! 979: return 1;
! 980: }
! 981:
! 982: /*
! 983: * Called from HPMC handler in locore
! 984: */
! 985: void
! 986: hpmc_dump(void)
! 987: {
! 988: printf("HPMC\n");
! 989:
! 990: cold = 0;
! 991: boot(RB_NOSYNC);
! 992: }
! 993:
! 994: int
! 995: cpu_dump(void)
! 996: {
! 997: long buf[dbtob(1) / sizeof (long)];
! 998: kcore_seg_t *segp;
! 999: cpu_kcore_hdr_t *cpuhdrp;
! 1000:
! 1001: segp = (kcore_seg_t *)buf;
! 1002: cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)];
! 1003:
! 1004: /*
! 1005: * Generate a segment header.
! 1006: */
! 1007: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 1008: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
! 1009:
! 1010: /*
! 1011: * Add the machine-dependent header info
! 1012: */
! 1013: /* nothing for now */
! 1014:
! 1015: return (bdevsw[major(dumpdev)].d_dump)
! 1016: (dumpdev, dumplo, (caddr_t)buf, dbtob(1));
! 1017: }
! 1018:
! 1019: /*
! 1020: * Dump the kernel's image to the swap partition.
! 1021: */
! 1022: #define BYTES_PER_DUMP NBPG
! 1023:
! 1024: void
! 1025: dumpsys(void)
! 1026: {
! 1027: int psize, bytes, i, n;
! 1028: caddr_t maddr;
! 1029: daddr64_t blkno;
! 1030: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 1031: int error;
! 1032:
! 1033: /* Save registers
! 1034: savectx(&dumppcb); */
! 1035:
! 1036: if (dumpsize == 0)
! 1037: dumpconf();
! 1038: if (dumplo <= 0) {
! 1039: printf("\ndump to dev %x not possible\n", dumpdev);
! 1040: return;
! 1041: }
! 1042: printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
! 1043:
! 1044: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
! 1045: printf("dump ");
! 1046: if (psize == -1) {
! 1047: printf("area unavailable\n");
! 1048: return;
! 1049: }
! 1050:
! 1051: if (!(error = cpu_dump())) {
! 1052:
! 1053: bytes = ctob(physmem);
! 1054: maddr = NULL;
! 1055: blkno = dumplo + cpu_dumpsize();
! 1056: dump = bdevsw[major(dumpdev)].d_dump;
! 1057: /* TODO block map the whole physical memory */
! 1058: for (i = 0; i < bytes; i += n) {
! 1059:
! 1060: /* Print out how many MBs we are to go. */
! 1061: n = bytes - i;
! 1062: if (n && (n % (1024*1024)) == 0)
! 1063: printf("%d ", n / (1024 * 1024));
! 1064:
! 1065: /* Limit size for next transfer. */
! 1066:
! 1067: if (n > BYTES_PER_DUMP)
! 1068: n = BYTES_PER_DUMP;
! 1069:
! 1070: if ((error = (*dump)(dumpdev, blkno, maddr, n)))
! 1071: break;
! 1072: maddr += n;
! 1073: blkno += btodb(n);
! 1074: }
! 1075: }
! 1076:
! 1077: switch (error) {
! 1078: case ENXIO: printf("device bad\n"); break;
! 1079: case EFAULT: printf("device not ready\n"); break;
! 1080: case EINVAL: printf("area improper\n"); break;
! 1081: case EIO: printf("i/o error\n"); break;
! 1082: case EINTR: printf("aborted from console\n"); break;
! 1083: case 0: printf("succeeded\n"); break;
! 1084: default: printf("error %d\n", error); break;
! 1085: }
! 1086: }
! 1087:
! 1088: /* bcopy(), error on fault */
! 1089: int
! 1090: kcopy(from, to, size)
! 1091: const void *from;
! 1092: void *to;
! 1093: size_t size;
! 1094: {
! 1095: return spcopy(HPPA_SID_KERNEL, from, HPPA_SID_KERNEL, to, size);
! 1096: }
! 1097:
! 1098: int
! 1099: copystr(src, dst, size, lenp)
! 1100: const void *src;
! 1101: void *dst;
! 1102: size_t size;
! 1103: size_t *lenp;
! 1104: {
! 1105: return spstrcpy(HPPA_SID_KERNEL, src, HPPA_SID_KERNEL, dst, size, lenp);
! 1106: }
! 1107:
! 1108: int
! 1109: copyinstr(src, dst, size, lenp)
! 1110: const void *src;
! 1111: void *dst;
! 1112: size_t size;
! 1113: size_t *lenp;
! 1114: {
! 1115: return spstrcpy(curproc->p_addr->u_pcb.pcb_space, src,
! 1116: HPPA_SID_KERNEL, dst, size, lenp);
! 1117: }
! 1118:
! 1119:
! 1120: int
! 1121: copyoutstr(src, dst, size, lenp)
! 1122: const void *src;
! 1123: void *dst;
! 1124: size_t size;
! 1125: size_t *lenp;
! 1126: {
! 1127: return spstrcpy(HPPA_SID_KERNEL, src,
! 1128: curproc->p_addr->u_pcb.pcb_space, dst, size, lenp);
! 1129: }
! 1130:
! 1131:
! 1132: int
! 1133: copyin(src, dst, size)
! 1134: const void *src;
! 1135: void *dst;
! 1136: size_t size;
! 1137: {
! 1138: return spcopy(curproc->p_addr->u_pcb.pcb_space, src,
! 1139: HPPA_SID_KERNEL, dst, size);
! 1140: }
! 1141:
! 1142: int
! 1143: copyout(src, dst, size)
! 1144: const void *src;
! 1145: void *dst;
! 1146: size_t size;
! 1147: {
! 1148: return spcopy(HPPA_SID_KERNEL, src,
! 1149: curproc->p_addr->u_pcb.pcb_space, dst, size);
! 1150: }
! 1151:
! 1152: /*
! 1153: * Set registers on exec.
! 1154: */
! 1155: void
! 1156: setregs(p, pack, stack, retval)
! 1157: struct proc *p;
! 1158: struct exec_package *pack;
! 1159: u_long stack;
! 1160: register_t *retval;
! 1161: {
! 1162: extern paddr_t fpu_curpcb; /* from locore.S */
! 1163: struct trapframe *tf = p->p_md.md_regs;
! 1164: struct pcb *pcb = &p->p_addr->u_pcb;
! 1165: register_t zero;
! 1166:
! 1167: tf->tf_flags = TFF_SYS|TFF_LAST;
! 1168: tf->tf_iioq_tail = 4 +
! 1169: (tf->tf_iioq_head = pack->ep_entry | HPPA_PC_PRIV_USER);
! 1170: tf->tf_rp = 0;
! 1171: tf->tf_arg0 = (u_long)PS_STRINGS;
! 1172: tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */
! 1173:
! 1174: /* setup terminal stack frame */
! 1175: stack = (stack + 0x1f) & ~0x1f;
! 1176: tf->tf_r3 = stack;
! 1177: tf->tf_sp = stack += HPPA_FRAME_SIZE;
! 1178: zero = 0;
! 1179: copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t));
! 1180: copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), sizeof(register_t));
! 1181:
! 1182: /* reset any of the pending FPU exceptions */
! 1183: if (tf->tf_cr30 == fpu_curpcb) {
! 1184: fpu_exit();
! 1185: fpu_curpcb = 0;
! 1186: }
! 1187: pcb->pcb_fpregs[0] = ((u_int64_t)HPPA_FPU_INIT) << 32;
! 1188: pcb->pcb_fpregs[1] = 0;
! 1189: pcb->pcb_fpregs[2] = 0;
! 1190: pcb->pcb_fpregs[3] = 0;
! 1191: fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4);
! 1192:
! 1193: retval[1] = 0;
! 1194: }
! 1195:
! 1196: /*
! 1197: * Send an interrupt to process.
! 1198: */
! 1199: void
! 1200: sendsig(catcher, sig, mask, code, type, val)
! 1201: sig_t catcher;
! 1202: int sig, mask;
! 1203: u_long code;
! 1204: int type;
! 1205: union sigval val;
! 1206: {
! 1207: extern paddr_t fpu_curpcb; /* from locore.S */
! 1208: extern u_int fpu_enable;
! 1209: struct proc *p = curproc;
! 1210: struct trapframe *tf = p->p_md.md_regs;
! 1211: struct pcb *pcb = &p->p_addr->u_pcb;
! 1212: struct sigacts *psp = p->p_sigacts;
! 1213: struct sigcontext ksc;
! 1214: siginfo_t ksi;
! 1215: register_t scp, sip;
! 1216: int sss;
! 1217:
! 1218: #ifdef DEBUG
! 1219: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1220: printf("sendsig: %s[%d] sig %d catcher %p\n",
! 1221: p->p_comm, p->p_pid, sig, catcher);
! 1222: #endif
! 1223:
! 1224: /* flush the FPU ctx first */
! 1225: if (tf->tf_cr30 == fpu_curpcb) {
! 1226: mtctl(fpu_enable, CR_CCR);
! 1227: fpu_save(fpu_curpcb);
! 1228: /* fpu_curpcb = 0; only needed if fpregs are preset */
! 1229: mtctl(0, CR_CCR);
! 1230: }
! 1231:
! 1232: ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 1233:
! 1234: /*
! 1235: * Allocate space for the signal handler context.
! 1236: */
! 1237: if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
! 1238: (psp->ps_sigonstack & sigmask(sig))) {
! 1239: scp = (register_t)psp->ps_sigstk.ss_sp;
! 1240: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1241: } else
! 1242: scp = (tf->tf_sp + 63) & ~63;
! 1243:
! 1244: sss = (sizeof(ksc) + 63) & ~63;
! 1245: sip = 0;
! 1246: if (psp->ps_siginfo & sigmask(sig)) {
! 1247: sip = scp + sizeof(ksc);
! 1248: sss += (sizeof(ksi) + 63) & ~63;
! 1249: }
! 1250:
! 1251: #ifdef DEBUG
! 1252: if ((tf->tf_iioq_head & ~PAGE_MASK) == SYSCALLGATE)
! 1253: printf("sendsig: interrupted syscall at 0x%x:0x%x flags %b\n",
! 1254: tf->tf_iioq_head, tf->tf_iioq_tail, tf->tf_ipsw, PSL_BITS);
! 1255: #endif
! 1256:
! 1257: ksc.sc_mask = mask;
! 1258: ksc.sc_fp = scp + sss;
! 1259: ksc.sc_ps = tf->tf_ipsw;
! 1260: ksc.sc_pcoqh = tf->tf_iioq_head;
! 1261: ksc.sc_pcoqt = tf->tf_iioq_tail;
! 1262: ksc.sc_regs[0] = tf->tf_t1;
! 1263: ksc.sc_regs[1] = tf->tf_t2;
! 1264: ksc.sc_regs[2] = tf->tf_sp;
! 1265: ksc.sc_regs[3] = tf->tf_t3;
! 1266: ksc.sc_regs[4] = tf->tf_sar;
! 1267: ksc.sc_regs[5] = tf->tf_r1;
! 1268: ksc.sc_regs[6] = tf->tf_rp;
! 1269: ksc.sc_regs[7] = tf->tf_r3;
! 1270: ksc.sc_regs[8] = tf->tf_r4;
! 1271: ksc.sc_regs[9] = tf->tf_r5;
! 1272: ksc.sc_regs[10] = tf->tf_r6;
! 1273: ksc.sc_regs[11] = tf->tf_r7;
! 1274: ksc.sc_regs[12] = tf->tf_r8;
! 1275: ksc.sc_regs[13] = tf->tf_r9;
! 1276: ksc.sc_regs[14] = tf->tf_r10;
! 1277: ksc.sc_regs[15] = tf->tf_r11;
! 1278: ksc.sc_regs[16] = tf->tf_r12;
! 1279: ksc.sc_regs[17] = tf->tf_r13;
! 1280: ksc.sc_regs[18] = tf->tf_r14;
! 1281: ksc.sc_regs[19] = tf->tf_r15;
! 1282: ksc.sc_regs[20] = tf->tf_r16;
! 1283: ksc.sc_regs[21] = tf->tf_r17;
! 1284: ksc.sc_regs[22] = tf->tf_r18;
! 1285: ksc.sc_regs[23] = tf->tf_t4;
! 1286: ksc.sc_regs[24] = tf->tf_arg3;
! 1287: ksc.sc_regs[25] = tf->tf_arg2;
! 1288: ksc.sc_regs[26] = tf->tf_arg1;
! 1289: ksc.sc_regs[27] = tf->tf_arg0;
! 1290: ksc.sc_regs[28] = tf->tf_dp;
! 1291: ksc.sc_regs[29] = tf->tf_ret0;
! 1292: ksc.sc_regs[30] = tf->tf_ret1;
! 1293: ksc.sc_regs[31] = tf->tf_r31;
! 1294: bcopy(p->p_addr->u_pcb.pcb_fpregs, ksc.sc_fpregs,
! 1295: sizeof(ksc.sc_fpregs));
! 1296:
! 1297: sss += HPPA_FRAME_SIZE;
! 1298: tf->tf_arg0 = sig;
! 1299: tf->tf_arg1 = sip;
! 1300: tf->tf_arg2 = tf->tf_r4 = scp;
! 1301: tf->tf_arg3 = (register_t)catcher;
! 1302: tf->tf_sp = scp + sss;
! 1303: tf->tf_ipsw &= ~(PSL_N|PSL_B);
! 1304: tf->tf_iioq_head = HPPA_PC_PRIV_USER | p->p_sigcode;
! 1305: tf->tf_iioq_tail = tf->tf_iioq_head + 4;
! 1306: tf->tf_iisq_tail = tf->tf_iisq_head = pcb->pcb_space;
! 1307: /* disable tracing in the trapframe */
! 1308:
! 1309: #ifdef DEBUG
! 1310: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1311: printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n",
! 1312: p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss);
! 1313: #endif
! 1314:
! 1315: if (copyout(&ksc, (void *)scp, sizeof(ksc)))
! 1316: sigexit(p, SIGILL);
! 1317:
! 1318: if (sip) {
! 1319: initsiginfo(&ksi, sig, code, type, val);
! 1320: if (copyout(&ksi, (void *)sip, sizeof(ksi)))
! 1321: sigexit(p, SIGILL);
! 1322: }
! 1323:
! 1324: if (copyout(&tf->tf_r3, (caddr_t)(tf->tf_sp - HPPA_FRAME_SIZE),
! 1325: sizeof(register_t)))
! 1326: sigexit(p, SIGILL);
! 1327: tf->tf_r3 = tf->tf_sp - HPPA_FRAME_SIZE;
! 1328:
! 1329: #ifdef DEBUG
! 1330: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1331: printf("sendsig(%d): pc 0x%x catcher 0x%x\n", p->p_pid,
! 1332: tf->tf_iioq_head, tf->tf_arg3);
! 1333: #endif
! 1334: }
! 1335:
! 1336: int
! 1337: sys_sigreturn(p, v, retval)
! 1338: struct proc *p;
! 1339: void *v;
! 1340: register_t *retval;
! 1341: {
! 1342: extern paddr_t fpu_curpcb; /* from locore.S */
! 1343: struct sys_sigreturn_args /* {
! 1344: syscallarg(struct sigcontext *) sigcntxp;
! 1345: } */ *uap = v;
! 1346: struct sigcontext *scp, ksc;
! 1347: struct trapframe *tf = p->p_md.md_regs;
! 1348: int error;
! 1349:
! 1350: scp = SCARG(uap, sigcntxp);
! 1351: #ifdef DEBUG
! 1352: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1353: printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
! 1354: #endif
! 1355:
! 1356: /* flush the FPU ctx first */
! 1357: if (tf->tf_cr30 == fpu_curpcb) {
! 1358: fpu_exit();
! 1359: fpu_curpcb = 0;
! 1360: }
! 1361:
! 1362: if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)))
! 1363: return (error);
! 1364:
! 1365: #define PSL_MBS (PSL_C|PSL_Q|PSL_P|PSL_D|PSL_I)
! 1366: #define PSL_MBZ (PSL_Y|PSL_Z|PSL_S|PSL_X|PSL_M|PSL_R)
! 1367: if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS)
! 1368: return (EINVAL);
! 1369:
! 1370: if (ksc.sc_onstack)
! 1371: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1372: else
! 1373: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 1374: p->p_sigmask = ksc.sc_mask &~ sigcantmask;
! 1375:
! 1376: tf->tf_t1 = ksc.sc_regs[0]; /* r22 */
! 1377: tf->tf_t2 = ksc.sc_regs[1]; /* r21 */
! 1378: tf->tf_sp = ksc.sc_regs[2];
! 1379: tf->tf_t3 = ksc.sc_regs[3]; /* r20 */
! 1380: tf->tf_sar = ksc.sc_regs[4];
! 1381: tf->tf_r1 = ksc.sc_regs[5];
! 1382: tf->tf_rp = ksc.sc_regs[6];
! 1383: tf->tf_r3 = ksc.sc_regs[7];
! 1384: tf->tf_r4 = ksc.sc_regs[8];
! 1385: tf->tf_r5 = ksc.sc_regs[9];
! 1386: tf->tf_r6 = ksc.sc_regs[10];
! 1387: tf->tf_r7 = ksc.sc_regs[11];
! 1388: tf->tf_r8 = ksc.sc_regs[12];
! 1389: tf->tf_r9 = ksc.sc_regs[13];
! 1390: tf->tf_r10 = ksc.sc_regs[14];
! 1391: tf->tf_r11 = ksc.sc_regs[15];
! 1392: tf->tf_r12 = ksc.sc_regs[16];
! 1393: tf->tf_r13 = ksc.sc_regs[17];
! 1394: tf->tf_r14 = ksc.sc_regs[18];
! 1395: tf->tf_r15 = ksc.sc_regs[19];
! 1396: tf->tf_r16 = ksc.sc_regs[20];
! 1397: tf->tf_r17 = ksc.sc_regs[21];
! 1398: tf->tf_r18 = ksc.sc_regs[22];
! 1399: tf->tf_t4 = ksc.sc_regs[23]; /* r19 */
! 1400: tf->tf_arg3 = ksc.sc_regs[24]; /* r23 */
! 1401: tf->tf_arg2 = ksc.sc_regs[25]; /* r24 */
! 1402: tf->tf_arg1 = ksc.sc_regs[26]; /* r25 */
! 1403: tf->tf_arg0 = ksc.sc_regs[27]; /* r26 */
! 1404: tf->tf_dp = ksc.sc_regs[28];
! 1405: tf->tf_ret0 = ksc.sc_regs[29];
! 1406: tf->tf_ret1 = ksc.sc_regs[30];
! 1407: tf->tf_r31 = ksc.sc_regs[31];
! 1408: bcopy(ksc.sc_fpregs, p->p_addr->u_pcb.pcb_fpregs,
! 1409: sizeof(ksc.sc_fpregs));
! 1410: fdcache(HPPA_SID_KERNEL, (vaddr_t)p->p_addr->u_pcb.pcb_fpregs,
! 1411: sizeof(ksc.sc_fpregs));
! 1412:
! 1413: tf->tf_iioq_head = ksc.sc_pcoqh | HPPA_PC_PRIV_USER;
! 1414: tf->tf_iioq_tail = ksc.sc_pcoqt | HPPA_PC_PRIV_USER;
! 1415: if ((tf->tf_iioq_head & ~PAGE_MASK) == SYSCALLGATE)
! 1416: tf->tf_iisq_head = HPPA_SID_KERNEL;
! 1417: else
! 1418: tf->tf_iisq_head = p->p_addr->u_pcb.pcb_space;
! 1419: if ((tf->tf_iioq_tail & ~PAGE_MASK) == SYSCALLGATE)
! 1420: tf->tf_iisq_tail = HPPA_SID_KERNEL;
! 1421: else
! 1422: tf->tf_iisq_tail = p->p_addr->u_pcb.pcb_space;
! 1423: tf->tf_ipsw = ksc.sc_ps;
! 1424:
! 1425: #ifdef DEBUG
! 1426: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1427: printf("sigreturn(%d): returns\n", p->p_pid);
! 1428: #endif
! 1429: return (EJUSTRETURN);
! 1430: }
! 1431:
! 1432: #ifdef COMPAT_HPUX
! 1433: void
! 1434: hpux_sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
! 1435: union sigval val)
! 1436: {
! 1437: extern paddr_t fpu_curpcb; /* from locore.S */
! 1438: extern u_int fpu_enable;
! 1439: struct proc *p = curproc;
! 1440: struct pcb *pcb = &p->p_addr->u_pcb;
! 1441: struct trapframe *tf = p->p_md.md_regs;
! 1442: struct sigacts *psp = p->p_sigacts;
! 1443: struct hpux_sigcontext hsc;
! 1444: int sss;
! 1445: register_t scp;
! 1446:
! 1447: #ifdef DEBUG
! 1448: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1449: printf("hpux_sendsig: %s[%d] sig %d catcher %p\n",
! 1450: p->p_comm, p->p_pid, sig, catcher);
! 1451: #endif
! 1452: /* flush the FPU ctx first */
! 1453: if (tf->tf_cr30 == fpu_curpcb) {
! 1454: mtctl(fpu_enable, CR_CCR);
! 1455: fpu_save(fpu_curpcb);
! 1456: fpu_curpcb = 0;
! 1457: mtctl(0, CR_CCR);
! 1458: }
! 1459:
! 1460: bzero(&hsc, sizeof hsc);
! 1461: hsc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 1462: hsc.sc_omask = mask;
! 1463: /* sc_scact ??? */
! 1464:
! 1465: hsc.sc_ret0 = tf->tf_ret0;
! 1466: hsc.sc_ret1 = tf->tf_ret1;
! 1467:
! 1468: hsc.sc_frame[0] = hsc.sc_args[0] = sig;
! 1469: hsc.sc_frame[1] = hsc.sc_args[1] = NULL;
! 1470: hsc.sc_frame[2] = hsc.sc_args[2] = scp;
! 1471:
! 1472: /*
! 1473: * Allocate space for the signal handler context.
! 1474: */
! 1475: if ((psp->ps_flags & SAS_ALTSTACK) && !hsc.sc_onstack &&
! 1476: (psp->ps_sigonstack & sigmask(sig))) {
! 1477: scp = (register_t)psp->ps_sigstk.ss_sp;
! 1478: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1479: } else
! 1480: scp = (tf->tf_sp + 63) & ~63;
! 1481:
! 1482: sss = (sizeof(hsc) + 63) & ~63;
! 1483:
! 1484: if (tf->tf_flags & TFF_SYS) {
! 1485: hsc.sc_tfflags = HPUX_TFF_SYSCALL;
! 1486: hsc.sc_syscall = tf->tf_t1;
! 1487: } else if (tf->tf_flags & TFF_INTR)
! 1488: hsc.sc_tfflags = HPUX_TFF_INTR;
! 1489: else
! 1490: hsc.sc_tfflags = HPUX_TFF_TRAP;
! 1491:
! 1492: hsc.sc_regs[0] = tf->tf_r1;
! 1493: hsc.sc_regs[1] = tf->tf_rp;
! 1494: hsc.sc_regs[2] = tf->tf_r3;
! 1495: hsc.sc_regs[3] = tf->tf_r4;
! 1496: hsc.sc_regs[4] = tf->tf_r5;
! 1497: hsc.sc_regs[5] = tf->tf_r6;
! 1498: hsc.sc_regs[6] = tf->tf_r7;
! 1499: hsc.sc_regs[7] = tf->tf_r8;
! 1500: hsc.sc_regs[8] = tf->tf_r9;
! 1501: hsc.sc_regs[9] = tf->tf_r10;
! 1502: hsc.sc_regs[10] = tf->tf_r11;
! 1503: hsc.sc_regs[11] = tf->tf_r12;
! 1504: hsc.sc_regs[12] = tf->tf_r13;
! 1505: hsc.sc_regs[13] = tf->tf_r14;
! 1506: hsc.sc_regs[14] = tf->tf_r15;
! 1507: hsc.sc_regs[15] = tf->tf_r16;
! 1508: hsc.sc_regs[16] = tf->tf_r17;
! 1509: hsc.sc_regs[17] = tf->tf_r18;
! 1510: hsc.sc_regs[18] = tf->tf_t4;
! 1511: hsc.sc_regs[19] = tf->tf_t3;
! 1512: hsc.sc_regs[20] = tf->tf_t2;
! 1513: hsc.sc_regs[21] = tf->tf_t1;
! 1514: hsc.sc_regs[22] = tf->tf_arg3;
! 1515: hsc.sc_regs[23] = tf->tf_arg2;
! 1516: hsc.sc_regs[24] = tf->tf_arg1;
! 1517: hsc.sc_regs[25] = tf->tf_arg0;
! 1518: hsc.sc_regs[26] = tf->tf_dp;
! 1519: hsc.sc_regs[27] = tf->tf_ret0;
! 1520: hsc.sc_regs[28] = tf->tf_ret1;
! 1521: hsc.sc_regs[29] = tf->tf_sp;
! 1522: hsc.sc_regs[30] = tf->tf_r31;
! 1523: hsc.sc_regs[31] = tf->tf_sar;
! 1524: hsc.sc_regs[32] = tf->tf_iioq_head;
! 1525: hsc.sc_regs[33] = tf->tf_iisq_head;
! 1526: hsc.sc_regs[34] = tf->tf_iioq_tail;
! 1527: hsc.sc_regs[35] = tf->tf_iisq_tail;
! 1528: hsc.sc_regs[35] = tf->tf_eiem;
! 1529: hsc.sc_regs[36] = tf->tf_iir;
! 1530: hsc.sc_regs[37] = tf->tf_isr;
! 1531: hsc.sc_regs[38] = tf->tf_ior;
! 1532: hsc.sc_regs[39] = tf->tf_ipsw;
! 1533: hsc.sc_regs[40] = 0;
! 1534: hsc.sc_regs[41] = tf->tf_sr4;
! 1535: hsc.sc_regs[42] = tf->tf_sr0;
! 1536: hsc.sc_regs[43] = tf->tf_sr1;
! 1537: hsc.sc_regs[44] = tf->tf_sr2;
! 1538: hsc.sc_regs[45] = tf->tf_sr3;
! 1539: hsc.sc_regs[46] = tf->tf_sr5;
! 1540: hsc.sc_regs[47] = tf->tf_sr6;
! 1541: hsc.sc_regs[48] = tf->tf_sr7;
! 1542: hsc.sc_regs[49] = tf->tf_rctr;
! 1543: hsc.sc_regs[50] = tf->tf_pidr1;
! 1544: hsc.sc_regs[51] = tf->tf_pidr2;
! 1545: hsc.sc_regs[52] = tf->tf_ccr;
! 1546: hsc.sc_regs[53] = tf->tf_pidr3;
! 1547: hsc.sc_regs[54] = tf->tf_pidr4;
! 1548: /* hsc.sc_regs[55] = tf->tf_cr24; */
! 1549: hsc.sc_regs[56] = tf->tf_vtop;
! 1550: /* hsc.sc_regs[57] = tf->tf_cr26; */
! 1551: /* hsc.sc_regs[58] = tf->tf_cr27; */
! 1552: hsc.sc_regs[59] = 0;
! 1553: hsc.sc_regs[60] = 0;
! 1554: bcopy(p->p_addr->u_pcb.pcb_fpregs, hsc.sc_fpregs,
! 1555: sizeof(hsc.sc_fpregs));
! 1556:
! 1557: tf->tf_rp = (register_t)pcb->pcb_sigreturn;
! 1558: tf->tf_arg3 = (register_t)catcher;
! 1559: tf->tf_sp = scp + sss;
! 1560: tf->tf_ipsw &= ~(PSL_N|PSL_B);
! 1561: tf->tf_iioq_head = HPPA_PC_PRIV_USER | p->p_sigcode;
! 1562: tf->tf_iioq_tail = tf->tf_iioq_head + 4;
! 1563:
! 1564: if (copyout(&hsc, (void *)scp, sizeof(hsc)))
! 1565: sigexit(p, SIGILL);
! 1566:
! 1567: #ifdef DEBUG
! 1568: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
! 1569: printf("sendsig(%d): pc 0x%x rp 0x%x\n", p->p_pid,
! 1570: tf->tf_iioq_head, tf->tf_rp);
! 1571: #endif
! 1572: }
! 1573: #endif
! 1574:
! 1575: /*
! 1576: * machine dependent system variables.
! 1577: */
! 1578: int
! 1579: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 1580: int *name;
! 1581: u_int namelen;
! 1582: void *oldp;
! 1583: size_t *oldlenp;
! 1584: void *newp;
! 1585: size_t newlen;
! 1586: struct proc *p;
! 1587: {
! 1588: extern paddr_t fpu_curpcb; /* from locore.S */
! 1589: extern u_int fpu_enable;
! 1590: extern int cpu_fpuena;
! 1591: dev_t consdev;
! 1592: int oldval, ret;
! 1593:
! 1594: /* all sysctl names at this level are terminal */
! 1595: if (namelen != 1)
! 1596: return (ENOTDIR); /* overloaded */
! 1597: switch (name[0]) {
! 1598: case CPU_CONSDEV:
! 1599: if (cn_tab != NULL)
! 1600: consdev = cn_tab->cn_dev;
! 1601: else
! 1602: consdev = NODEV;
! 1603: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 1604: sizeof consdev));
! 1605: case CPU_FPU:
! 1606: if (fpu_curpcb) {
! 1607: mtctl(fpu_enable, CR_CCR);
! 1608: fpu_save(fpu_curpcb);
! 1609: fpu_curpcb = 0;
! 1610: mtctl(0, CR_CCR);
! 1611: }
! 1612: return (sysctl_int(oldp, oldlenp, newp, newlen, &cpu_fpuena));
! 1613: case CPU_LED_BLINK:
! 1614: oldval = led_blink;
! 1615: ret = sysctl_int(oldp, oldlenp, newp, newlen, &led_blink);
! 1616: /*
! 1617: * If we were false and are now true, start the timer.
! 1618: */
! 1619: if (!oldval && led_blink > oldval)
! 1620: blink_led_timeout(NULL);
! 1621: return (ret);
! 1622: default:
! 1623: return (EOPNOTSUPP);
! 1624: }
! 1625: /* NOTREACHED */
! 1626: }
! 1627:
! 1628:
! 1629: /*
! 1630: * consinit:
! 1631: * initialize the system console.
! 1632: */
! 1633: void
! 1634: consinit(void)
! 1635: {
! 1636: /*
! 1637: * Initial console setup has been done in pdc_init().
! 1638: */
! 1639: }
! 1640:
! 1641:
! 1642: struct blink_led_softc {
! 1643: SLIST_HEAD(, blink_led) bls_head;
! 1644: int bls_on;
! 1645: struct timeout bls_to;
! 1646: } blink_sc = { SLIST_HEAD_INITIALIZER(bls_head), 0 };
! 1647:
! 1648: void
! 1649: blink_led_register(struct blink_led *l)
! 1650: {
! 1651: if (SLIST_EMPTY(&blink_sc.bls_head)) {
! 1652: timeout_set(&blink_sc.bls_to, blink_led_timeout, &blink_sc);
! 1653: blink_sc.bls_on = 0;
! 1654: if (led_blink)
! 1655: timeout_add(&blink_sc.bls_to, 1);
! 1656: }
! 1657: SLIST_INSERT_HEAD(&blink_sc.bls_head, l, bl_next);
! 1658: }
! 1659:
! 1660: void
! 1661: blink_led_timeout(void *vsc)
! 1662: {
! 1663: struct blink_led_softc *sc = &blink_sc;
! 1664: struct blink_led *l;
! 1665: int t;
! 1666:
! 1667: if (SLIST_EMPTY(&sc->bls_head))
! 1668: return;
! 1669:
! 1670: SLIST_FOREACH(l, &sc->bls_head, bl_next) {
! 1671: (*l->bl_func)(l->bl_arg, sc->bls_on);
! 1672: }
! 1673: sc->bls_on = !sc->bls_on;
! 1674:
! 1675: if (!led_blink)
! 1676: return;
! 1677:
! 1678: /*
! 1679: * Blink rate is:
! 1680: * full cycle every second if completely idle (loadav = 0)
! 1681: * full cycle every 2 seconds if loadav = 1
! 1682: * full cycle every 3 seconds if loadav = 2
! 1683: * etc.
! 1684: */
! 1685: t = (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1));
! 1686: timeout_add(&sc->bls_to, t);
! 1687: }
CVSweb