Annotation of sys/arch/alpha/alpha/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.110 2007/06/06 17:15:11 deraadt Exp $ */
! 2: /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
! 10: * NASA Ames Research Center and by Chris G. Demetriou.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the NetBSD
! 23: * Foundation, Inc. and its contributors.
! 24: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 25: * contributors may be used to endorse or promote products derived
! 26: * from this software without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 38: * POSSIBILITY OF SUCH DAMAGE.
! 39: */
! 40:
! 41: /*
! 42: * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
! 43: * All rights reserved.
! 44: *
! 45: * Author: Chris G. Demetriou
! 46: *
! 47: * Permission to use, copy, modify and distribute this software and
! 48: * its documentation is hereby granted, provided that both the copyright
! 49: * notice and this permission notice appear in all copies of the
! 50: * software, derivative works or modified versions, and any portions
! 51: * thereof, and that both notices appear in supporting documentation.
! 52: *
! 53: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 54: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 55: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 56: *
! 57: * Carnegie Mellon requests users of this software to return to
! 58: *
! 59: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 60: * School of Computer Science
! 61: * Carnegie Mellon University
! 62: * Pittsburgh PA 15213-3890
! 63: *
! 64: * any improvements or extensions that they make and grant Carnegie the
! 65: * rights to redistribute these changes.
! 66: */
! 67:
! 68: #include <sys/param.h>
! 69: #include <sys/systm.h>
! 70: #include <sys/signalvar.h>
! 71: #include <sys/kernel.h>
! 72: #include <sys/proc.h>
! 73: #include <sys/sched.h>
! 74: #include <sys/buf.h>
! 75: #include <sys/reboot.h>
! 76: #include <sys/device.h>
! 77: #include <sys/conf.h>
! 78: #include <sys/file.h>
! 79: #include <sys/timeout.h>
! 80: #include <sys/malloc.h>
! 81: #include <sys/mbuf.h>
! 82: #include <sys/msgbuf.h>
! 83: #include <sys/ioctl.h>
! 84: #include <sys/tty.h>
! 85: #include <sys/user.h>
! 86: #include <sys/exec.h>
! 87: #include <sys/exec_ecoff.h>
! 88: #include <uvm/uvm_extern.h>
! 89: #include <sys/sysctl.h>
! 90: #include <sys/core.h>
! 91: #include <sys/kcore.h>
! 92: #include <machine/kcore.h>
! 93: #ifndef NO_IEEE
! 94: #include <machine/fpu.h>
! 95: #endif
! 96: #ifdef SYSVMSG
! 97: #include <sys/msg.h>
! 98: #endif
! 99: #include <sys/timetc.h>
! 100:
! 101: #include <sys/mount.h>
! 102: #include <sys/syscallargs.h>
! 103:
! 104: #include <dev/cons.h>
! 105:
! 106: #include <machine/autoconf.h>
! 107: #include <machine/cpu.h>
! 108: #include <machine/reg.h>
! 109: #include <machine/rpb.h>
! 110: #include <machine/prom.h>
! 111: #include <machine/cpuconf.h>
! 112: #ifndef NO_IEEE
! 113: #include <machine/ieeefp.h>
! 114: #endif
! 115:
! 116: #include <dev/pci/pcivar.h>
! 117:
! 118: #ifdef DDB
! 119: #include <machine/db_machdep.h>
! 120: #include <ddb/db_access.h>
! 121: #include <ddb/db_sym.h>
! 122: #include <ddb/db_extern.h>
! 123: #endif
! 124:
! 125: int cpu_dump(void);
! 126: int cpu_dumpsize(void);
! 127: u_long cpu_dump_mempagecnt(void);
! 128: void dumpsys(void);
! 129: caddr_t allocsys(caddr_t);
! 130: void identifycpu(void);
! 131: void regdump(struct trapframe *framep);
! 132: void printregs(struct reg *);
! 133:
! 134: /*
! 135: * Declare these as initialized data so we can patch them.
! 136: */
! 137: #ifndef BUFCACHEPERCENT
! 138: #define BUFCACHEPERCENT 10
! 139: #endif
! 140:
! 141: #ifdef BUFPAGES
! 142: int bufpages = BUFPAGES;
! 143: #else
! 144: int bufpages = 0;
! 145: #endif
! 146: int bufcachepercent = BUFCACHEPERCENT;
! 147:
! 148: struct vm_map *exec_map = NULL;
! 149: struct vm_map *phys_map = NULL;
! 150:
! 151: #ifdef APERTURE
! 152: #ifdef INSECURE
! 153: int allowaperture = 1;
! 154: #else
! 155: int allowaperture = 0;
! 156: #endif
! 157: #endif
! 158:
! 159: int totalphysmem; /* total amount of physical memory in system */
! 160: int physmem; /* physical mem used by OpenBSD + some rsvd */
! 161: int resvmem; /* amount of memory reserved for PROM */
! 162: int unusedmem; /* amount of memory for OS that we don't use */
! 163: int unknownmem; /* amount of memory with an unknown use */
! 164:
! 165: int cputype; /* system type, from the RPB */
! 166: int alpha_cpus;
! 167:
! 168: int bootdev_debug = 0; /* patchable, or from DDB */
! 169:
! 170: /* the following is used externally (sysctl_hw) */
! 171: char machine[] = MACHINE; /* from <machine/param.h> */
! 172: char cpu_model[128];
! 173: char root_device[17];
! 174:
! 175: struct user *proc0paddr;
! 176:
! 177: /* Number of machine cycles per microsecond */
! 178: u_int64_t cycles_per_usec;
! 179:
! 180: struct bootinfo_kernel bootinfo;
! 181:
! 182: /* For built-in TCDS */
! 183: #if defined(DEC_3000_300) || defined(DEC_3000_500)
! 184: u_int8_t dec_3000_scsiid[2], dec_3000_scsifast[2];
! 185: #endif
! 186:
! 187: struct platform platform;
! 188:
! 189: /* for cpu_sysctl() */
! 190: int alpha_unaligned_print = 1; /* warn about unaligned accesses */
! 191: int alpha_unaligned_fix = 1; /* fix up unaligned accesses */
! 192: int alpha_unaligned_sigbus = 1; /* SIGBUS on fixed-up accesses */
! 193: #ifndef NO_IEEE
! 194: int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */
! 195: #endif
! 196:
! 197: /* used by hw_sysctl */
! 198: extern char *hw_serial;
! 199:
! 200: /*
! 201: * XXX This should be dynamically sized, but we have the chicken-egg problem!
! 202: * XXX it should also be larger than it is, because not all of the mddt
! 203: * XXX clusters end up being used for VM.
! 204: */
! 205: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; /* low size bits overloaded */
! 206: int mem_cluster_cnt;
! 207:
! 208: void
! 209: alpha_init(pfn, ptb, bim, bip, biv)
! 210: u_long pfn; /* first free PFN number */
! 211: u_long ptb; /* PFN of current level 1 page table */
! 212: u_long bim; /* bootinfo magic */
! 213: u_long bip; /* bootinfo pointer */
! 214: u_long biv; /* bootinfo version */
! 215: {
! 216: extern char kernel_text[], _end[];
! 217: struct mddt *mddtp;
! 218: struct mddt_cluster *memc;
! 219: int i, mddtweird;
! 220: struct vm_physseg *vps;
! 221: vaddr_t kernstart, kernend;
! 222: paddr_t kernstartpfn, kernendpfn, pfn0, pfn1;
! 223: vsize_t size;
! 224: char *p;
! 225: caddr_t v;
! 226: const char *bootinfo_msg;
! 227: const struct cpuinit *c;
! 228: extern caddr_t esym;
! 229: struct cpu_info *ci;
! 230: cpuid_t cpu_id;
! 231:
! 232: /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */
! 233:
! 234: /*
! 235: * Turn off interrupts (not mchecks) and floating point.
! 236: * Make sure the instruction and data streams are consistent.
! 237: */
! 238: (void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
! 239: alpha_pal_wrfen(0);
! 240: ALPHA_TBIA();
! 241: alpha_pal_imb();
! 242:
! 243: /* Initialize the SCB. */
! 244: scb_init();
! 245:
! 246: cpu_id = cpu_number();
! 247:
! 248: #if defined(MULTIPROCESSOR)
! 249: /*
! 250: * Set our SysValue to the address of our cpu_info structure.
! 251: * Secondary processors do this in their spinup trampoline.
! 252: */
! 253: alpha_pal_wrval((u_long)&cpu_info[cpu_id]);
! 254: #endif
! 255:
! 256: ci = curcpu();
! 257: ci->ci_cpuid = cpu_id;
! 258:
! 259: /*
! 260: * Get critical system information (if possible, from the
! 261: * information provided by the boot program).
! 262: */
! 263: bootinfo_msg = NULL;
! 264: if (bim == BOOTINFO_MAGIC) {
! 265: if (biv == 0) { /* backward compat */
! 266: biv = *(u_long *)bip;
! 267: bip += 8;
! 268: }
! 269: switch (biv) {
! 270: case 1: {
! 271: struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip;
! 272:
! 273: bootinfo.ssym = v1p->ssym;
! 274: bootinfo.esym = v1p->esym;
! 275: /* hwrpb may not be provided by boot block in v1 */
! 276: if (v1p->hwrpb != NULL) {
! 277: bootinfo.hwrpb_phys =
! 278: ((struct rpb *)v1p->hwrpb)->rpb_phys;
! 279: bootinfo.hwrpb_size = v1p->hwrpbsize;
! 280: } else {
! 281: bootinfo.hwrpb_phys =
! 282: ((struct rpb *)HWRPB_ADDR)->rpb_phys;
! 283: bootinfo.hwrpb_size =
! 284: ((struct rpb *)HWRPB_ADDR)->rpb_size;
! 285: }
! 286: bcopy(v1p->boot_flags, bootinfo.boot_flags,
! 287: min(sizeof v1p->boot_flags,
! 288: sizeof bootinfo.boot_flags));
! 289: bcopy(v1p->booted_kernel, bootinfo.booted_kernel,
! 290: min(sizeof v1p->booted_kernel,
! 291: sizeof bootinfo.booted_kernel));
! 292: /* booted dev not provided in bootinfo */
! 293: init_prom_interface((struct rpb *)
! 294: ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys));
! 295: prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
! 296: sizeof bootinfo.booted_dev);
! 297: break;
! 298: }
! 299: default:
! 300: bootinfo_msg = "unknown bootinfo version";
! 301: goto nobootinfo;
! 302: }
! 303: } else {
! 304: bootinfo_msg = "boot program did not pass bootinfo";
! 305: nobootinfo:
! 306: bootinfo.ssym = (u_long)_end;
! 307: bootinfo.esym = (u_long)_end;
! 308: bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys;
! 309: bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size;
! 310: init_prom_interface((struct rpb *)HWRPB_ADDR);
! 311: prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
! 312: sizeof bootinfo.boot_flags);
! 313: prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
! 314: sizeof bootinfo.booted_kernel);
! 315: prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
! 316: sizeof bootinfo.booted_dev);
! 317: }
! 318:
! 319: esym = (caddr_t)bootinfo.esym;
! 320: /*
! 321: * Initialize the kernel's mapping of the RPB. It's needed for
! 322: * lots of things.
! 323: */
! 324: hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys);
! 325:
! 326: #if defined(DEC_3000_300) || defined(DEC_3000_500)
! 327: if (hwrpb->rpb_type == ST_DEC_3000_300 ||
! 328: hwrpb->rpb_type == ST_DEC_3000_500) {
! 329: prom_getenv(PROM_E_SCSIID, dec_3000_scsiid,
! 330: sizeof(dec_3000_scsiid));
! 331: prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast,
! 332: sizeof(dec_3000_scsifast));
! 333: }
! 334: #endif
! 335:
! 336: /*
! 337: * Remember how many cycles there are per microsecond,
! 338: * so that we can use delay(). Round up, for safety.
! 339: */
! 340: cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
! 341:
! 342: /*
! 343: * Initialize the (temporary) bootstrap console interface, so
! 344: * we can use printf until the VM system starts being setup.
! 345: * The real console is initialized before then.
! 346: */
! 347: init_bootstrap_console();
! 348:
! 349: /* OUTPUT NOW ALLOWED */
! 350:
! 351: /* delayed from above */
! 352: if (bootinfo_msg)
! 353: printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n",
! 354: bootinfo_msg, bim, bip, biv);
! 355:
! 356: /* Initialize the trap vectors on the primary processor. */
! 357: trap_init();
! 358:
! 359: /*
! 360: * Find out what hardware we're on, and do basic initialization.
! 361: */
! 362: cputype = hwrpb->rpb_type;
! 363: if (cputype < 0) {
! 364: /*
! 365: * At least some white-box systems have SRM which
! 366: * reports a systype that's the negative of their
! 367: * blue-box counterpart.
! 368: */
! 369: cputype = -cputype;
! 370: }
! 371: c = platform_lookup(cputype);
! 372: if (c == NULL) {
! 373: platform_not_supported();
! 374: /* NOTREACHED */
! 375: }
! 376: (*c->init)();
! 377: strlcpy(cpu_model, platform.model, sizeof cpu_model);
! 378:
! 379: /*
! 380: * Initialize the real console, so that the bootstrap console is
! 381: * no longer necessary.
! 382: */
! 383: (*platform.cons_init)();
! 384:
! 385: #if 0
! 386: /* Paranoid sanity checking */
! 387:
! 388: assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami());
! 389:
! 390: /*
! 391: * On single-CPU systypes, the primary should always be CPU 0,
! 392: * except on Alpha 8200 systems where the CPU id is related
! 393: * to the VID, which is related to the Turbo Laser node id.
! 394: */
! 395: if (cputype != ST_DEC_21000)
! 396: assert(hwrpb->rpb_primary_cpu_id == 0);
! 397: #endif
! 398:
! 399: /* NO MORE FIRMWARE ACCESS ALLOWED */
! 400: #ifdef _PMAP_MAY_USE_PROM_CONSOLE
! 401: /*
! 402: * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and
! 403: * XXX pmap_uses_prom_console() evaluates to non-zero.)
! 404: */
! 405: #endif
! 406:
! 407: #ifndef SMALL_KERNEL
! 408: /*
! 409: * If we run on a BWX-capable processor, override cpu_switch
! 410: * with a faster version.
! 411: * We do this now because the kernel text might be mapped
! 412: * read-only eventually (although this is not the case at the moment).
! 413: */
! 414: if (alpha_implver() >= ALPHA_IMPLVER_EV5) {
! 415: if (~alpha_amask(ALPHA_AMASK_BWX) != 0) {
! 416: extern vaddr_t __bwx_switch0, __bwx_switch1,
! 417: __bwx_switch2, __bwx_switch3;
! 418: u_int32_t *dst, *src, *end;
! 419:
! 420: src = (u_int32_t *)&__bwx_switch2;
! 421: end = (u_int32_t *)&__bwx_switch3;
! 422: dst = (u_int32_t *)&__bwx_switch0;
! 423: while (src != end)
! 424: *dst++ = *src++;
! 425: src = (u_int32_t *)&__bwx_switch1;
! 426: end = (u_int32_t *)&__bwx_switch2;
! 427: while (src != end)
! 428: *dst++ = *src++;
! 429: }
! 430: }
! 431: #endif
! 432:
! 433: /*
! 434: * find out this system's page size
! 435: */
! 436: if ((uvmexp.pagesize = hwrpb->rpb_page_size) != 8192)
! 437: panic("page size %d != 8192?!", uvmexp.pagesize);
! 438:
! 439: uvm_setpagesize();
! 440:
! 441: /*
! 442: * Find the beginning and end of the kernel (and leave a
! 443: * bit of space before the beginning for the bootstrap
! 444: * stack).
! 445: */
! 446: kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE;
! 447: kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym);
! 448:
! 449: kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart));
! 450: kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend));
! 451:
! 452: /*
! 453: * Find out how much memory is available, by looking at
! 454: * the memory cluster descriptors. This also tries to do
! 455: * its best to detect things things that have never been seen
! 456: * before...
! 457: */
! 458: mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
! 459:
! 460: /* MDDT SANITY CHECKING */
! 461: mddtweird = 0;
! 462: if (mddtp->mddt_cluster_cnt < 2) {
! 463: mddtweird = 1;
! 464: printf("WARNING: weird number of mem clusters: %lu\n",
! 465: mddtp->mddt_cluster_cnt);
! 466: }
! 467:
! 468: #if 0
! 469: printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt);
! 470: #endif
! 471:
! 472: for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
! 473: memc = &mddtp->mddt_clusters[i];
! 474: #if 0
! 475: printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i,
! 476: memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage);
! 477: #endif
! 478: totalphysmem += memc->mddt_pg_cnt;
! 479: if (mem_cluster_cnt < VM_PHYSSEG_MAX) { /* XXX */
! 480: mem_clusters[mem_cluster_cnt].start =
! 481: ptoa(memc->mddt_pfn);
! 482: mem_clusters[mem_cluster_cnt].size =
! 483: ptoa(memc->mddt_pg_cnt);
! 484: if (memc->mddt_usage & MDDT_mbz ||
! 485: memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */
! 486: memc->mddt_usage & MDDT_PALCODE)
! 487: mem_clusters[mem_cluster_cnt].size |=
! 488: VM_PROT_READ;
! 489: else
! 490: mem_clusters[mem_cluster_cnt].size |=
! 491: VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
! 492: mem_cluster_cnt++;
! 493: } /* XXX else print something! */
! 494:
! 495: if (memc->mddt_usage & MDDT_mbz) {
! 496: mddtweird = 1;
! 497: printf("WARNING: mem cluster %d has weird "
! 498: "usage 0x%lx\n", i, memc->mddt_usage);
! 499: unknownmem += memc->mddt_pg_cnt;
! 500: continue;
! 501: }
! 502: if (memc->mddt_usage & MDDT_NONVOLATILE) {
! 503: /* XXX should handle these... */
! 504: printf("WARNING: skipping non-volatile mem "
! 505: "cluster %d\n", i);
! 506: unusedmem += memc->mddt_pg_cnt;
! 507: continue;
! 508: }
! 509: if (memc->mddt_usage & MDDT_PALCODE) {
! 510: resvmem += memc->mddt_pg_cnt;
! 511: continue;
! 512: }
! 513:
! 514: /*
! 515: * We have a memory cluster available for system
! 516: * software use. We must determine if this cluster
! 517: * holds the kernel.
! 518: */
! 519: #ifdef _PMAP_MAY_USE_PROM_CONSOLE
! 520: /*
! 521: * XXX If the kernel uses the PROM console, we only use the
! 522: * XXX memory after the kernel in the first system segment,
! 523: * XXX to avoid clobbering prom mapping, data, etc.
! 524: */
! 525: if (!pmap_uses_prom_console() || physmem == 0) {
! 526: #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
! 527: physmem += memc->mddt_pg_cnt;
! 528: pfn0 = memc->mddt_pfn;
! 529: pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt;
! 530: if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) {
! 531: /*
! 532: * Must compute the location of the kernel
! 533: * within the segment.
! 534: */
! 535: #if 0
! 536: printf("Cluster %d contains kernel\n", i);
! 537: #endif
! 538: #ifdef _PMAP_MAY_USE_PROM_CONSOLE
! 539: if (!pmap_uses_prom_console()) {
! 540: #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
! 541: if (pfn0 < kernstartpfn) {
! 542: /*
! 543: * There is a chunk before the kernel.
! 544: */
! 545: #if 0
! 546: printf("Loading chunk before kernel: "
! 547: "0x%lx / 0x%lx\n", pfn0, kernstartpfn);
! 548: #endif
! 549: uvm_page_physload(pfn0, kernstartpfn,
! 550: pfn0, kernstartpfn, VM_FREELIST_DEFAULT);
! 551: }
! 552: #ifdef _PMAP_MAY_USE_PROM_CONSOLE
! 553: }
! 554: #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
! 555: if (kernendpfn < pfn1) {
! 556: /*
! 557: * There is a chunk after the kernel.
! 558: */
! 559: #if 0
! 560: printf("Loading chunk after kernel: "
! 561: "0x%lx / 0x%lx\n", kernendpfn, pfn1);
! 562: #endif
! 563: uvm_page_physload(kernendpfn, pfn1,
! 564: kernendpfn, pfn1, VM_FREELIST_DEFAULT);
! 565: }
! 566: } else {
! 567: /*
! 568: * Just load this cluster as one chunk.
! 569: */
! 570: #if 0
! 571: printf("Loading cluster %d: 0x%lx / 0x%lx\n", i,
! 572: pfn0, pfn1);
! 573: #endif
! 574: uvm_page_physload(pfn0, pfn1, pfn0, pfn1,
! 575: VM_FREELIST_DEFAULT);
! 576: }
! 577: #ifdef _PMAP_MAY_USE_PROM_CONSOLE
! 578: }
! 579: #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
! 580: }
! 581:
! 582: #ifdef DEBUG
! 583: /*
! 584: * Dump out the MDDT if it looks odd...
! 585: */
! 586: if (mddtweird) {
! 587: printf("\n");
! 588: printf("complete memory cluster information:\n");
! 589: for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
! 590: printf("mddt %d:\n", i);
! 591: printf("\tpfn %lx\n",
! 592: mddtp->mddt_clusters[i].mddt_pfn);
! 593: printf("\tcnt %lx\n",
! 594: mddtp->mddt_clusters[i].mddt_pg_cnt);
! 595: printf("\ttest %lx\n",
! 596: mddtp->mddt_clusters[i].mddt_pg_test);
! 597: printf("\tbva %lx\n",
! 598: mddtp->mddt_clusters[i].mddt_v_bitaddr);
! 599: printf("\tbpa %lx\n",
! 600: mddtp->mddt_clusters[i].mddt_p_bitaddr);
! 601: printf("\tbcksum %lx\n",
! 602: mddtp->mddt_clusters[i].mddt_bit_cksum);
! 603: printf("\tusage %lx\n",
! 604: mddtp->mddt_clusters[i].mddt_usage);
! 605: }
! 606: printf("\n");
! 607: }
! 608: #endif
! 609:
! 610: if (totalphysmem == 0)
! 611: panic("can't happen: system seems to have no memory!");
! 612: #if 0
! 613: printf("totalphysmem = %u\n", totalphysmem);
! 614: printf("physmem = %u\n", physmem);
! 615: printf("resvmem = %d\n", resvmem);
! 616: printf("unusedmem = %d\n", unusedmem);
! 617: printf("unknownmem = %d\n", unknownmem);
! 618: #endif
! 619:
! 620: /*
! 621: * Initialize error message buffer (at end of core).
! 622: */
! 623: {
! 624: vsize_t sz = (vsize_t)round_page(MSGBUFSIZE);
! 625: vsize_t reqsz = sz;
! 626:
! 627: vps = &vm_physmem[vm_nphysseg - 1];
! 628:
! 629: /* shrink so that it'll fit in the last segment */
! 630: if ((vps->avail_end - vps->avail_start) < atop(sz))
! 631: sz = ptoa(vps->avail_end - vps->avail_start);
! 632:
! 633: vps->end -= atop(sz);
! 634: vps->avail_end -= atop(sz);
! 635: initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz);
! 636:
! 637: /* Remove the last segment if it now has no pages. */
! 638: if (vps->start == vps->end)
! 639: vm_nphysseg--;
! 640:
! 641: /* warn if the message buffer had to be shrunk */
! 642: if (sz != reqsz)
! 643: printf("WARNING: %ld bytes not available for msgbuf "
! 644: "in last cluster (%ld used)\n", reqsz, sz);
! 645:
! 646: }
! 647:
! 648: /*
! 649: * Init mapping for u page(s) for proc 0
! 650: */
! 651: proc0.p_addr = proc0paddr =
! 652: (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL);
! 653:
! 654: /*
! 655: * Allocate space for system data structures. These data structures
! 656: * are allocated here instead of cpu_startup() because physical
! 657: * memory is directly addressable. We don't have to map these into
! 658: * virtual address space.
! 659: */
! 660: size = (vsize_t)allocsys(NULL);
! 661: v = (caddr_t)pmap_steal_memory(size, NULL, NULL);
! 662: if ((allocsys(v) - v) != size)
! 663: panic("alpha_init: table size inconsistency");
! 664:
! 665: /*
! 666: * Clear allocated memory.
! 667: */
! 668: bzero(v, size);
! 669:
! 670: /*
! 671: * Initialize the virtual memory system, and set the
! 672: * page table base register in proc 0's PCB.
! 673: */
! 674: pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT),
! 675: hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt);
! 676:
! 677: /*
! 678: * Initialize the rest of proc 0's PCB, and cache its physical
! 679: * address.
! 680: */
! 681: proc0.p_md.md_pcbpaddr =
! 682: (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb);
! 683:
! 684: /*
! 685: * Set the kernel sp, reserving space for an (empty) trapframe,
! 686: * and make proc0's trapframe pointer point to it for sanity.
! 687: */
! 688: proc0paddr->u_pcb.pcb_hw.apcb_ksp =
! 689: (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
! 690: proc0.p_md.md_tf =
! 691: (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
! 692:
! 693: /*
! 694: * Initialize the primary CPU's idle PCB to proc0's. In a
! 695: * MULTIPROCESSOR configuration, each CPU will later get
! 696: * its own idle PCB when autoconfiguration runs.
! 697: */
! 698: ci->ci_idle_pcb = &proc0paddr->u_pcb;
! 699: ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr;
! 700:
! 701: /*
! 702: * Look at arguments passed to us and compute boothowto.
! 703: */
! 704:
! 705: #ifdef KADB
! 706: boothowto |= RB_KDB;
! 707: #endif
! 708: for (p = bootinfo.boot_flags; p && *p != '\0'; p++) {
! 709: /*
! 710: * Note that we'd really like to differentiate case here,
! 711: * but the Alpha AXP Architecture Reference Manual
! 712: * says that we shouldn't.
! 713: */
! 714: switch (*p) {
! 715: case 'a': /* Ignore */
! 716: case 'A':
! 717: break;
! 718:
! 719: case 'b': /* Enter DDB as soon as the console is initialised */
! 720: case 'B':
! 721: boothowto |= RB_KDB;
! 722: break;
! 723:
! 724: case 'c': /* enter user kernel configuration */
! 725: case 'C':
! 726: boothowto |= RB_CONFIG;
! 727: break;
! 728:
! 729: #ifdef DEBUG
! 730: case 'd': /* crash dump immediately after autoconfig */
! 731: case 'D':
! 732: boothowto |= RB_DUMP;
! 733: break;
! 734: #endif
! 735:
! 736: case 'h': /* always halt, never reboot */
! 737: case 'H':
! 738: boothowto |= RB_HALT;
! 739: break;
! 740:
! 741: #if 0
! 742: case 'm': /* mini root present in memory */
! 743: case 'M':
! 744: boothowto |= RB_MINIROOT;
! 745: break;
! 746: #endif
! 747:
! 748: case 'n': /* askname */
! 749: case 'N':
! 750: boothowto |= RB_ASKNAME;
! 751: break;
! 752:
! 753: case 's': /* single-user */
! 754: case 'S':
! 755: boothowto |= RB_SINGLE;
! 756: break;
! 757:
! 758: case '-':
! 759: /*
! 760: * Just ignore this. It's not required, but it's
! 761: * common for it to be passed regardless.
! 762: */
! 763: break;
! 764:
! 765: default:
! 766: printf("Unrecognized boot flag '%c'.\n", *p);
! 767: break;
! 768: }
! 769: }
! 770:
! 771:
! 772: /*
! 773: * Figure out the number of cpus in the box, from RPB fields.
! 774: * Really. We mean it.
! 775: */
! 776: for (alpha_cpus = 0, i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
! 777: struct pcs *pcsp;
! 778:
! 779: pcsp = LOCATE_PCS(hwrpb, i);
! 780: if ((pcsp->pcs_flags & PCS_PP) != 0)
! 781: alpha_cpus++;
! 782: }
! 783:
! 784: /*
! 785: * Initialize debuggers, and break into them if appropriate.
! 786: */
! 787: #ifdef DDB
! 788: ddb_init();
! 789:
! 790: if (boothowto & RB_KDB)
! 791: Debugger();
! 792: #endif
! 793: #ifdef KGDB
! 794: if (boothowto & RB_KDB)
! 795: kgdb_connect(0);
! 796: #endif
! 797: /*
! 798: * Figure out our clock frequency, from RPB fields.
! 799: */
! 800: hz = hwrpb->rpb_intr_freq >> 12;
! 801: if (!(60 <= hz && hz <= 10240)) {
! 802: hz = 1024;
! 803: #ifdef DIAGNOSTIC
! 804: printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n",
! 805: hwrpb->rpb_intr_freq, hz);
! 806: #endif
! 807: }
! 808: }
! 809:
! 810: caddr_t
! 811: allocsys(v)
! 812: caddr_t v;
! 813: {
! 814: /*
! 815: * Allocate space for system data structures.
! 816: * The first available kernel virtual address is in "v".
! 817: * As pages of kernel virtual memory are allocated, "v" is incremented.
! 818: *
! 819: * These data structures are allocated here instead of cpu_startup()
! 820: * because physical memory is directly addressable. We don't have
! 821: * to map these into virtual address space.
! 822: */
! 823: #define valloc(name, type, num) \
! 824: (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num))
! 825:
! 826: #ifdef SYSVMSG
! 827: valloc(msgpool, char, msginfo.msgmax);
! 828: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 829: valloc(msghdrs, struct msg, msginfo.msgtql);
! 830: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 831: #endif
! 832:
! 833: #undef valloc
! 834:
! 835: return v;
! 836: }
! 837:
! 838: void
! 839: consinit()
! 840: {
! 841:
! 842: /*
! 843: * Everything related to console initialization is done
! 844: * in alpha_init().
! 845: */
! 846: #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE)
! 847: printf("consinit: %susing prom console\n",
! 848: pmap_uses_prom_console() ? "" : "not ");
! 849: #endif
! 850: }
! 851:
! 852: void
! 853: cpu_startup()
! 854: {
! 855: vaddr_t minaddr, maxaddr;
! 856: #if defined(DEBUG)
! 857: extern int pmapdebug;
! 858: int opmapdebug = pmapdebug;
! 859:
! 860: pmapdebug = 0;
! 861: #endif
! 862:
! 863: /*
! 864: * Good {morning,afternoon,evening,night}.
! 865: */
! 866: printf(version);
! 867: identifycpu();
! 868: printf("total memory = %ld (%ldK)\n", ptoa((u_long)totalphysmem),
! 869: ptoa((u_long)totalphysmem) / 1024);
! 870: printf("(%ld reserved for PROM, ", ptoa((u_long)resvmem));
! 871: printf("%ld used by OpenBSD)\n", ptoa((u_long)physmem));
! 872: if (unusedmem) {
! 873: printf("WARNING: unused memory = %ld (%ldK)\n",
! 874: ptoa((u_long)unusedmem), ptoa((u_long)unusedmem) / 1024);
! 875: }
! 876: if (unknownmem) {
! 877: printf("WARNING: %ld (%ldK) of memory with unknown purpose\n",
! 878: ptoa((u_long)unknownmem), ptoa((u_long)unknownmem) / 1024);
! 879: }
! 880:
! 881: /*
! 882: * Determine how many buffers to allocate.
! 883: * We allocate bufcachepercent% of memory for buffer space.
! 884: */
! 885: if (bufpages == 0)
! 886: bufpages = physmem * bufcachepercent / 100;
! 887:
! 888: /*
! 889: * Allocate a submap for exec arguments. This map effectively
! 890: * limits the number of processes exec'ing at any time.
! 891: */
! 892: minaddr = vm_map_min(kernel_map);
! 893: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 894: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 895:
! 896: /*
! 897: * Allocate a submap for physio
! 898: */
! 899: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 900: VM_PHYS_SIZE, 0, FALSE, NULL);
! 901:
! 902: #if defined(DEBUG)
! 903: pmapdebug = opmapdebug;
! 904: #endif
! 905: printf("avail memory = %ld (%ldK)\n", (long)ptoa(uvmexp.free),
! 906: (long)ptoa(uvmexp.free) / 1024);
! 907: #if 0
! 908: {
! 909: extern u_long pmap_pages_stolen;
! 910:
! 911: printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE);
! 912: }
! 913: #endif
! 914:
! 915: /*
! 916: * Set up buffers, so they can be used to read disk labels.
! 917: */
! 918: bufinit();
! 919:
! 920: /*
! 921: * Configure the system.
! 922: */
! 923: if (boothowto & RB_CONFIG) {
! 924: #ifdef BOOT_CONFIG
! 925: user_config();
! 926: #else
! 927: printf("kernel does not support -c; continuing..\n");
! 928: #endif
! 929: }
! 930:
! 931: /*
! 932: * Set up the HWPCB so that it's safe to configure secondary
! 933: * CPUs.
! 934: */
! 935: hwrpb_primary_init();
! 936: }
! 937:
! 938: /*
! 939: * Retrieve the platform name from the DSR.
! 940: */
! 941: const char *
! 942: alpha_dsr_sysname()
! 943: {
! 944: struct dsrdb *dsr;
! 945: const char *sysname;
! 946:
! 947: /*
! 948: * DSR does not exist on early HWRPB versions.
! 949: */
! 950: if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS)
! 951: return (NULL);
! 952:
! 953: dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off);
! 954: sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off +
! 955: sizeof(u_int64_t)));
! 956: return (sysname);
! 957: }
! 958:
! 959: /*
! 960: * Lookup the system specified system variation in the provided table,
! 961: * returning the model string on match.
! 962: */
! 963: const char *
! 964: alpha_variation_name(variation, avtp)
! 965: u_int64_t variation;
! 966: const struct alpha_variation_table *avtp;
! 967: {
! 968: int i;
! 969:
! 970: for (i = 0; avtp[i].avt_model != NULL; i++)
! 971: if (avtp[i].avt_variation == variation)
! 972: return (avtp[i].avt_model);
! 973: return (NULL);
! 974: }
! 975:
! 976: /*
! 977: * Generate a default platform name based for unknown system variations.
! 978: */
! 979: const char *
! 980: alpha_unknown_sysname()
! 981: {
! 982: static char s[128]; /* safe size */
! 983:
! 984: snprintf(s, sizeof s, "%s family, unknown model variation 0x%lx",
! 985: platform.family, hwrpb->rpb_variation & SV_ST_MASK);
! 986: return ((const char *)s);
! 987: }
! 988:
! 989: void
! 990: identifycpu()
! 991: {
! 992: char *s;
! 993: int slen;
! 994:
! 995: /*
! 996: * print out CPU identification information.
! 997: */
! 998: printf("%s", cpu_model);
! 999: for(s = cpu_model; *s; ++s)
! 1000: if(strncasecmp(s, "MHz", 3) == 0)
! 1001: goto skipMHz;
! 1002: printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000);
! 1003: skipMHz:
! 1004: /* fill in hw_serial if a serial number is known */
! 1005: slen = strlen(hwrpb->rpb_ssn) + 1;
! 1006: if (slen > 1) {
! 1007: hw_serial = malloc(slen, M_SYSCTL, M_NOWAIT);
! 1008: if (hw_serial)
! 1009: strlcpy(hw_serial, (char *)hwrpb->rpb_ssn, slen);
! 1010: }
! 1011:
! 1012: printf("\n");
! 1013: printf("%ld byte page size, %d processor%s.\n",
! 1014: hwrpb->rpb_page_size, alpha_cpus, alpha_cpus == 1 ? "" : "s");
! 1015: #if 0
! 1016: /* this is not particularly useful! */
! 1017: printf("variation: 0x%lx, revision 0x%lx\n",
! 1018: hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
! 1019: #endif
! 1020: }
! 1021:
! 1022: int waittime = -1;
! 1023: struct pcb dumppcb;
! 1024:
! 1025: void
! 1026: boot(howto)
! 1027: int howto;
! 1028: {
! 1029: #if defined(MULTIPROCESSOR)
! 1030: #if 0 /* XXX See below. */
! 1031: u_long cpu_id;
! 1032: #endif
! 1033: #endif
! 1034:
! 1035: #if defined(MULTIPROCESSOR)
! 1036: /* We must be running on the primary CPU. */
! 1037: if (alpha_pal_whami() != hwrpb->rpb_primary_cpu_id)
! 1038: panic("cpu_reboot: not on primary CPU!");
! 1039: #endif
! 1040:
! 1041: /* If system is cold, just halt. */
! 1042: if (cold) {
! 1043: /* (Unless the user explicitly asked for reboot.) */
! 1044: if ((howto & RB_USERREQ) == 0)
! 1045: howto |= RB_HALT;
! 1046: goto haltsys;
! 1047: }
! 1048:
! 1049: /* If "always halt" was specified as a boot flag, obey. */
! 1050: if ((boothowto & RB_HALT) != 0)
! 1051: howto |= RB_HALT;
! 1052:
! 1053: boothowto = howto;
! 1054: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
! 1055: waittime = 0;
! 1056: vfs_shutdown();
! 1057: /*
! 1058: * If we've been adjusting the clock, the todr
! 1059: * will be out of synch; adjust it now unless
! 1060: * the system has been sitting in ddb.
! 1061: */
! 1062: if ((howto & RB_TIMEBAD) == 0) {
! 1063: resettodr();
! 1064: } else {
! 1065: printf("WARNING: not updating battery clock\n");
! 1066: }
! 1067: }
! 1068:
! 1069: /* Disable interrupts. */
! 1070: splhigh();
! 1071:
! 1072: /* If rebooting and a dump is requested do it. */
! 1073: if (howto & RB_DUMP)
! 1074: dumpsys();
! 1075:
! 1076: haltsys:
! 1077:
! 1078: /* run any shutdown hooks */
! 1079: doshutdownhooks();
! 1080:
! 1081: #if defined(MULTIPROCESSOR)
! 1082: #if 0 /* XXX doesn't work when called from here?! */
! 1083: /* Kill off any secondary CPUs. */
! 1084: for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) {
! 1085: if (cpu_id == hwrpb->rpb_primary_cpu_id ||
! 1086: cpu_info[cpu_id].ci_softc == NULL)
! 1087: continue;
! 1088: cpu_halt_secondary(cpu_id);
! 1089: }
! 1090: #endif
! 1091: #endif
! 1092:
! 1093: #ifdef BOOTKEY
! 1094: printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
! 1095: cnpollc(1); /* for proper keyboard command handling */
! 1096: cngetc();
! 1097: cnpollc(0);
! 1098: printf("\n");
! 1099: #endif
! 1100:
! 1101: /* Finally, powerdown/halt/reboot the system. */
! 1102: if ((howto & RB_POWERDOWN) == RB_POWERDOWN &&
! 1103: platform.powerdown != NULL) {
! 1104: (*platform.powerdown)();
! 1105: printf("WARNING: powerdown failed!\n");
! 1106: }
! 1107: printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
! 1108: prom_halt(howto & RB_HALT);
! 1109: /*NOTREACHED*/
! 1110: }
! 1111:
! 1112: /*
! 1113: * These variables are needed by /sbin/savecore
! 1114: */
! 1115: u_long dumpmag = 0x8fca0101; /* magic number */
! 1116: int dumpsize = 0; /* pages */
! 1117: long dumplo = 0; /* blocks */
! 1118:
! 1119: /*
! 1120: * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
! 1121: */
! 1122: int
! 1123: cpu_dumpsize()
! 1124: {
! 1125: int size;
! 1126:
! 1127: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
! 1128: ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
! 1129: if (roundup(size, dbtob(1)) != dbtob(1))
! 1130: return -1;
! 1131:
! 1132: return (1);
! 1133: }
! 1134:
! 1135: /*
! 1136: * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped.
! 1137: */
! 1138: u_long
! 1139: cpu_dump_mempagecnt()
! 1140: {
! 1141: u_long i, n;
! 1142:
! 1143: n = 0;
! 1144: for (i = 0; i < mem_cluster_cnt; i++)
! 1145: n += atop(mem_clusters[i].size);
! 1146: return (n);
! 1147: }
! 1148:
! 1149: /*
! 1150: * cpu_dump: dump machine-dependent kernel core dump headers.
! 1151: */
! 1152: int
! 1153: cpu_dump()
! 1154: {
! 1155: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 1156: char buf[dbtob(1)];
! 1157: kcore_seg_t *segp;
! 1158: cpu_kcore_hdr_t *cpuhdrp;
! 1159: phys_ram_seg_t *memsegp;
! 1160: int i;
! 1161:
! 1162: dump = bdevsw[major(dumpdev)].d_dump;
! 1163:
! 1164: bzero(buf, sizeof buf);
! 1165: segp = (kcore_seg_t *)buf;
! 1166: cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
! 1167: memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) +
! 1168: ALIGN(sizeof(*cpuhdrp))];
! 1169:
! 1170: /*
! 1171: * Generate a segment header.
! 1172: */
! 1173: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 1174: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
! 1175:
! 1176: /*
! 1177: * Add the machine-dependent header info.
! 1178: */
! 1179: cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map);
! 1180: cpuhdrp->page_size = PAGE_SIZE;
! 1181: cpuhdrp->nmemsegs = mem_cluster_cnt;
! 1182:
! 1183: /*
! 1184: * Fill in the memory segment descriptors.
! 1185: */
! 1186: for (i = 0; i < mem_cluster_cnt; i++) {
! 1187: memsegp[i].start = mem_clusters[i].start;
! 1188: memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK;
! 1189: }
! 1190:
! 1191: return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
! 1192: }
! 1193:
! 1194: /*
! 1195: * This is called by main to set dumplo and dumpsize.
! 1196: * Dumps always skip the first PAGE_SIZE of disk space
! 1197: * in case there might be a disk label stored there.
! 1198: * If there is extra space, put dump at the end to
! 1199: * reduce the chance that swapping trashes it.
! 1200: */
! 1201: void
! 1202: dumpconf(void)
! 1203: {
! 1204: int nblks, dumpblks; /* size of dump area */
! 1205:
! 1206: if (dumpdev == NODEV ||
! 1207: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 1208: return;
! 1209: if (nblks <= ctod(1))
! 1210: return;
! 1211:
! 1212: dumpblks = cpu_dumpsize();
! 1213: if (dumpblks < 0)
! 1214: return;
! 1215: dumpblks += ctod(cpu_dump_mempagecnt());
! 1216:
! 1217: /* If dump won't fit (incl. room for possible label), punt. */
! 1218: if (dumpblks > (nblks - ctod(1)))
! 1219: return;
! 1220:
! 1221: /* Put dump at end of partition */
! 1222: dumplo = nblks - dumpblks;
! 1223:
! 1224: /* dumpsize is in page units, and doesn't include headers. */
! 1225: dumpsize = cpu_dump_mempagecnt();
! 1226: }
! 1227:
! 1228: /*
! 1229: * Dump the kernel's image to the swap partition.
! 1230: */
! 1231: #define BYTES_PER_DUMP PAGE_SIZE
! 1232:
! 1233: void
! 1234: dumpsys()
! 1235: {
! 1236: u_long totalbytesleft, bytes, i, n, memcl;
! 1237: u_long maddr;
! 1238: int psize;
! 1239: daddr64_t blkno;
! 1240: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 1241: int error;
! 1242: extern int msgbufmapped;
! 1243:
! 1244: /* Save registers. */
! 1245: savectx(&dumppcb);
! 1246:
! 1247: msgbufmapped = 0; /* don't record dump msgs in msgbuf */
! 1248: if (dumpdev == NODEV)
! 1249: return;
! 1250:
! 1251: /*
! 1252: * For dumps during autoconfiguration,
! 1253: * if dump device has already configured...
! 1254: */
! 1255: if (dumpsize == 0)
! 1256: dumpconf();
! 1257: if (dumplo <= 0) {
! 1258: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
! 1259: minor(dumpdev));
! 1260: return;
! 1261: }
! 1262: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
! 1263: minor(dumpdev), dumplo);
! 1264:
! 1265: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
! 1266: printf("dump ");
! 1267: if (psize == -1) {
! 1268: printf("area unavailable\n");
! 1269: return;
! 1270: }
! 1271:
! 1272: /* XXX should purge all outstanding keystrokes. */
! 1273:
! 1274: if ((error = cpu_dump()) != 0)
! 1275: goto err;
! 1276:
! 1277: totalbytesleft = ptoa(cpu_dump_mempagecnt());
! 1278: blkno = dumplo + cpu_dumpsize();
! 1279: dump = bdevsw[major(dumpdev)].d_dump;
! 1280: error = 0;
! 1281:
! 1282: for (memcl = 0; memcl < mem_cluster_cnt; memcl++) {
! 1283: maddr = mem_clusters[memcl].start;
! 1284: bytes = mem_clusters[memcl].size & ~PAGE_MASK;
! 1285:
! 1286: for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
! 1287:
! 1288: /* Print out how many MBs we to go. */
! 1289: if ((totalbytesleft % (1024*1024)) == 0)
! 1290: printf("%ld ", totalbytesleft / (1024 * 1024));
! 1291:
! 1292: /* Limit size for next transfer. */
! 1293: n = bytes - i;
! 1294: if (n > BYTES_PER_DUMP)
! 1295: n = BYTES_PER_DUMP;
! 1296:
! 1297: error = (*dump)(dumpdev, blkno,
! 1298: (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n);
! 1299: if (error)
! 1300: goto err;
! 1301: maddr += n;
! 1302: blkno += btodb(n); /* XXX? */
! 1303:
! 1304: /* XXX should look for keystrokes, to cancel. */
! 1305: }
! 1306: }
! 1307:
! 1308: err:
! 1309: switch (error) {
! 1310: #ifdef DEBUG
! 1311: case ENXIO:
! 1312: printf("device bad\n");
! 1313: break;
! 1314:
! 1315: case EFAULT:
! 1316: printf("device not ready\n");
! 1317: break;
! 1318:
! 1319: case EINVAL:
! 1320: printf("area improper\n");
! 1321: break;
! 1322:
! 1323: case EIO:
! 1324: printf("i/o error\n");
! 1325: break;
! 1326:
! 1327: case EINTR:
! 1328: printf("aborted from console\n");
! 1329: break;
! 1330: #endif /* DEBUG */
! 1331: case 0:
! 1332: printf("succeeded\n");
! 1333: break;
! 1334:
! 1335: default:
! 1336: printf("error %d\n", error);
! 1337: break;
! 1338: }
! 1339: printf("\n\n");
! 1340: delay(1000);
! 1341: }
! 1342:
! 1343: void
! 1344: frametoreg(framep, regp)
! 1345: struct trapframe *framep;
! 1346: struct reg *regp;
! 1347: {
! 1348:
! 1349: regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
! 1350: regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
! 1351: regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
! 1352: regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
! 1353: regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
! 1354: regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
! 1355: regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
! 1356: regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
! 1357: regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
! 1358: regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
! 1359: regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
! 1360: regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
! 1361: regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
! 1362: regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
! 1363: regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
! 1364: regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
! 1365: regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0];
! 1366: regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1];
! 1367: regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2];
! 1368: regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
! 1369: regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
! 1370: regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
! 1371: regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
! 1372: regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
! 1373: regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
! 1374: regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
! 1375: regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
! 1376: regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
! 1377: regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
! 1378: regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP];
! 1379: /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */
! 1380: regp->r_regs[R_ZERO] = 0;
! 1381: }
! 1382:
! 1383: void
! 1384: regtoframe(regp, framep)
! 1385: struct reg *regp;
! 1386: struct trapframe *framep;
! 1387: {
! 1388:
! 1389: framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
! 1390: framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
! 1391: framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
! 1392: framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
! 1393: framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
! 1394: framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
! 1395: framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
! 1396: framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
! 1397: framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
! 1398: framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
! 1399: framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
! 1400: framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
! 1401: framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
! 1402: framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
! 1403: framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
! 1404: framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
! 1405: framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0];
! 1406: framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1];
! 1407: framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2];
! 1408: framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
! 1409: framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
! 1410: framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
! 1411: framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
! 1412: framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
! 1413: framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
! 1414: framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
! 1415: framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
! 1416: framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
! 1417: framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
! 1418: framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP];
! 1419: /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */
! 1420: /* ??? = regp->r_regs[R_ZERO]; */
! 1421: }
! 1422:
! 1423: void
! 1424: printregs(regp)
! 1425: struct reg *regp;
! 1426: {
! 1427: int i;
! 1428:
! 1429: for (i = 0; i < 32; i++)
! 1430: printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
! 1431: i & 1 ? "\n" : "\t");
! 1432: }
! 1433:
! 1434: void
! 1435: regdump(framep)
! 1436: struct trapframe *framep;
! 1437: {
! 1438: struct reg reg;
! 1439:
! 1440: frametoreg(framep, ®);
! 1441: reg.r_regs[R_SP] = alpha_pal_rdusp();
! 1442:
! 1443: printf("REGISTERS:\n");
! 1444: printregs(®);
! 1445: }
! 1446:
! 1447: #ifdef DEBUG
! 1448: int sigdebug = 0;
! 1449: int sigpid = 0;
! 1450: #define SDB_FOLLOW 0x01
! 1451: #define SDB_KSTACK 0x02
! 1452: #endif
! 1453:
! 1454: /*
! 1455: * Send an interrupt to process.
! 1456: */
! 1457: void
! 1458: sendsig(catcher, sig, mask, code, type, val)
! 1459: sig_t catcher;
! 1460: int sig, mask;
! 1461: u_long code;
! 1462: int type;
! 1463: union sigval val;
! 1464: {
! 1465: struct proc *p = curproc;
! 1466: struct sigcontext *scp, ksc;
! 1467: struct trapframe *frame;
! 1468: struct sigacts *psp = p->p_sigacts;
! 1469: int oonstack, fsize, rndfsize, kscsize;
! 1470: siginfo_t *sip, ksi;
! 1471:
! 1472: frame = p->p_md.md_tf;
! 1473: oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 1474: fsize = sizeof ksc;
! 1475: rndfsize = ((fsize + 15) / 16) * 16;
! 1476: kscsize = rndfsize;
! 1477: if (psp->ps_siginfo & sigmask(sig)) {
! 1478: fsize += sizeof ksi;
! 1479: rndfsize = ((fsize + 15) / 16) * 16;
! 1480: }
! 1481:
! 1482: /*
! 1483: * Allocate and validate space for the signal handler
! 1484: * context. Note that if the stack is in P0 space, the
! 1485: * call to uvm_grow() is a nop, and the useracc() check
! 1486: * will fail if the process has not already allocated
! 1487: * the space with a `brk'.
! 1488: */
! 1489: if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
! 1490: (psp->ps_sigonstack & sigmask(sig))) {
! 1491: scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp +
! 1492: psp->ps_sigstk.ss_size - rndfsize);
! 1493: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1494: } else
! 1495: scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize);
! 1496: if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
! 1497: (void)uvm_grow(p, (u_long)scp);
! 1498: #ifdef DEBUG
! 1499: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 1500: printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
! 1501: sig, &oonstack, scp);
! 1502: #endif
! 1503:
! 1504: /*
! 1505: * Build the signal context to be used by sigreturn.
! 1506: */
! 1507: ksc.sc_onstack = oonstack;
! 1508: ksc.sc_mask = mask;
! 1509: ksc.sc_pc = frame->tf_regs[FRAME_PC];
! 1510: ksc.sc_ps = frame->tf_regs[FRAME_PS];
! 1511:
! 1512: /* copy the registers. */
! 1513: frametoreg(frame, (struct reg *)ksc.sc_regs);
! 1514: ksc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */
! 1515: ksc.sc_regs[R_SP] = alpha_pal_rdusp();
! 1516:
! 1517: /* save the floating-point state, if necessary, then copy it. */
! 1518: if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
! 1519: fpusave_proc(p, 1);
! 1520: ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
! 1521: memcpy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
! 1522: sizeof(struct fpreg));
! 1523: #ifndef NO_IEEE
! 1524: ksc.sc_fp_control = alpha_read_fp_c(p);
! 1525: #else
! 1526: ksc.sc_fp_control = 0;
! 1527: #endif
! 1528: memset(ksc.sc_reserved, 0, sizeof ksc.sc_reserved); /* XXX */
! 1529: memset(ksc.sc_xxx, 0, sizeof ksc.sc_xxx); /* XXX */
! 1530:
! 1531: #ifdef COMPAT_OSF1
! 1532: /*
! 1533: * XXX Create an OSF/1-style sigcontext and associated goo.
! 1534: */
! 1535: #endif
! 1536:
! 1537: if (psp->ps_siginfo & sigmask(sig)) {
! 1538: initsiginfo(&ksi, sig, code, type, val);
! 1539: sip = (void *)scp + kscsize;
! 1540: if (copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize) != 0)
! 1541: goto trash;
! 1542: } else
! 1543: sip = NULL;
! 1544:
! 1545: /*
! 1546: * copy the frame out to userland.
! 1547: */
! 1548: if (copyout((caddr_t)&ksc, (caddr_t)scp, kscsize) != 0) {
! 1549: trash:
! 1550: #ifdef DEBUG
! 1551: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 1552: printf("sendsig(%d): copyout failed on sig %d\n",
! 1553: p->p_pid, sig);
! 1554: #endif
! 1555: /*
! 1556: * Process has trashed its stack; give it an illegal
! 1557: * instruction to halt it in its tracks.
! 1558: */
! 1559: sigexit(p, SIGILL);
! 1560: /* NOTREACHED */
! 1561: }
! 1562: #ifdef DEBUG
! 1563: if (sigdebug & SDB_FOLLOW)
! 1564: printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig,
! 1565: scp, code);
! 1566: #endif
! 1567:
! 1568: /*
! 1569: * Set up the registers to return to sigcode.
! 1570: */
! 1571: frame->tf_regs[FRAME_PC] = p->p_sigcode;
! 1572: frame->tf_regs[FRAME_A0] = sig;
! 1573: frame->tf_regs[FRAME_A1] = (u_int64_t)sip;
! 1574: frame->tf_regs[FRAME_A2] = (u_int64_t)scp;
! 1575: frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */
! 1576: alpha_pal_wrusp((unsigned long)scp);
! 1577:
! 1578: #ifdef DEBUG
! 1579: if (sigdebug & SDB_FOLLOW)
! 1580: printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
! 1581: frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]);
! 1582: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 1583: printf("sendsig(%d): sig %d returns\n",
! 1584: p->p_pid, sig);
! 1585: #endif
! 1586: }
! 1587:
! 1588: /*
! 1589: * System call to cleanup state after a signal
! 1590: * has been taken. Reset signal mask and
! 1591: * stack state from context left by sendsig (above).
! 1592: * Return to previous pc and psl as specified by
! 1593: * context left by sendsig. Check carefully to
! 1594: * make sure that the user has not modified the
! 1595: * psl to gain improper privileges or to cause
! 1596: * a machine fault.
! 1597: */
! 1598: /* ARGSUSED */
! 1599: int
! 1600: sys_sigreturn(p, v, retval)
! 1601: struct proc *p;
! 1602: void *v;
! 1603: register_t *retval;
! 1604: {
! 1605: struct sys_sigreturn_args /* {
! 1606: syscallarg(struct sigcontext *) sigcntxp;
! 1607: } */ *uap = v;
! 1608: struct sigcontext ksc;
! 1609: #ifdef DEBUG
! 1610: struct sigcontext *scp;
! 1611: #endif
! 1612: int error;
! 1613:
! 1614: #ifdef DEBUG
! 1615: if (sigdebug & SDB_FOLLOW)
! 1616: printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
! 1617: #endif
! 1618:
! 1619: /*
! 1620: * Test and fetch the context structure.
! 1621: * We grab it all at once for speed.
! 1622: */
! 1623: if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0)
! 1624: return (error);
! 1625:
! 1626: if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */
! 1627: return (EINVAL);
! 1628: /*
! 1629: * Restore the user-supplied information
! 1630: */
! 1631: if (ksc.sc_onstack)
! 1632: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
! 1633: else
! 1634: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 1635: p->p_sigmask = ksc.sc_mask &~ sigcantmask;
! 1636:
! 1637: p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
! 1638: p->p_md.md_tf->tf_regs[FRAME_PS] =
! 1639: (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
! 1640:
! 1641: regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
! 1642: alpha_pal_wrusp(ksc.sc_regs[R_SP]);
! 1643:
! 1644: /* XXX ksc.sc_ownedfp ? */
! 1645: if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
! 1646: fpusave_proc(p, 0);
! 1647: memcpy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
! 1648: sizeof(struct fpreg));
! 1649: #ifndef NO_IEEE
! 1650: p->p_addr->u_pcb.pcb_fp.fpr_cr = ksc.sc_fpcr;
! 1651: p->p_md.md_flags = ksc.sc_fp_control & MDP_FP_C;
! 1652: #endif
! 1653:
! 1654: #ifdef DEBUG
! 1655: if (sigdebug & SDB_FOLLOW)
! 1656: printf("sigreturn(%d): returns\n", p->p_pid);
! 1657: #endif
! 1658: return (EJUSTRETURN);
! 1659: }
! 1660:
! 1661: /*
! 1662: * machine dependent system variables.
! 1663: */
! 1664: int
! 1665: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 1666: int *name;
! 1667: u_int namelen;
! 1668: void *oldp;
! 1669: size_t *oldlenp;
! 1670: void *newp;
! 1671: size_t newlen;
! 1672: struct proc *p;
! 1673: {
! 1674: dev_t consdev;
! 1675:
! 1676: if (name[0] != CPU_CHIPSET && namelen != 1)
! 1677: return (ENOTDIR); /* overloaded */
! 1678:
! 1679: switch (name[0]) {
! 1680: case CPU_CONSDEV:
! 1681: if (cn_tab != NULL)
! 1682: consdev = cn_tab->cn_dev;
! 1683: else
! 1684: consdev = NODEV;
! 1685: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 1686: sizeof consdev));
! 1687:
! 1688: case CPU_ROOT_DEVICE:
! 1689: return (sysctl_rdstring(oldp, oldlenp, newp,
! 1690: root_device));
! 1691: #ifndef SMALL_KERNEL
! 1692: case CPU_UNALIGNED_PRINT:
! 1693: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 1694: &alpha_unaligned_print));
! 1695:
! 1696: case CPU_UNALIGNED_FIX:
! 1697: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 1698: &alpha_unaligned_fix));
! 1699:
! 1700: case CPU_UNALIGNED_SIGBUS:
! 1701: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 1702: &alpha_unaligned_sigbus));
! 1703:
! 1704: case CPU_BOOTED_KERNEL:
! 1705: return (sysctl_rdstring(oldp, oldlenp, newp,
! 1706: bootinfo.booted_kernel));
! 1707:
! 1708: case CPU_CHIPSET:
! 1709: return (alpha_sysctl_chipset(name + 1, namelen - 1, oldp,
! 1710: oldlenp));
! 1711: #endif /* SMALL_KERNEL */
! 1712:
! 1713: #ifndef NO_IEEE
! 1714: case CPU_FP_SYNC_COMPLETE:
! 1715: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 1716: &alpha_fp_sync_complete));
! 1717: #endif
! 1718: case CPU_ALLOWAPERTURE:
! 1719: #ifdef APERTURE
! 1720: if (securelevel > 0)
! 1721: return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
! 1722: &allowaperture));
! 1723: else
! 1724: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 1725: &allowaperture));
! 1726: #else
! 1727: return (sysctl_rdint(oldp, oldlenp, newp, 0));
! 1728: #endif
! 1729: default:
! 1730: return (EOPNOTSUPP);
! 1731: }
! 1732: /* NOTREACHED */
! 1733: }
! 1734:
! 1735: /*
! 1736: * Set registers on exec.
! 1737: */
! 1738: void
! 1739: setregs(p, pack, stack, retval)
! 1740: register struct proc *p;
! 1741: struct exec_package *pack;
! 1742: u_long stack;
! 1743: register_t *retval;
! 1744: {
! 1745: struct trapframe *tfp = p->p_md.md_tf;
! 1746: #ifdef DEBUG
! 1747: int i;
! 1748: #endif
! 1749:
! 1750: #ifdef DEBUG
! 1751: /*
! 1752: * Crash and dump, if the user requested it.
! 1753: */
! 1754: if (boothowto & RB_DUMP)
! 1755: panic("crash requested by boot flags");
! 1756: #endif
! 1757:
! 1758: #ifdef DEBUG
! 1759: for (i = 0; i < FRAME_SIZE; i++)
! 1760: tfp->tf_regs[i] = 0xbabefacedeadbeef;
! 1761: #else
! 1762: bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
! 1763: #endif
! 1764: bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
! 1765: alpha_pal_wrusp(stack);
! 1766: tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
! 1767: tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
! 1768:
! 1769: tfp->tf_regs[FRAME_A0] = stack;
! 1770: /* a1 and a2 already zeroed */
! 1771: tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */
! 1772:
! 1773: p->p_md.md_flags &= ~MDP_FPUSED;
! 1774: #ifndef NO_IEEE
! 1775: if (__predict_true((p->p_md.md_flags & IEEE_INHERIT) == 0)) {
! 1776: p->p_md.md_flags &= ~MDP_FP_C;
! 1777: p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_DYN(FP_RN);
! 1778: }
! 1779: #endif
! 1780: if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
! 1781: fpusave_proc(p, 0);
! 1782:
! 1783: retval[1] = 0;
! 1784: }
! 1785:
! 1786: /*
! 1787: * Release the FPU.
! 1788: */
! 1789: void
! 1790: fpusave_cpu(struct cpu_info *ci, int save)
! 1791: {
! 1792: struct proc *p;
! 1793:
! 1794: KDASSERT(ci == curcpu());
! 1795:
! 1796: #if defined(MULTIPROCESSOR)
! 1797: atomic_setbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
! 1798: #endif
! 1799:
! 1800: p = ci->ci_fpcurproc;
! 1801: if (p == NULL)
! 1802: goto out;
! 1803:
! 1804: if (save) {
! 1805: alpha_pal_wrfen(1);
! 1806: savefpstate(&p->p_addr->u_pcb.pcb_fp);
! 1807: }
! 1808:
! 1809: alpha_pal_wrfen(0);
! 1810:
! 1811: p->p_addr->u_pcb.pcb_fpcpu = NULL;
! 1812: ci->ci_fpcurproc = NULL;
! 1813:
! 1814: out:
! 1815: #if defined(MULTIPROCESSOR)
! 1816: atomic_clearbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
! 1817: #endif
! 1818: return;
! 1819: }
! 1820:
! 1821: /*
! 1822: * Synchronize FP state for this process.
! 1823: */
! 1824: void
! 1825: fpusave_proc(struct proc *p, int save)
! 1826: {
! 1827: struct cpu_info *ci = curcpu();
! 1828: struct cpu_info *oci;
! 1829: #if defined(MULTIPROCESSOR)
! 1830: u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU;
! 1831: int spincount;
! 1832: #endif
! 1833:
! 1834: KDASSERT(p->p_addr != NULL);
! 1835:
! 1836: oci = p->p_addr->u_pcb.pcb_fpcpu;
! 1837: if (oci == NULL) {
! 1838: return;
! 1839: }
! 1840:
! 1841: #if defined(MULTIPROCESSOR)
! 1842: if (oci == ci) {
! 1843: KASSERT(ci->ci_fpcurproc == p);
! 1844: fpusave_cpu(ci, save);
! 1845: return;
! 1846: }
! 1847:
! 1848: KASSERT(oci->ci_fpcurproc == p);
! 1849: alpha_send_ipi(oci->ci_cpuid, ipi);
! 1850:
! 1851: spincount = 0;
! 1852: while (p->p_addr->u_pcb.pcb_fpcpu != NULL) {
! 1853: spincount++;
! 1854: delay(1000); /* XXX */
! 1855: if (spincount > 10000)
! 1856: panic("fpsave ipi didn't");
! 1857: }
! 1858: #else
! 1859: KASSERT(ci->ci_fpcurproc == p);
! 1860: fpusave_cpu(ci, save);
! 1861: #endif /* MULTIPROCESSOR */
! 1862: }
! 1863:
! 1864: int
! 1865: spl0()
! 1866: {
! 1867:
! 1868: if (ssir) {
! 1869: (void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT);
! 1870: softintr_dispatch();
! 1871: }
! 1872:
! 1873: return (alpha_pal_swpipl(ALPHA_PSL_IPL_0));
! 1874: }
! 1875:
! 1876: /*
! 1877: * The following primitives manipulate the run queues. _whichqs tells which
! 1878: * of the 32 queues _qs have processes in them. Setrunqueue puts processes
! 1879: * into queues, Remrunqueue removes them from queues. The running process is
! 1880: * on no queue, other processes are on a queue related to p->p_priority,
! 1881: * divided by 4 actually to shrink the 0-127 range of priorities into the 32
! 1882: * available queues.
! 1883: */
! 1884: /*
! 1885: * setrunqueue(p)
! 1886: * proc *p;
! 1887: *
! 1888: * Call should be made at splclock(), and p->p_stat should be SRUN.
! 1889: */
! 1890:
! 1891: /* XXXART - grmble */
! 1892: #define sched_qs qs
! 1893: #define sched_whichqs whichqs
! 1894:
! 1895: void
! 1896: setrunqueue(p)
! 1897: struct proc *p;
! 1898: {
! 1899: int bit;
! 1900:
! 1901: /* firewall: p->p_back must be NULL */
! 1902: if (p->p_back != NULL)
! 1903: panic("setrunqueue");
! 1904:
! 1905: bit = p->p_priority >> 2;
! 1906: sched_whichqs |= (1 << bit);
! 1907: p->p_forw = (struct proc *)&sched_qs[bit];
! 1908: p->p_back = sched_qs[bit].ph_rlink;
! 1909: p->p_back->p_forw = p;
! 1910: sched_qs[bit].ph_rlink = p;
! 1911: }
! 1912:
! 1913: /*
! 1914: * remrunqueue(p)
! 1915: *
! 1916: * Call should be made at splclock().
! 1917: */
! 1918: void
! 1919: remrunqueue(p)
! 1920: struct proc *p;
! 1921: {
! 1922: int bit;
! 1923:
! 1924: bit = p->p_priority >> 2;
! 1925: if ((sched_whichqs & (1 << bit)) == 0)
! 1926: panic("remrunqueue");
! 1927:
! 1928: p->p_back->p_forw = p->p_forw;
! 1929: p->p_forw->p_back = p->p_back;
! 1930: p->p_back = NULL; /* for firewall checking. */
! 1931:
! 1932: if ((struct proc *)&sched_qs[bit] == sched_qs[bit].ph_link)
! 1933: sched_whichqs &= ~(1 << bit);
! 1934: }
! 1935:
! 1936: /*
! 1937: * Wait "n" microseconds.
! 1938: */
! 1939: void
! 1940: delay(n)
! 1941: unsigned long n;
! 1942: {
! 1943: unsigned long pcc0, pcc1, curcycle, cycles, usec;
! 1944:
! 1945: if (n == 0)
! 1946: return;
! 1947:
! 1948: pcc0 = alpha_rpcc() & 0xffffffffUL;
! 1949: cycles = 0;
! 1950: usec = 0;
! 1951:
! 1952: while (usec <= n) {
! 1953: /*
! 1954: * Get the next CPU cycle count - assumes that we can not
! 1955: * have had more than one 32 bit overflow.
! 1956: */
! 1957: pcc1 = alpha_rpcc() & 0xffffffffUL;
! 1958: if (pcc1 < pcc0)
! 1959: curcycle = (pcc1 + 0x100000000UL) - pcc0;
! 1960: else
! 1961: curcycle = pcc1 - pcc0;
! 1962:
! 1963: /*
! 1964: * We now have the number of processor cycles since we
! 1965: * last checked. Add the current cycle count to the
! 1966: * running total. If it's over cycles_per_usec, increment
! 1967: * the usec counter.
! 1968: */
! 1969: cycles += curcycle;
! 1970: while (cycles > cycles_per_usec) {
! 1971: usec++;
! 1972: cycles -= cycles_per_usec;
! 1973: }
! 1974: pcc0 = pcc1;
! 1975: }
! 1976: }
! 1977:
! 1978: #if defined(COMPAT_OSF1)
! 1979: void cpu_exec_ecoff_setregs(struct proc *, struct exec_package *,
! 1980: u_long, register_t *);
! 1981:
! 1982: void
! 1983: cpu_exec_ecoff_setregs(p, epp, stack, retval)
! 1984: struct proc *p;
! 1985: struct exec_package *epp;
! 1986: u_long stack;
! 1987: register_t *retval;
! 1988: {
! 1989: struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
! 1990:
! 1991: setregs(p, epp, stack, retval);
! 1992: p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value;
! 1993: }
! 1994:
! 1995: /*
! 1996: * cpu_exec_ecoff_hook():
! 1997: * cpu-dependent ECOFF format hook for execve().
! 1998: *
! 1999: * Do any machine-dependent diddling of the exec package when doing ECOFF.
! 2000: *
! 2001: */
! 2002: int
! 2003: cpu_exec_ecoff_hook(p, epp)
! 2004: struct proc *p;
! 2005: struct exec_package *epp;
! 2006: {
! 2007: struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
! 2008: extern struct emul emul_native;
! 2009: int error;
! 2010: extern int osf1_exec_ecoff_hook(struct proc *, struct exec_package *);
! 2011:
! 2012: switch (execp->f.f_magic) {
! 2013: #ifdef COMPAT_OSF1
! 2014: case ECOFF_MAGIC_ALPHA:
! 2015: error = osf1_exec_ecoff_hook(p, epp);
! 2016: break;
! 2017: #endif
! 2018:
! 2019: case ECOFF_MAGIC_NATIVE_ALPHA:
! 2020: epp->ep_emul = &emul_native;
! 2021: error = 0;
! 2022: break;
! 2023:
! 2024: default:
! 2025: error = ENOEXEC;
! 2026: }
! 2027: return (error);
! 2028: }
! 2029: #endif
! 2030:
! 2031: int
! 2032: alpha_pa_access(pa)
! 2033: u_long pa;
! 2034: {
! 2035: int i;
! 2036:
! 2037: for (i = 0; i < mem_cluster_cnt; i++) {
! 2038: if (pa < mem_clusters[i].start)
! 2039: continue;
! 2040: if ((pa - mem_clusters[i].start) >=
! 2041: (mem_clusters[i].size & ~PAGE_MASK))
! 2042: continue;
! 2043: return (mem_clusters[i].size & PAGE_MASK); /* prot */
! 2044: }
! 2045:
! 2046: /*
! 2047: * Address is not a memory address. If we're secure, disallow
! 2048: * access. Otherwise, grant read/write.
! 2049: */
! 2050: if (securelevel > 0)
! 2051: return (VM_PROT_NONE);
! 2052: else
! 2053: return (VM_PROT_READ | VM_PROT_WRITE);
! 2054: }
! 2055:
! 2056: /* XXX XXX BEGIN XXX XXX */
! 2057: paddr_t alpha_XXX_dmamap_or; /* XXX */
! 2058: /* XXX */
! 2059: paddr_t /* XXX */
! 2060: alpha_XXX_dmamap(v) /* XXX */
! 2061: vaddr_t v; /* XXX */
! 2062: { /* XXX */
! 2063: /* XXX */
! 2064: return (vtophys(v) | alpha_XXX_dmamap_or); /* XXX */
! 2065: } /* XXX */
! 2066: /* XXX XXX END XXX XXX */
CVSweb