1*4fa86cc0Smiod /* $OpenBSD: machdep.c,v 1.148 2014/02/04 21:52:42 miod Exp $ */ 22a2685f2Sart /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ 3aed035abSart 4aed035abSart /*- 5aed035abSart * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 6aed035abSart * All rights reserved. 7aed035abSart * 8aed035abSart * This code is derived from software contributed to The NetBSD Foundation 9aed035abSart * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10aed035abSart * NASA Ames Research Center and by Chris G. Demetriou. 11aed035abSart * 12aed035abSart * Redistribution and use in source and binary forms, with or without 13aed035abSart * modification, are permitted provided that the following conditions 14aed035abSart * are met: 15aed035abSart * 1. Redistributions of source code must retain the above copyright 16aed035abSart * notice, this list of conditions and the following disclaimer. 17aed035abSart * 2. Redistributions in binary form must reproduce the above copyright 18aed035abSart * notice, this list of conditions and the following disclaimer in the 19aed035abSart * documentation and/or other materials provided with the distribution. 20aed035abSart * 21aed035abSart * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22aed035abSart * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23aed035abSart * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24aed035abSart * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25aed035abSart * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26aed035abSart * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27aed035abSart * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28aed035abSart * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29aed035abSart * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30aed035abSart * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31aed035abSart * POSSIBILITY OF SUCH DAMAGE. 32aed035abSart */ 33df930be7Sderaadt 34df930be7Sderaadt /* 35417eba8cSderaadt * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 36df930be7Sderaadt * All rights reserved. 37df930be7Sderaadt * 38df930be7Sderaadt * Author: Chris G. Demetriou 39df930be7Sderaadt * 40df930be7Sderaadt * Permission to use, copy, modify and distribute this software and 41df930be7Sderaadt * its documentation is hereby granted, provided that both the copyright 42df930be7Sderaadt * notice and this permission notice appear in all copies of the 43df930be7Sderaadt * software, derivative works or modified versions, and any portions 44df930be7Sderaadt * thereof, and that both notices appear in supporting documentation. 45df930be7Sderaadt * 46df930be7Sderaadt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 47df930be7Sderaadt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 48df930be7Sderaadt * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 49df930be7Sderaadt * 50df930be7Sderaadt * Carnegie Mellon requests users of this software to return to 51df930be7Sderaadt * 52df930be7Sderaadt * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 53df930be7Sderaadt * School of Computer Science 54df930be7Sderaadt * Carnegie Mellon University 55df930be7Sderaadt * Pittsburgh PA 15213-3890 56df930be7Sderaadt * 57df930be7Sderaadt * any improvements or extensions that they make and grant Carnegie the 58df930be7Sderaadt * rights to redistribute these changes. 59df930be7Sderaadt */ 60df930be7Sderaadt 61df930be7Sderaadt #include <sys/param.h> 62df930be7Sderaadt #include <sys/systm.h> 63df930be7Sderaadt #include <sys/signalvar.h> 64df930be7Sderaadt #include <sys/kernel.h> 65df930be7Sderaadt #include <sys/proc.h> 667d9ca166Sderaadt #include <sys/socket.h> 672a2685f2Sart #include <sys/sched.h> 68df930be7Sderaadt #include <sys/buf.h> 69df930be7Sderaadt #include <sys/reboot.h> 70417eba8cSderaadt #include <sys/device.h> 71df930be7Sderaadt #include <sys/conf.h> 72df930be7Sderaadt #include <sys/file.h> 73d66eba84Sart #include <sys/timeout.h> 74df930be7Sderaadt #include <sys/malloc.h> 75df930be7Sderaadt #include <sys/mbuf.h> 76df930be7Sderaadt #include <sys/msgbuf.h> 77df930be7Sderaadt #include <sys/ioctl.h> 78df930be7Sderaadt #include <sys/tty.h> 79df930be7Sderaadt #include <sys/user.h> 80df930be7Sderaadt #include <sys/exec.h> 81df930be7Sderaadt #include <sys/sysctl.h> 8250ce9ee0Sniklas #include <sys/core.h> 8350ce9ee0Sniklas #include <sys/kcore.h> 847d9ca166Sderaadt 857d9ca166Sderaadt #include <net/if.h> 867d9ca166Sderaadt #include <uvm/uvm.h> 877d9ca166Sderaadt 8850ce9ee0Sniklas #include <machine/kcore.h> 89433075b6Spvalchev #ifndef NO_IEEE 90433075b6Spvalchev #include <machine/fpu.h> 91433075b6Spvalchev #endif 921f87e7b7Sart #include <sys/timetc.h> 93df930be7Sderaadt 94df930be7Sderaadt #include <sys/mount.h> 95df930be7Sderaadt #include <sys/syscallargs.h> 96df930be7Sderaadt 97df930be7Sderaadt #include <dev/cons.h> 98df930be7Sderaadt 9950ce9ee0Sniklas #include <machine/autoconf.h> 100df930be7Sderaadt #include <machine/cpu.h> 101df930be7Sderaadt #include <machine/reg.h> 102df930be7Sderaadt #include <machine/rpb.h> 103df930be7Sderaadt #include <machine/prom.h> 1043a630e3fSniklas #include <machine/cpuconf.h> 105433075b6Spvalchev #ifndef NO_IEEE 106433075b6Spvalchev #include <machine/ieeefp.h> 107433075b6Spvalchev #endif 108df930be7Sderaadt 10945e5a1a0Sart #include <dev/pci/pcivar.h> 11045e5a1a0Sart 11112f8bbedSniklas #ifdef DDB 11212f8bbedSniklas #include <machine/db_machdep.h> 11312f8bbedSniklas #include <ddb/db_extern.h> 11421c23d01Smiod #include <ddb/db_interface.h> 11512f8bbedSniklas #endif 11612f8bbedSniklas 117a072164aSmiod #include "ioasic.h" 118a072164aSmiod 119a072164aSmiod #if NIOASIC > 0 120a072164aSmiod #include <machine/tc_machdep.h> 121a072164aSmiod #include <dev/tc/tcreg.h> 122a072164aSmiod #include <dev/tc/ioasicvar.h> 123a072164aSmiod #endif 124a072164aSmiod 12565c47ec0Sderaadt #ifdef BROKEN_PROM_CONSOLE 12665c47ec0Sderaadt extern void sio_intr_shutdown(void); 12765c47ec0Sderaadt #endif 12865c47ec0Sderaadt 129c4071fd1Smillert int cpu_dump(void); 130c4071fd1Smillert int cpu_dumpsize(void); 131c4071fd1Smillert u_long cpu_dump_mempagecnt(void); 132c4071fd1Smillert void dumpsys(void); 133c4071fd1Smillert void identifycpu(void); 134c4071fd1Smillert void regdump(struct trapframe *framep); 135c4071fd1Smillert void printregs(struct reg *); 136df930be7Sderaadt 137b426ab7bSthib struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; 138b426ab7bSthib struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; 139b426ab7bSthib struct uvm_constraint_range *uvm_md_constraints[] = { 140b426ab7bSthib &isa_constraint, 141b426ab7bSthib NULL 142b426ab7bSthib }; 143b426ab7bSthib 144ab8e80c5Sart struct vm_map *exec_map = NULL; 145ab8e80c5Sart struct vm_map *phys_map = NULL; 146aed035abSart 147c72644a3Sderaadt /* 148c72644a3Sderaadt * safepri is a safe priority for sleep to set for a spin-wait 149c72644a3Sderaadt * during autoconfiguration or after a panic. 150c72644a3Sderaadt */ 151c72644a3Sderaadt int safepri = 0; 152c72644a3Sderaadt 15327626149Smatthieu #ifdef APERTURE 15427626149Smatthieu #ifdef INSECURE 15527626149Smatthieu int allowaperture = 1; 15627626149Smatthieu #else 15727626149Smatthieu int allowaperture = 0; 15827626149Smatthieu #endif 15927626149Smatthieu #endif 16027626149Smatthieu 161df930be7Sderaadt int totalphysmem; /* total amount of physical memory in system */ 16274652a67Sniklas int physmem; /* physical mem used by OpenBSD + some rsvd */ 163df930be7Sderaadt int resvmem; /* amount of memory reserved for PROM */ 164df930be7Sderaadt int unusedmem; /* amount of memory for OS that we don't use */ 165df930be7Sderaadt int unknownmem; /* amount of memory with an unknown use */ 166df930be7Sderaadt 167df930be7Sderaadt int cputype; /* system type, from the RPB */ 168df930be7Sderaadt 1692a2685f2Sart int bootdev_debug = 0; /* patchable, or from DDB */ 1702a2685f2Sart 171df930be7Sderaadt /* the following is used externally (sysctl_hw) */ 172aed035abSart char machine[] = MACHINE; /* from <machine/param.h> */ 173417eba8cSderaadt char cpu_model[128]; 174df930be7Sderaadt 175df930be7Sderaadt struct user *proc0paddr; 176df930be7Sderaadt 177df930be7Sderaadt /* Number of machine cycles per microsecond */ 178df930be7Sderaadt u_int64_t cycles_per_usec; 179df930be7Sderaadt 180aed035abSart struct bootinfo_kernel bootinfo; 181aed035abSart 182b1560ceaSmiod struct consdev *cn_tab; 183b1560ceaSmiod 184aed035abSart /* For built-in TCDS */ 185aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500) 186aed035abSart u_int8_t dec_3000_scsiid[2], dec_3000_scsifast[2]; 187aed035abSart #endif 188aed035abSart 189aed035abSart struct platform platform; 190417eba8cSderaadt 191417eba8cSderaadt /* for cpu_sysctl() */ 19250ce9ee0Sniklas int alpha_unaligned_print = 1; /* warn about unaligned accesses */ 19350ce9ee0Sniklas int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ 194881c1eabSart int alpha_unaligned_sigbus = 1; /* SIGBUS on fixed-up accesses */ 195433075b6Spvalchev #ifndef NO_IEEE 196433075b6Spvalchev int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */ 197433075b6Spvalchev #endif 198a072164aSmiod #if NIOASIC > 0 199a072164aSmiod int alpha_led_blink = 0; 200a072164aSmiod #endif 20150ce9ee0Sniklas 202b3cee53eSmartin /* used by hw_sysctl */ 203b3cee53eSmartin extern char *hw_serial; 204b3cee53eSmartin 205aed035abSart /* 206aed035abSart * XXX This should be dynamically sized, but we have the chicken-egg problem! 207aed035abSart * XXX it should also be larger than it is, because not all of the mddt 208aed035abSart * XXX clusters end up being used for VM. 209aed035abSart */ 210aed035abSart phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; /* low size bits overloaded */ 211aed035abSart int mem_cluster_cnt; 212aed035abSart 2133a630e3fSniklas void 214dd3e8537Smiod alpha_init(unused, ptb, bim, bip, biv) 215dd3e8537Smiod u_long unused; 216df930be7Sderaadt u_long ptb; /* PFN of current level 1 page table */ 217aed035abSart u_long bim; /* bootinfo magic */ 218aed035abSart u_long bip; /* bootinfo pointer */ 219aed035abSart u_long biv; /* bootinfo version */ 220df930be7Sderaadt { 221aed035abSart extern char kernel_text[], _end[]; 222df930be7Sderaadt struct mddt *mddtp; 223aed035abSart struct mddt_cluster *memc; 224df930be7Sderaadt int i, mddtweird; 225aed035abSart struct vm_physseg *vps; 226aed035abSart vaddr_t kernstart, kernend; 227aed035abSart paddr_t kernstartpfn, kernendpfn, pfn0, pfn1; 228df930be7Sderaadt char *p; 2292a2685f2Sart const char *bootinfo_msg; 230aed035abSart const struct cpuinit *c; 231aed035abSart extern caddr_t esym; 232aed035abSart struct cpu_info *ci; 233aed035abSart cpuid_t cpu_id; 234df930be7Sderaadt 235aed035abSart /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ 236f3914c62Sniklas 237df930be7Sderaadt /* 238aed035abSart * Turn off interrupts (not mchecks) and floating point. 239df930be7Sderaadt * Make sure the instruction and data streams are consistent. 240df930be7Sderaadt */ 241aed035abSart (void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); 24250ce9ee0Sniklas alpha_pal_wrfen(0); 24350ce9ee0Sniklas ALPHA_TBIA(); 24450ce9ee0Sniklas alpha_pal_imb(); 245df930be7Sderaadt 246c62181b1Sbrad /* Initialize the SCB. */ 247c62181b1Sbrad scb_init(); 248c62181b1Sbrad 249aed035abSart cpu_id = cpu_number(); 250aed035abSart 251aed035abSart #if defined(MULTIPROCESSOR) 252df930be7Sderaadt /* 253aed035abSart * Set our SysValue to the address of our cpu_info structure. 254aed035abSart * Secondary processors do this in their spinup trampoline. 255df930be7Sderaadt */ 25621c23d01Smiod alpha_pal_wrval((u_long)&cpu_info_primary); 25721c23d01Smiod cpu_info[cpu_id] = &cpu_info_primary; 258aed035abSart #endif 259aed035abSart 260aed035abSart ci = curcpu(); 261aed035abSart ci->ci_cpuid = cpu_id; 262aed035abSart 263aed035abSart /* 264aed035abSart * Get critical system information (if possible, from the 265aed035abSart * information provided by the boot program). 266aed035abSart */ 267aed035abSart bootinfo_msg = NULL; 268aed035abSart if (bim == BOOTINFO_MAGIC) { 269aed035abSart if (biv == 0) { /* backward compat */ 270aed035abSart biv = *(u_long *)bip; 271aed035abSart bip += 8; 272aed035abSart } 273aed035abSart switch (biv) { 274aed035abSart case 1: { 275aed035abSart struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip; 276aed035abSart 277aed035abSart bootinfo.ssym = v1p->ssym; 278aed035abSart bootinfo.esym = v1p->esym; 279aed035abSart /* hwrpb may not be provided by boot block in v1 */ 280aed035abSart if (v1p->hwrpb != NULL) { 281aed035abSart bootinfo.hwrpb_phys = 282aed035abSart ((struct rpb *)v1p->hwrpb)->rpb_phys; 283aed035abSart bootinfo.hwrpb_size = v1p->hwrpbsize; 284aed035abSart } else { 285aed035abSart bootinfo.hwrpb_phys = 286aed035abSart ((struct rpb *)HWRPB_ADDR)->rpb_phys; 287aed035abSart bootinfo.hwrpb_size = 288aed035abSart ((struct rpb *)HWRPB_ADDR)->rpb_size; 289aed035abSart } 290aed035abSart bcopy(v1p->boot_flags, bootinfo.boot_flags, 291aed035abSart min(sizeof v1p->boot_flags, 292aed035abSart sizeof bootinfo.boot_flags)); 293aed035abSart bcopy(v1p->booted_kernel, bootinfo.booted_kernel, 294aed035abSart min(sizeof v1p->booted_kernel, 295aed035abSart sizeof bootinfo.booted_kernel)); 296aed035abSart /* booted dev not provided in bootinfo */ 297aed035abSart init_prom_interface((struct rpb *) 298aed035abSart ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys)); 299aed035abSart prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, 300aed035abSart sizeof bootinfo.booted_dev); 301aed035abSart break; 302aed035abSart } 303aed035abSart default: 304aed035abSart bootinfo_msg = "unknown bootinfo version"; 305aed035abSart goto nobootinfo; 306aed035abSart } 307aed035abSart } else { 308aed035abSart bootinfo_msg = "boot program did not pass bootinfo"; 309aed035abSart nobootinfo: 310aed035abSart bootinfo.ssym = (u_long)_end; 311aed035abSart bootinfo.esym = (u_long)_end; 312aed035abSart bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys; 313aed035abSart bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size; 314aed035abSart init_prom_interface((struct rpb *)HWRPB_ADDR); 315aed035abSart prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags, 316aed035abSart sizeof bootinfo.boot_flags); 317aed035abSart prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel, 318aed035abSart sizeof bootinfo.booted_kernel); 319aed035abSart prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, 320aed035abSart sizeof bootinfo.booted_dev); 321aed035abSart } 322aed035abSart 323aed035abSart esym = (caddr_t)bootinfo.esym; 324aed035abSart /* 325aed035abSart * Initialize the kernel's mapping of the RPB. It's needed for 326aed035abSart * lots of things. 327aed035abSart */ 328aed035abSart hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys); 329aed035abSart 330aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500) 331aed035abSart if (hwrpb->rpb_type == ST_DEC_3000_300 || 332aed035abSart hwrpb->rpb_type == ST_DEC_3000_500) { 333aed035abSart prom_getenv(PROM_E_SCSIID, dec_3000_scsiid, 334aed035abSart sizeof(dec_3000_scsiid)); 335aed035abSart prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast, 336aed035abSart sizeof(dec_3000_scsifast)); 337aed035abSart } 338aed035abSart #endif 339df930be7Sderaadt 340df930be7Sderaadt /* 341df930be7Sderaadt * Remember how many cycles there are per microsecond, 342df930be7Sderaadt * so that we can use delay(). Round up, for safety. 343df930be7Sderaadt */ 344df930be7Sderaadt cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000; 345df930be7Sderaadt 346df930be7Sderaadt /* 3479e71c994Saaron * Initialize the (temporary) bootstrap console interface, so 348aed035abSart * we can use printf until the VM system starts being setup. 349aed035abSart * The real console is initialized before then. 350df930be7Sderaadt */ 351aed035abSart init_bootstrap_console(); 352aed035abSart 353aed035abSart /* OUTPUT NOW ALLOWED */ 354aed035abSart 355aed035abSart /* delayed from above */ 356aed035abSart if (bootinfo_msg) 357aed035abSart printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n", 358aed035abSart bootinfo_msg, bim, bip, biv); 359aed035abSart 360aed035abSart /* Initialize the trap vectors on the primary processor. */ 361aed035abSart trap_init(); 362df930be7Sderaadt 363df930be7Sderaadt /* 364aed035abSart * Find out what hardware we're on, and do basic initialization. 365df930be7Sderaadt */ 366aed035abSart cputype = hwrpb->rpb_type; 367aed035abSart if (cputype < 0) { 368aed035abSart /* 369aed035abSart * At least some white-box systems have SRM which 370aed035abSart * reports a systype that's the negative of their 371aed035abSart * blue-box counterpart. 372aed035abSart */ 373aed035abSart cputype = -cputype; 374aed035abSart } 375aed035abSart c = platform_lookup(cputype); 376aed035abSart if (c == NULL) { 377aed035abSart platform_not_supported(); 378aed035abSart /* NOTREACHED */ 379aed035abSart } 380aed035abSart (*c->init)(); 381094fa01fSderaadt strlcpy(cpu_model, platform.model, sizeof cpu_model); 38250ce9ee0Sniklas 38350ce9ee0Sniklas /* 3849e71c994Saaron * Initialize the real console, so that the bootstrap console is 385aed035abSart * no longer necessary. 38650ce9ee0Sniklas */ 387aed035abSart (*platform.cons_init)(); 388aed035abSart 389a55851f4Sderaadt #if 0 390aed035abSart /* Paranoid sanity checking */ 391aed035abSart 392aed035abSart assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami()); 393aed035abSart 394aed035abSart /* 395aed035abSart * On single-CPU systypes, the primary should always be CPU 0, 396aed035abSart * except on Alpha 8200 systems where the CPU id is related 397aed035abSart * to the VID, which is related to the Turbo Laser node id. 398aed035abSart */ 399aed035abSart if (cputype != ST_DEC_21000) 400aed035abSart assert(hwrpb->rpb_primary_cpu_id == 0); 401aed035abSart #endif 402aed035abSart 403aed035abSart /* NO MORE FIRMWARE ACCESS ALLOWED */ 404aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 405aed035abSart /* 406aed035abSart * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and 407aed035abSart * XXX pmap_uses_prom_console() evaluates to non-zero.) 408aed035abSart */ 409aed035abSart #endif 410aed035abSart 411cfcdef40Smiod #ifndef SMALL_KERNEL 412cfcdef40Smiod /* 413cfcdef40Smiod * If we run on a BWX-capable processor, override cpu_switch 414cfcdef40Smiod * with a faster version. 415cfcdef40Smiod * We do this now because the kernel text might be mapped 416cfcdef40Smiod * read-only eventually (although this is not the case at the moment). 417cfcdef40Smiod */ 418cfcdef40Smiod if (alpha_implver() >= ALPHA_IMPLVER_EV5) { 419cfcdef40Smiod if (~alpha_amask(ALPHA_AMASK_BWX) != 0) { 420cfcdef40Smiod extern vaddr_t __bwx_switch0, __bwx_switch1, 421cfcdef40Smiod __bwx_switch2, __bwx_switch3; 422cfcdef40Smiod u_int32_t *dst, *src, *end; 423cfcdef40Smiod 424cfcdef40Smiod src = (u_int32_t *)&__bwx_switch2; 425cfcdef40Smiod end = (u_int32_t *)&__bwx_switch3; 426cfcdef40Smiod dst = (u_int32_t *)&__bwx_switch0; 427cfcdef40Smiod while (src != end) 428cfcdef40Smiod *dst++ = *src++; 429cfcdef40Smiod src = (u_int32_t *)&__bwx_switch1; 430cfcdef40Smiod end = (u_int32_t *)&__bwx_switch2; 431cfcdef40Smiod while (src != end) 432cfcdef40Smiod *dst++ = *src++; 433cfcdef40Smiod } 434cfcdef40Smiod } 435cfcdef40Smiod #endif 436cfcdef40Smiod 437aed035abSart /* 438aed035abSart * find out this system's page size 439aed035abSart */ 44073b9fe7cSart if ((uvmexp.pagesize = hwrpb->rpb_page_size) != 8192) 44173b9fe7cSart panic("page size %d != 8192?!", uvmexp.pagesize); 442aed035abSart 443aed035abSart uvm_setpagesize(); 444aed035abSart 445aed035abSart /* 446aed035abSart * Find the beginning and end of the kernel (and leave a 447aed035abSart * bit of space before the beginning for the bootstrap 448aed035abSart * stack). 449aed035abSart */ 450aed035abSart kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE; 451aed035abSart kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym); 452aed035abSart 453aed035abSart kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart)); 454aed035abSart kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend)); 455df930be7Sderaadt 456df930be7Sderaadt /* 457df930be7Sderaadt * Find out how much memory is available, by looking at 458df930be7Sderaadt * the memory cluster descriptors. This also tries to do 459df930be7Sderaadt * its best to detect things things that have never been seen 460df930be7Sderaadt * before... 461df930be7Sderaadt */ 462df930be7Sderaadt mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off); 463df930be7Sderaadt 464aed035abSart /* MDDT SANITY CHECKING */ 465df930be7Sderaadt mddtweird = 0; 466aed035abSart if (mddtp->mddt_cluster_cnt < 2) { 467df930be7Sderaadt mddtweird = 1; 468aed035abSart printf("WARNING: weird number of mem clusters: %lu\n", 469aed035abSart mddtp->mddt_cluster_cnt); 470df930be7Sderaadt } 471df930be7Sderaadt 472aed035abSart #if 0 473aed035abSart printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt); 474aed035abSart #endif 475df930be7Sderaadt 476aed035abSart for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 477aed035abSart memc = &mddtp->mddt_clusters[i]; 478aed035abSart #if 0 479aed035abSart printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i, 480aed035abSart memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage); 481aed035abSart #endif 482aed035abSart totalphysmem += memc->mddt_pg_cnt; 483aed035abSart if (mem_cluster_cnt < VM_PHYSSEG_MAX) { /* XXX */ 484aed035abSart mem_clusters[mem_cluster_cnt].start = 485aed035abSart ptoa(memc->mddt_pfn); 486aed035abSart mem_clusters[mem_cluster_cnt].size = 487aed035abSart ptoa(memc->mddt_pg_cnt); 488aed035abSart if (memc->mddt_usage & MDDT_mbz || 489aed035abSart memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */ 490aed035abSart memc->mddt_usage & MDDT_PALCODE) 491aed035abSart mem_clusters[mem_cluster_cnt].size |= 492aed035abSart VM_PROT_READ; 493aed035abSart else 494aed035abSart mem_clusters[mem_cluster_cnt].size |= 495aed035abSart VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; 496aed035abSart mem_cluster_cnt++; 497ee2d823aSmiod } /* XXX else print something! */ 498aed035abSart 499aed035abSart if (memc->mddt_usage & MDDT_mbz) { 500aed035abSart mddtweird = 1; 501aed035abSart printf("WARNING: mem cluster %d has weird " 502aed035abSart "usage 0x%lx\n", i, memc->mddt_usage); 503aed035abSart unknownmem += memc->mddt_pg_cnt; 504aed035abSart continue; 505aed035abSart } 506aed035abSart if (memc->mddt_usage & MDDT_NONVOLATILE) { 507aed035abSart /* XXX should handle these... */ 508aed035abSart printf("WARNING: skipping non-volatile mem " 509aed035abSart "cluster %d\n", i); 510aed035abSart unusedmem += memc->mddt_pg_cnt; 511aed035abSart continue; 512aed035abSart } 513aed035abSart if (memc->mddt_usage & MDDT_PALCODE) { 514aed035abSart resvmem += memc->mddt_pg_cnt; 515aed035abSart continue; 516aed035abSart } 517aed035abSart 518aed035abSart /* 519aed035abSart * We have a memory cluster available for system 520aed035abSart * software use. We must determine if this cluster 521aed035abSart * holds the kernel. 522aed035abSart */ 523aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 524aed035abSart /* 525aed035abSart * XXX If the kernel uses the PROM console, we only use the 526aed035abSart * XXX memory after the kernel in the first system segment, 527aed035abSart * XXX to avoid clobbering prom mapping, data, etc. 528aed035abSart */ 529aed035abSart if (!pmap_uses_prom_console() || physmem == 0) { 530aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 531aed035abSart physmem += memc->mddt_pg_cnt; 532aed035abSart pfn0 = memc->mddt_pfn; 533aed035abSart pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt; 534aed035abSart if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) { 535aed035abSart /* 536aed035abSart * Must compute the location of the kernel 537aed035abSart * within the segment. 538aed035abSart */ 539aed035abSart #if 0 540aed035abSart printf("Cluster %d contains kernel\n", i); 541aed035abSart #endif 542aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 543aed035abSart if (!pmap_uses_prom_console()) { 544aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 545aed035abSart if (pfn0 < kernstartpfn) { 546aed035abSart /* 547aed035abSart * There is a chunk before the kernel. 548aed035abSart */ 549aed035abSart #if 0 550aed035abSart printf("Loading chunk before kernel: " 551aed035abSart "0x%lx / 0x%lx\n", pfn0, kernstartpfn); 552aed035abSart #endif 553aed035abSart uvm_page_physload(pfn0, kernstartpfn, 5542ce3b4a8Soga pfn0, kernstartpfn, 0); 555aed035abSart } 556aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 557aed035abSart } 558aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 559aed035abSart if (kernendpfn < pfn1) { 560aed035abSart /* 561aed035abSart * There is a chunk after the kernel. 562aed035abSart */ 563aed035abSart #if 0 564aed035abSart printf("Loading chunk after kernel: " 565aed035abSart "0x%lx / 0x%lx\n", kernendpfn, pfn1); 566aed035abSart #endif 567aed035abSart uvm_page_physload(kernendpfn, pfn1, 5682ce3b4a8Soga kernendpfn, pfn1, 0); 569aed035abSart } 570aed035abSart } else { 571aed035abSart /* 572aed035abSart * Just load this cluster as one chunk. 573aed035abSart */ 574aed035abSart #if 0 575aed035abSart printf("Loading cluster %d: 0x%lx / 0x%lx\n", i, 576aed035abSart pfn0, pfn1); 577aed035abSart #endif 5782ce3b4a8Soga uvm_page_physload(pfn0, pfn1, pfn0, pfn1, 0); 579aed035abSart } 580aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 581aed035abSart } 582aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 583aed035abSart } 584aed035abSart 585a37778bcSderaadt #ifdef DEBUG 586aed035abSart /* 587aed035abSart * Dump out the MDDT if it looks odd... 588aed035abSart */ 589df930be7Sderaadt if (mddtweird) { 590df930be7Sderaadt printf("\n"); 591df930be7Sderaadt printf("complete memory cluster information:\n"); 592df930be7Sderaadt for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 593df930be7Sderaadt printf("mddt %d:\n", i); 594df930be7Sderaadt printf("\tpfn %lx\n", 595df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pfn); 596df930be7Sderaadt printf("\tcnt %lx\n", 597df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_cnt); 598df930be7Sderaadt printf("\ttest %lx\n", 599df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_test); 600df930be7Sderaadt printf("\tbva %lx\n", 601df930be7Sderaadt mddtp->mddt_clusters[i].mddt_v_bitaddr); 602df930be7Sderaadt printf("\tbpa %lx\n", 603df930be7Sderaadt mddtp->mddt_clusters[i].mddt_p_bitaddr); 604df930be7Sderaadt printf("\tbcksum %lx\n", 605df930be7Sderaadt mddtp->mddt_clusters[i].mddt_bit_cksum); 606df930be7Sderaadt printf("\tusage %lx\n", 607df930be7Sderaadt mddtp->mddt_clusters[i].mddt_usage); 608df930be7Sderaadt } 609df930be7Sderaadt printf("\n"); 610df930be7Sderaadt } 611a37778bcSderaadt #endif 612df930be7Sderaadt 613df930be7Sderaadt if (totalphysmem == 0) 614df930be7Sderaadt panic("can't happen: system seems to have no memory!"); 615df930be7Sderaadt #if 0 616f46637d1Sderaadt printf("totalphysmem = %u\n", totalphysmem); 617f46637d1Sderaadt printf("physmem = %u\n", physmem); 618df930be7Sderaadt printf("resvmem = %d\n", resvmem); 619df930be7Sderaadt printf("unusedmem = %d\n", unusedmem); 620df930be7Sderaadt printf("unknownmem = %d\n", unknownmem); 621df930be7Sderaadt #endif 622df930be7Sderaadt 623df930be7Sderaadt /* 624aed035abSart * Initialize error message buffer (at end of core). 625df930be7Sderaadt */ 626aed035abSart { 627aed035abSart vsize_t sz = (vsize_t)round_page(MSGBUFSIZE); 628aed035abSart vsize_t reqsz = sz; 629df930be7Sderaadt 630aed035abSart vps = &vm_physmem[vm_nphysseg - 1]; 631e1da84e1Salex 632aed035abSart /* shrink so that it'll fit in the last segment */ 633aed035abSart if ((vps->avail_end - vps->avail_start) < atop(sz)) 634aed035abSart sz = ptoa(vps->avail_end - vps->avail_start); 635aed035abSart 636aed035abSart vps->end -= atop(sz); 637aed035abSart vps->avail_end -= atop(sz); 638aed035abSart initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz); 639aed035abSart 640aed035abSart /* Remove the last segment if it now has no pages. */ 641aed035abSart if (vps->start == vps->end) 642aed035abSart vm_nphysseg--; 643aed035abSart 644aed035abSart /* warn if the message buffer had to be shrunk */ 645aed035abSart if (sz != reqsz) 646aed035abSart printf("WARNING: %ld bytes not available for msgbuf " 647aed035abSart "in last cluster (%ld used)\n", reqsz, sz); 648aed035abSart 649aed035abSart } 650aed035abSart 651df930be7Sderaadt /* 652df930be7Sderaadt * Init mapping for u page(s) for proc 0 653df930be7Sderaadt */ 654aed035abSart proc0.p_addr = proc0paddr = 655aed035abSart (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL); 656df930be7Sderaadt 657df930be7Sderaadt /* 658df930be7Sderaadt * Initialize the virtual memory system, and set the 659df930be7Sderaadt * page table base register in proc 0's PCB. 660df930be7Sderaadt */ 661aed035abSart pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), 662aed035abSart hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt); 663df930be7Sderaadt 664df930be7Sderaadt /* 665df930be7Sderaadt * Initialize the rest of proc 0's PCB, and cache its physical 666df930be7Sderaadt * address. 667df930be7Sderaadt */ 668df930be7Sderaadt proc0.p_md.md_pcbpaddr = 669aed035abSart (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb); 670df930be7Sderaadt 671df930be7Sderaadt /* 672df930be7Sderaadt * Set the kernel sp, reserving space for an (empty) trapframe, 673df930be7Sderaadt * and make proc0's trapframe pointer point to it for sanity. 674df930be7Sderaadt */ 67550ce9ee0Sniklas proc0paddr->u_pcb.pcb_hw.apcb_ksp = 676df930be7Sderaadt (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe); 67774652a67Sniklas proc0.p_md.md_tf = 67874652a67Sniklas (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp; 67950ce9ee0Sniklas 680aed035abSart /* 681aed035abSart * Initialize the primary CPU's idle PCB to proc0's. In a 682aed035abSart * MULTIPROCESSOR configuration, each CPU will later get 683aed035abSart * its own idle PCB when autoconfiguration runs. 684aed035abSart */ 685aed035abSart ci->ci_idle_pcb = &proc0paddr->u_pcb; 686aed035abSart ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr; 687df930be7Sderaadt 688df930be7Sderaadt /* 689df930be7Sderaadt * Look at arguments passed to us and compute boothowto. 690df930be7Sderaadt */ 691417eba8cSderaadt 692df930be7Sderaadt #ifdef KADB 693df930be7Sderaadt boothowto |= RB_KDB; 694df930be7Sderaadt #endif 695aed035abSart for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { 696417eba8cSderaadt /* 697417eba8cSderaadt * Note that we'd really like to differentiate case here, 698417eba8cSderaadt * but the Alpha AXP Architecture Reference Manual 699417eba8cSderaadt * says that we shouldn't. 700417eba8cSderaadt */ 701df930be7Sderaadt switch (*p) { 702371c77f5Smartin case 'a': /* Ignore */ 703417eba8cSderaadt case 'A': 704df930be7Sderaadt break; 705df930be7Sderaadt 70612f8bbedSniklas case 'b': /* Enter DDB as soon as the console is initialised */ 70712f8bbedSniklas case 'B': 70812f8bbedSniklas boothowto |= RB_KDB; 70912f8bbedSniklas break; 71012f8bbedSniklas 71150ce9ee0Sniklas case 'c': /* enter user kernel configuration */ 71250ce9ee0Sniklas case 'C': 71350ce9ee0Sniklas boothowto |= RB_CONFIG; 71450ce9ee0Sniklas break; 71550ce9ee0Sniklas 71650ce9ee0Sniklas #ifdef DEBUG 71750ce9ee0Sniklas case 'd': /* crash dump immediately after autoconfig */ 71850ce9ee0Sniklas case 'D': 71950ce9ee0Sniklas boothowto |= RB_DUMP; 72050ce9ee0Sniklas break; 72150ce9ee0Sniklas #endif 72250ce9ee0Sniklas 72350ce9ee0Sniklas case 'h': /* always halt, never reboot */ 72450ce9ee0Sniklas case 'H': 72550ce9ee0Sniklas boothowto |= RB_HALT; 726df930be7Sderaadt break; 727df930be7Sderaadt 728417eba8cSderaadt #if 0 729417eba8cSderaadt case 'm': /* mini root present in memory */ 730417eba8cSderaadt case 'M': 731417eba8cSderaadt boothowto |= RB_MINIROOT; 732417eba8cSderaadt break; 733417eba8cSderaadt #endif 73450ce9ee0Sniklas 73550ce9ee0Sniklas case 'n': /* askname */ 73650ce9ee0Sniklas case 'N': 73750ce9ee0Sniklas boothowto |= RB_ASKNAME; 73850ce9ee0Sniklas break; 739aed035abSart 740371c77f5Smartin case 's': /* single-user */ 741aed035abSart case 'S': 742aed035abSart boothowto |= RB_SINGLE; 743aed035abSart break; 744aed035abSart 745aed035abSart case '-': 746aed035abSart /* 747aed035abSart * Just ignore this. It's not required, but it's 748aed035abSart * common for it to be passed regardless. 749aed035abSart */ 750aed035abSart break; 751aed035abSart 752aed035abSart default: 753aed035abSart printf("Unrecognized boot flag '%c'.\n", *p); 754aed035abSart break; 755df930be7Sderaadt } 756df930be7Sderaadt } 757df930be7Sderaadt 758aed035abSart 759df930be7Sderaadt /* 760df930be7Sderaadt * Figure out the number of cpus in the box, from RPB fields. 761df930be7Sderaadt * Really. We mean it. 762df930be7Sderaadt */ 76331326ec3Smiod for (ncpusfound = 0, i = 0; i < hwrpb->rpb_pcs_cnt; i++) { 764df930be7Sderaadt struct pcs *pcsp; 765df930be7Sderaadt 766aed035abSart pcsp = LOCATE_PCS(hwrpb, i); 767df930be7Sderaadt if ((pcsp->pcs_flags & PCS_PP) != 0) 76831326ec3Smiod ncpusfound++; 769df930be7Sderaadt } 770aed035abSart 771aed035abSart /* 772aed035abSart * Initialize debuggers, and break into them if appropriate. 773aed035abSart */ 774aed035abSart #ifdef DDB 77521c23d01Smiod db_machine_init(); 776aed035abSart ddb_init(); 777aed035abSart 778aed035abSart if (boothowto & RB_KDB) 779aed035abSart Debugger(); 780aed035abSart #endif 781aed035abSart #ifdef KGDB 782aed035abSart if (boothowto & RB_KDB) 783aed035abSart kgdb_connect(0); 784aed035abSart #endif 785aed035abSart /* 786aed035abSart * Figure out our clock frequency, from RPB fields. 787aed035abSart */ 788aed035abSart hz = hwrpb->rpb_intr_freq >> 12; 789aed035abSart if (!(60 <= hz && hz <= 10240)) { 790aed035abSart #ifdef DIAGNOSTIC 791aed035abSart printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n", 792aed035abSart hwrpb->rpb_intr_freq, hz); 793aed035abSart #endif 794dd3e8537Smiod hz = 1024; 795aed035abSart } 796aed035abSart } 797aed035abSart 798417eba8cSderaadt void 799df930be7Sderaadt consinit() 800df930be7Sderaadt { 801aed035abSart 802aed035abSart /* 803aed035abSart * Everything related to console initialization is done 804aed035abSart * in alpha_init(). 805aed035abSart */ 806aed035abSart #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE) 807aed035abSart printf("consinit: %susing prom console\n", 808aed035abSart pmap_uses_prom_console() ? "" : "not "); 80912f8bbedSniklas #endif 810df930be7Sderaadt } 811df930be7Sderaadt 812417eba8cSderaadt void 813df930be7Sderaadt cpu_startup() 814df930be7Sderaadt { 815aed035abSart vaddr_t minaddr, maxaddr; 81650ce9ee0Sniklas #if defined(DEBUG) 817df930be7Sderaadt extern int pmapdebug; 818df930be7Sderaadt int opmapdebug = pmapdebug; 819df930be7Sderaadt 820df930be7Sderaadt pmapdebug = 0; 821df930be7Sderaadt #endif 822df930be7Sderaadt 823df930be7Sderaadt /* 824df930be7Sderaadt * Good {morning,afternoon,evening,night}. 825df930be7Sderaadt */ 826df930be7Sderaadt printf(version); 827df930be7Sderaadt identifycpu(); 828701cd583Smiod printf("real mem = %lu (%luMB)\n", ptoa((psize_t)totalphysmem), 829701cd583Smiod ptoa((psize_t)totalphysmem) / 1024 / 1024); 830701cd583Smiod printf("rsvd mem = %lu (%luMB)\n", ptoa((psize_t)resvmem), 831701cd583Smiod ptoa((psize_t)resvmem) / 1024 / 1024); 832aed035abSart if (unusedmem) { 833701cd583Smiod printf("WARNING: unused memory = %lu (%luMB)\n", 834701cd583Smiod ptoa((psize_t)unusedmem), 835701cd583Smiod ptoa((psize_t)unusedmem) / 1024 / 1024); 836aed035abSart } 837aed035abSart if (unknownmem) { 838701cd583Smiod printf("WARNING: %lu (%luMB) of memory with unknown purpose\n", 839701cd583Smiod ptoa((psize_t)unknownmem), 840701cd583Smiod ptoa((psize_t)unknownmem) / 1024 / 1024); 841aed035abSart } 842df930be7Sderaadt 843df930be7Sderaadt /* 844df930be7Sderaadt * Allocate a submap for exec arguments. This map effectively 845df930be7Sderaadt * limits the number of processes exec'ing at any time. 846df930be7Sderaadt */ 8477c10a71dSdrahn minaddr = vm_map_min(kernel_map); 848aed035abSart exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 849aed035abSart 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 850df930be7Sderaadt 851df930be7Sderaadt /* 852df930be7Sderaadt * Allocate a submap for physio 853df930be7Sderaadt */ 854aed035abSart phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 855aed035abSart VM_PHYS_SIZE, 0, FALSE, NULL); 856df930be7Sderaadt 85750ce9ee0Sniklas #if defined(DEBUG) 858df930be7Sderaadt pmapdebug = opmapdebug; 859df930be7Sderaadt #endif 860701cd583Smiod printf("avail mem = %lu (%luMB)\n", ptoa((psize_t)uvmexp.free), 861701cd583Smiod ptoa((psize_t)uvmexp.free) / 1024 / 1024); 862aed035abSart #if 0 863aed035abSart { 864aed035abSart extern u_long pmap_pages_stolen; 865aed035abSart 866aed035abSart printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE); 867aed035abSart } 868aed035abSart #endif 869df930be7Sderaadt 870df930be7Sderaadt /* 871df930be7Sderaadt * Set up buffers, so they can be used to read disk labels. 872df930be7Sderaadt */ 873df930be7Sderaadt bufinit(); 874df930be7Sderaadt 875df930be7Sderaadt /* 876df930be7Sderaadt * Configure the system. 877df930be7Sderaadt */ 87841033391Sderaadt if (boothowto & RB_CONFIG) { 87941033391Sderaadt #ifdef BOOT_CONFIG 88041033391Sderaadt user_config(); 88141033391Sderaadt #else 88241033391Sderaadt printf("kernel does not support -c; continuing..\n"); 88341033391Sderaadt #endif 88441033391Sderaadt } 88550ce9ee0Sniklas 88650ce9ee0Sniklas /* 887aed035abSart * Set up the HWPCB so that it's safe to configure secondary 888aed035abSart * CPUs. 88950ce9ee0Sniklas */ 890aed035abSart hwrpb_primary_init(); 891aed035abSart } 892aed035abSart 893aed035abSart /* 894aed035abSart * Retrieve the platform name from the DSR. 895aed035abSart */ 896aed035abSart const char * 897aed035abSart alpha_dsr_sysname() 898aed035abSart { 899aed035abSart struct dsrdb *dsr; 900aed035abSart const char *sysname; 901aed035abSart 902aed035abSart /* 903aed035abSart * DSR does not exist on early HWRPB versions. 904aed035abSart */ 905aed035abSart if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS) 906aed035abSart return (NULL); 907aed035abSart 908aed035abSart dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off); 909aed035abSart sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off + 910aed035abSart sizeof(u_int64_t))); 911aed035abSart return (sysname); 912aed035abSart } 913aed035abSart 914aed035abSart /* 915aed035abSart * Lookup the system specified system variation in the provided table, 916aed035abSart * returning the model string on match. 917aed035abSart */ 918aed035abSart const char * 919aed035abSart alpha_variation_name(variation, avtp) 920aed035abSart u_int64_t variation; 921aed035abSart const struct alpha_variation_table *avtp; 922aed035abSart { 923aed035abSart int i; 924aed035abSart 925aed035abSart for (i = 0; avtp[i].avt_model != NULL; i++) 926aed035abSart if (avtp[i].avt_variation == variation) 927aed035abSart return (avtp[i].avt_model); 928aed035abSart return (NULL); 929aed035abSart } 930aed035abSart 931aed035abSart /* 932aed035abSart * Generate a default platform name based for unknown system variations. 933aed035abSart */ 934aed035abSart const char * 935aed035abSart alpha_unknown_sysname() 936aed035abSart { 937aed035abSart static char s[128]; /* safe size */ 938aed035abSart 939d5eb2d9aSderaadt snprintf(s, sizeof s, "%s family, unknown model variation 0x%lx", 940aed035abSart platform.family, hwrpb->rpb_variation & SV_ST_MASK); 941aed035abSart return ((const char *)s); 942df930be7Sderaadt } 943df930be7Sderaadt 94450ce9ee0Sniklas void 945df930be7Sderaadt identifycpu() 946df930be7Sderaadt { 947aed035abSart char *s; 948b3cee53eSmartin int slen; 949df930be7Sderaadt 950df930be7Sderaadt /* 951df930be7Sderaadt * print out CPU identification information. 952df930be7Sderaadt */ 953aed035abSart printf("%s", cpu_model); 954aed035abSart for(s = cpu_model; *s; ++s) 955aed035abSart if(strncasecmp(s, "MHz", 3) == 0) 956aed035abSart goto skipMHz; 957aed035abSart printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000); 958aed035abSart skipMHz: 959b3cee53eSmartin /* fill in hw_serial if a serial number is known */ 960b3cee53eSmartin slen = strlen(hwrpb->rpb_ssn) + 1; 961b3cee53eSmartin if (slen > 1) { 962b3cee53eSmartin hw_serial = malloc(slen, M_SYSCTL, M_NOWAIT); 963b3cee53eSmartin if (hw_serial) 964b3cee53eSmartin strlcpy(hw_serial, (char *)hwrpb->rpb_ssn, slen); 965b3cee53eSmartin } 966b3cee53eSmartin 967aed035abSart printf("\n"); 96850ce9ee0Sniklas printf("%ld byte page size, %d processor%s.\n", 96931326ec3Smiod hwrpb->rpb_page_size, ncpusfound, ncpusfound == 1 ? "" : "s"); 970df930be7Sderaadt #if 0 971b3cee53eSmartin /* this is not particularly useful! */ 972df930be7Sderaadt printf("variation: 0x%lx, revision 0x%lx\n", 973df930be7Sderaadt hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision); 974df930be7Sderaadt #endif 975df930be7Sderaadt } 976df930be7Sderaadt 977df930be7Sderaadt int waittime = -1; 978df930be7Sderaadt struct pcb dumppcb; 979df930be7Sderaadt 980417eba8cSderaadt void 981aed035abSart boot(howto) 982df930be7Sderaadt int howto; 983df930be7Sderaadt { 984aed035abSart #if defined(MULTIPROCESSOR) 98521c23d01Smiod u_long wait_mask; 98621c23d01Smiod int i; 987aed035abSart #endif 988aed035abSart 989df930be7Sderaadt /* If system is cold, just halt. */ 990df930be7Sderaadt if (cold) { 991c9ad5066Stom /* (Unless the user explicitly asked for reboot.) */ 992c9ad5066Stom if ((howto & RB_USERREQ) == 0) 993df930be7Sderaadt howto |= RB_HALT; 994df930be7Sderaadt goto haltsys; 995df930be7Sderaadt } 996df930be7Sderaadt 99750ce9ee0Sniklas /* If "always halt" was specified as a boot flag, obey. */ 99850ce9ee0Sniklas if ((boothowto & RB_HALT) != 0) 99950ce9ee0Sniklas howto |= RB_HALT; 100050ce9ee0Sniklas 1001df930be7Sderaadt boothowto = howto; 1002df930be7Sderaadt if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 1003df930be7Sderaadt waittime = 0; 1004df930be7Sderaadt vfs_shutdown(); 1005df930be7Sderaadt /* 1006df930be7Sderaadt * If we've been adjusting the clock, the todr 10072417125dSmiod * will be out of synch; adjust it now unless 10082417125dSmiod * the system has been sitting in ddb. 1009df930be7Sderaadt */ 10102417125dSmiod if ((howto & RB_TIMEBAD) == 0) { 1011df930be7Sderaadt resettodr(); 10122417125dSmiod } else { 10132417125dSmiod printf("WARNING: not updating battery clock\n"); 10142417125dSmiod } 1015df930be7Sderaadt } 10167d9ca166Sderaadt if_downall(); 1017df930be7Sderaadt 1018c98e8b29Sderaadt uvm_shutdown(); 1019c98e8b29Sderaadt splhigh(); /* Disable interrupts. */ 1020df930be7Sderaadt 102121c23d01Smiod #if defined(MULTIPROCESSOR) 102221c23d01Smiod /* 102321c23d01Smiod * Halt all other CPUs. 102421c23d01Smiod */ 102521c23d01Smiod wait_mask = (1UL << hwrpb->rpb_primary_cpu_id); 102621c23d01Smiod alpha_broadcast_ipi(ALPHA_IPI_HALT); 102721c23d01Smiod 102821c23d01Smiod /* Ensure any CPUs paused by DDB resume execution so they can halt */ 102921c23d01Smiod cpus_paused = 0; 103021c23d01Smiod 103121c23d01Smiod for (i = 0; i < 10000; i++) { 103221c23d01Smiod alpha_mb(); 103321c23d01Smiod if (cpus_running == wait_mask) 103421c23d01Smiod break; 103521c23d01Smiod delay(1000); 103621c23d01Smiod } 103721c23d01Smiod alpha_mb(); 103821c23d01Smiod if (cpus_running != wait_mask) 103921c23d01Smiod printf("WARNING: Unable to halt secondary CPUs (0x%lx)\n", 104021c23d01Smiod cpus_running); 104121c23d01Smiod #endif 104221c23d01Smiod 1043df930be7Sderaadt /* If rebooting and a dump is requested do it. */ 104450ce9ee0Sniklas if (howto & RB_DUMP) 1045df930be7Sderaadt dumpsys(); 1046df930be7Sderaadt 104734fbf6deSderaadt haltsys: 1048df930be7Sderaadt doshutdownhooks(); 10497313f802Smiod if (!TAILQ_EMPTY(&alldevs)) 10501e4b376cSderaadt config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); 1051df930be7Sderaadt 105265c47ec0Sderaadt #ifdef BROKEN_PROM_CONSOLE 105365c47ec0Sderaadt sio_intr_shutdown(NULL); 105465c47ec0Sderaadt #endif 105565c47ec0Sderaadt 1056df930be7Sderaadt #ifdef BOOTKEY 1057df930be7Sderaadt printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot"); 1058aed035abSart cnpollc(1); /* for proper keyboard command handling */ 1059df930be7Sderaadt cngetc(); 1060aed035abSart cnpollc(0); 1061df930be7Sderaadt printf("\n"); 1062df930be7Sderaadt #endif 1063df930be7Sderaadt 1064aed035abSart /* Finally, powerdown/halt/reboot the system. */ 1065aed035abSart if ((howto & RB_POWERDOWN) == RB_POWERDOWN && 1066aed035abSart platform.powerdown != NULL) { 1067aed035abSart (*platform.powerdown)(); 1068aed035abSart printf("WARNING: powerdown failed!\n"); 1069aed035abSart } 1070df930be7Sderaadt printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 1071df930be7Sderaadt prom_halt(howto & RB_HALT); 1072df930be7Sderaadt /*NOTREACHED*/ 1073df930be7Sderaadt } 1074df930be7Sderaadt 1075df930be7Sderaadt /* 1076df930be7Sderaadt * These variables are needed by /sbin/savecore 1077df930be7Sderaadt */ 1078df930be7Sderaadt u_long dumpmag = 0x8fca0101; /* magic number */ 1079df930be7Sderaadt int dumpsize = 0; /* pages */ 1080df930be7Sderaadt long dumplo = 0; /* blocks */ 1081df930be7Sderaadt 1082df930be7Sderaadt /* 108350ce9ee0Sniklas * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. 108450ce9ee0Sniklas */ 108550ce9ee0Sniklas int 108650ce9ee0Sniklas cpu_dumpsize() 108750ce9ee0Sniklas { 108850ce9ee0Sniklas int size; 108950ce9ee0Sniklas 1090aed035abSart size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) + 1091aed035abSart ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); 109250ce9ee0Sniklas if (roundup(size, dbtob(1)) != dbtob(1)) 109350ce9ee0Sniklas return -1; 109450ce9ee0Sniklas 109550ce9ee0Sniklas return (1); 109650ce9ee0Sniklas } 109750ce9ee0Sniklas 109850ce9ee0Sniklas /* 1099aed035abSart * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped. 1100aed035abSart */ 1101aed035abSart u_long 1102aed035abSart cpu_dump_mempagecnt() 1103aed035abSart { 1104aed035abSart u_long i, n; 1105aed035abSart 1106aed035abSart n = 0; 1107aed035abSart for (i = 0; i < mem_cluster_cnt; i++) 1108aed035abSart n += atop(mem_clusters[i].size); 1109aed035abSart return (n); 1110aed035abSart } 1111aed035abSart 1112aed035abSart /* 111350ce9ee0Sniklas * cpu_dump: dump machine-dependent kernel core dump headers. 111450ce9ee0Sniklas */ 111550ce9ee0Sniklas int 111650ce9ee0Sniklas cpu_dump() 111750ce9ee0Sniklas { 11181abdbfdeSderaadt int (*dump)(dev_t, daddr_t, caddr_t, size_t); 1119aed035abSart char buf[dbtob(1)]; 112050ce9ee0Sniklas kcore_seg_t *segp; 112150ce9ee0Sniklas cpu_kcore_hdr_t *cpuhdrp; 1122aed035abSart phys_ram_seg_t *memsegp; 1123aed035abSart int i; 112450ce9ee0Sniklas 112550ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 112650ce9ee0Sniklas 1127aed035abSart bzero(buf, sizeof buf); 112850ce9ee0Sniklas segp = (kcore_seg_t *)buf; 1129aed035abSart cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; 1130aed035abSart memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) + 1131aed035abSart ALIGN(sizeof(*cpuhdrp))]; 113250ce9ee0Sniklas 113350ce9ee0Sniklas /* 113450ce9ee0Sniklas * Generate a segment header. 113550ce9ee0Sniklas */ 113650ce9ee0Sniklas CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 113750ce9ee0Sniklas segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); 113850ce9ee0Sniklas 113950ce9ee0Sniklas /* 1140aed035abSart * Add the machine-dependent header info. 114150ce9ee0Sniklas */ 1142aed035abSart cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map); 114350ce9ee0Sniklas cpuhdrp->page_size = PAGE_SIZE; 1144aed035abSart cpuhdrp->nmemsegs = mem_cluster_cnt; 1145aed035abSart 1146aed035abSart /* 1147aed035abSart * Fill in the memory segment descriptors. 1148aed035abSart */ 1149aed035abSart for (i = 0; i < mem_cluster_cnt; i++) { 1150aed035abSart memsegp[i].start = mem_clusters[i].start; 1151aed035abSart memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK; 1152aed035abSart } 115350ce9ee0Sniklas 115450ce9ee0Sniklas return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1))); 115550ce9ee0Sniklas } 115650ce9ee0Sniklas 115750ce9ee0Sniklas /* 1158aed035abSart * This is called by main to set dumplo and dumpsize. 1159194dd68bSbrad * Dumps always skip the first PAGE_SIZE of disk space 1160df930be7Sderaadt * in case there might be a disk label stored there. 1161df930be7Sderaadt * If there is extra space, put dump at the end to 1162df930be7Sderaadt * reduce the chance that swapping trashes it. 1163df930be7Sderaadt */ 1164df930be7Sderaadt void 1165e17d3b39Sderaadt dumpconf(void) 1166df930be7Sderaadt { 116750ce9ee0Sniklas int nblks, dumpblks; /* size of dump area */ 1168df930be7Sderaadt 1169e17d3b39Sderaadt if (dumpdev == NODEV || 1170e17d3b39Sderaadt (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) 1171e17d3b39Sderaadt return; 1172df930be7Sderaadt if (nblks <= ctod(1)) 1173e17d3b39Sderaadt return; 117450ce9ee0Sniklas 117550ce9ee0Sniklas dumpblks = cpu_dumpsize(); 117650ce9ee0Sniklas if (dumpblks < 0) 1177e17d3b39Sderaadt return; 1178aed035abSart dumpblks += ctod(cpu_dump_mempagecnt()); 117950ce9ee0Sniklas 118050ce9ee0Sniklas /* If dump won't fit (incl. room for possible label), punt. */ 118150ce9ee0Sniklas if (dumpblks > (nblks - ctod(1))) 1182e17d3b39Sderaadt return; 118350ce9ee0Sniklas 118450ce9ee0Sniklas /* Put dump at end of partition */ 118550ce9ee0Sniklas dumplo = nblks - dumpblks; 118650ce9ee0Sniklas 118750ce9ee0Sniklas /* dumpsize is in page units, and doesn't include headers. */ 1188aed035abSart dumpsize = cpu_dump_mempagecnt(); 1189df930be7Sderaadt } 1190df930be7Sderaadt 1191df930be7Sderaadt /* 119250ce9ee0Sniklas * Dump the kernel's image to the swap partition. 1193df930be7Sderaadt */ 1194194dd68bSbrad #define BYTES_PER_DUMP PAGE_SIZE 119550ce9ee0Sniklas 1196df930be7Sderaadt void 1197df930be7Sderaadt dumpsys() 1198df930be7Sderaadt { 1199aed035abSart u_long totalbytesleft, bytes, i, n, memcl; 1200aed035abSart u_long maddr; 1201aed035abSart int psize; 12021abdbfdeSderaadt daddr_t blkno; 12031abdbfdeSderaadt int (*dump)(dev_t, daddr_t, caddr_t, size_t); 120450ce9ee0Sniklas int error; 1205067cbd75Sderaadt extern int msgbufmapped; 1206df930be7Sderaadt 120750ce9ee0Sniklas /* Save registers. */ 120850ce9ee0Sniklas savectx(&dumppcb); 120950ce9ee0Sniklas 121050ce9ee0Sniklas msgbufmapped = 0; /* don't record dump msgs in msgbuf */ 1211df930be7Sderaadt if (dumpdev == NODEV) 1212df930be7Sderaadt return; 121350ce9ee0Sniklas 121450ce9ee0Sniklas /* 121550ce9ee0Sniklas * For dumps during autoconfiguration, 121650ce9ee0Sniklas * if dump device has already configured... 121750ce9ee0Sniklas */ 1218df930be7Sderaadt if (dumpsize == 0) 121950ce9ee0Sniklas dumpconf(); 122050ce9ee0Sniklas if (dumplo <= 0) { 1221aed035abSart printf("\ndump to dev %u,%u not possible\n", major(dumpdev), 1222aed035abSart minor(dumpdev)); 1223df930be7Sderaadt return; 1224df930be7Sderaadt } 1225aed035abSart printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), 1226aed035abSart minor(dumpdev), dumplo); 1227df930be7Sderaadt 12281b720b8bSmiod #ifdef UVM_SWAP_ENCRYPT 12291b720b8bSmiod uvm_swap_finicrypt_all(); 12301b720b8bSmiod #endif 12311b720b8bSmiod 123250ce9ee0Sniklas psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 1233df930be7Sderaadt printf("dump "); 123450ce9ee0Sniklas if (psize == -1) { 123550ce9ee0Sniklas printf("area unavailable\n"); 123650ce9ee0Sniklas return; 123750ce9ee0Sniklas } 123850ce9ee0Sniklas 123950ce9ee0Sniklas /* XXX should purge all outstanding keystrokes. */ 124050ce9ee0Sniklas 124150ce9ee0Sniklas if ((error = cpu_dump()) != 0) 124250ce9ee0Sniklas goto err; 124350ce9ee0Sniklas 1244aed035abSart totalbytesleft = ptoa(cpu_dump_mempagecnt()); 124550ce9ee0Sniklas blkno = dumplo + cpu_dumpsize(); 124650ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 124750ce9ee0Sniklas error = 0; 1248aed035abSart 1249aed035abSart for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { 1250aed035abSart maddr = mem_clusters[memcl].start; 1251aed035abSart bytes = mem_clusters[memcl].size & ~PAGE_MASK; 1252aed035abSart 1253aed035abSart for (i = 0; i < bytes; i += n, totalbytesleft -= n) { 125450ce9ee0Sniklas 125550ce9ee0Sniklas /* Print out how many MBs we to go. */ 1256aed035abSart if ((totalbytesleft % (1024*1024)) == 0) 1257aed035abSart printf("%ld ", totalbytesleft / (1024 * 1024)); 125850ce9ee0Sniklas 125950ce9ee0Sniklas /* Limit size for next transfer. */ 1260aed035abSart n = bytes - i; 126150ce9ee0Sniklas if (n > BYTES_PER_DUMP) 126250ce9ee0Sniklas n = BYTES_PER_DUMP; 126350ce9ee0Sniklas 126450ce9ee0Sniklas error = (*dump)(dumpdev, blkno, 126550ce9ee0Sniklas (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n); 126650ce9ee0Sniklas if (error) 1267aed035abSart goto err; 126850ce9ee0Sniklas maddr += n; 126950ce9ee0Sniklas blkno += btodb(n); /* XXX? */ 127050ce9ee0Sniklas 127150ce9ee0Sniklas /* XXX should look for keystrokes, to cancel. */ 127250ce9ee0Sniklas } 1273aed035abSart } 127450ce9ee0Sniklas 127550ce9ee0Sniklas err: 127650ce9ee0Sniklas switch (error) { 1277a37778bcSderaadt #ifdef DEBUG 1278df930be7Sderaadt case ENXIO: 1279df930be7Sderaadt printf("device bad\n"); 1280df930be7Sderaadt break; 1281df930be7Sderaadt 1282df930be7Sderaadt case EFAULT: 1283df930be7Sderaadt printf("device not ready\n"); 1284df930be7Sderaadt break; 1285df930be7Sderaadt 1286df930be7Sderaadt case EINVAL: 1287df930be7Sderaadt printf("area improper\n"); 1288df930be7Sderaadt break; 1289df930be7Sderaadt 1290df930be7Sderaadt case EIO: 1291df930be7Sderaadt printf("i/o error\n"); 1292df930be7Sderaadt break; 1293df930be7Sderaadt 1294df930be7Sderaadt case EINTR: 1295df930be7Sderaadt printf("aborted from console\n"); 1296df930be7Sderaadt break; 1297a37778bcSderaadt #endif /* DEBUG */ 129850ce9ee0Sniklas case 0: 1299df930be7Sderaadt printf("succeeded\n"); 1300df930be7Sderaadt break; 130150ce9ee0Sniklas 130250ce9ee0Sniklas default: 130350ce9ee0Sniklas printf("error %d\n", error); 130450ce9ee0Sniklas break; 1305df930be7Sderaadt } 1306df930be7Sderaadt printf("\n\n"); 1307df930be7Sderaadt delay(1000); 1308df930be7Sderaadt } 1309df930be7Sderaadt 1310df930be7Sderaadt void 1311df930be7Sderaadt frametoreg(framep, regp) 1312df930be7Sderaadt struct trapframe *framep; 1313df930be7Sderaadt struct reg *regp; 1314df930be7Sderaadt { 1315df930be7Sderaadt 1316df930be7Sderaadt regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0]; 1317df930be7Sderaadt regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0]; 1318df930be7Sderaadt regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1]; 1319df930be7Sderaadt regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2]; 1320df930be7Sderaadt regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3]; 1321df930be7Sderaadt regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4]; 1322df930be7Sderaadt regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5]; 1323df930be7Sderaadt regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6]; 1324df930be7Sderaadt regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7]; 1325df930be7Sderaadt regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0]; 1326df930be7Sderaadt regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1]; 1327df930be7Sderaadt regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2]; 1328df930be7Sderaadt regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3]; 1329df930be7Sderaadt regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; 1330df930be7Sderaadt regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; 1331df930be7Sderaadt regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; 133250ce9ee0Sniklas regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; 133350ce9ee0Sniklas regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; 133450ce9ee0Sniklas regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; 1335df930be7Sderaadt regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; 1336df930be7Sderaadt regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; 1337df930be7Sderaadt regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; 1338df930be7Sderaadt regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8]; 1339df930be7Sderaadt regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9]; 1340df930be7Sderaadt regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10]; 1341df930be7Sderaadt regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11]; 1342df930be7Sderaadt regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; 1343df930be7Sderaadt regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; 1344df930be7Sderaadt regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; 134550ce9ee0Sniklas regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; 134650ce9ee0Sniklas /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ 1347df930be7Sderaadt regp->r_regs[R_ZERO] = 0; 1348df930be7Sderaadt } 1349df930be7Sderaadt 1350df930be7Sderaadt void 1351df930be7Sderaadt regtoframe(regp, framep) 1352df930be7Sderaadt struct reg *regp; 1353df930be7Sderaadt struct trapframe *framep; 1354df930be7Sderaadt { 1355df930be7Sderaadt 1356df930be7Sderaadt framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0]; 1357df930be7Sderaadt framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0]; 1358df930be7Sderaadt framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1]; 1359df930be7Sderaadt framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2]; 1360df930be7Sderaadt framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3]; 1361df930be7Sderaadt framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4]; 1362df930be7Sderaadt framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5]; 1363df930be7Sderaadt framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6]; 1364df930be7Sderaadt framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7]; 1365df930be7Sderaadt framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0]; 1366df930be7Sderaadt framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1]; 1367df930be7Sderaadt framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2]; 1368df930be7Sderaadt framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3]; 1369df930be7Sderaadt framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; 1370df930be7Sderaadt framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; 1371df930be7Sderaadt framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; 137250ce9ee0Sniklas framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; 137350ce9ee0Sniklas framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; 137450ce9ee0Sniklas framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; 1375df930be7Sderaadt framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; 1376df930be7Sderaadt framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; 1377df930be7Sderaadt framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; 1378df930be7Sderaadt framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8]; 1379df930be7Sderaadt framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9]; 1380df930be7Sderaadt framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10]; 1381df930be7Sderaadt framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11]; 1382df930be7Sderaadt framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; 1383df930be7Sderaadt framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; 1384df930be7Sderaadt framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; 138550ce9ee0Sniklas framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; 138650ce9ee0Sniklas /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ 1387df930be7Sderaadt /* ??? = regp->r_regs[R_ZERO]; */ 1388df930be7Sderaadt } 1389df930be7Sderaadt 1390df930be7Sderaadt void 1391df930be7Sderaadt printregs(regp) 1392df930be7Sderaadt struct reg *regp; 1393df930be7Sderaadt { 1394df930be7Sderaadt int i; 1395df930be7Sderaadt 1396df930be7Sderaadt for (i = 0; i < 32; i++) 1397df930be7Sderaadt printf("R%d:\t0x%016lx%s", i, regp->r_regs[i], 1398df930be7Sderaadt i & 1 ? "\n" : "\t"); 1399df930be7Sderaadt } 1400df930be7Sderaadt 1401df930be7Sderaadt void 1402df930be7Sderaadt regdump(framep) 1403df930be7Sderaadt struct trapframe *framep; 1404df930be7Sderaadt { 1405df930be7Sderaadt struct reg reg; 1406df930be7Sderaadt 1407df930be7Sderaadt frametoreg(framep, ®); 140850ce9ee0Sniklas reg.r_regs[R_SP] = alpha_pal_rdusp(); 140950ce9ee0Sniklas 1410df930be7Sderaadt printf("REGISTERS:\n"); 1411df930be7Sderaadt printregs(®); 1412df930be7Sderaadt } 1413df930be7Sderaadt 1414df930be7Sderaadt #ifdef DEBUG 1415df930be7Sderaadt int sigdebug = 0; 141672830333Sokan pid_t sigpid = 0; 1417df930be7Sderaadt #define SDB_FOLLOW 0x01 1418df930be7Sderaadt #define SDB_KSTACK 0x02 1419df930be7Sderaadt #endif 1420df930be7Sderaadt 1421df930be7Sderaadt /* 1422df930be7Sderaadt * Send an interrupt to process. 1423df930be7Sderaadt */ 1424df930be7Sderaadt void 14255e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val) 1426df930be7Sderaadt sig_t catcher; 1427df930be7Sderaadt int sig, mask; 1428df930be7Sderaadt u_long code; 14295e1760a6Sderaadt int type; 14305e1760a6Sderaadt union sigval val; 1431df930be7Sderaadt { 1432df930be7Sderaadt struct proc *p = curproc; 1433df930be7Sderaadt struct sigcontext *scp, ksc; 1434e7e08221Smiod struct fpreg *fpregs = (struct fpreg *)&ksc.sc_fpregs; 1435df930be7Sderaadt struct trapframe *frame; 1436df930be7Sderaadt struct sigacts *psp = p->p_sigacts; 14371eaa59e7Sguenther unsigned long oldsp; 14381eaa59e7Sguenther int fsize, rndfsize, kscsize; 14392bf9c155Sderaadt siginfo_t *sip, ksi; 1440df930be7Sderaadt 14411eaa59e7Sguenther oldsp = alpha_pal_rdusp(); 1442df930be7Sderaadt frame = p->p_md.md_tf; 1443df930be7Sderaadt fsize = sizeof ksc; 1444df930be7Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 14452bf9c155Sderaadt kscsize = rndfsize; 14462bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 14472bf9c155Sderaadt fsize += sizeof ksi; 14482bf9c155Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 14492bf9c155Sderaadt } 145074652a67Sniklas 1451df930be7Sderaadt /* 1452df930be7Sderaadt * Allocate and validate space for the signal handler 1453df930be7Sderaadt * context. Note that if the stack is in P0 space, the 1454aed035abSart * call to uvm_grow() is a nop, and the useracc() check 1455df930be7Sderaadt * will fail if the process has not already allocated 1456df930be7Sderaadt * the space with a `brk'. 1457df930be7Sderaadt */ 14581eaa59e7Sguenther if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 14591eaa59e7Sguenther !sigonstack(oldsp) && (psp->ps_sigonstack & sigmask(sig))) 14602725daddSguenther scp = (struct sigcontext *)(p->p_sigstk.ss_sp + 14612725daddSguenther p->p_sigstk.ss_size - rndfsize); 14621eaa59e7Sguenther else 14631eaa59e7Sguenther scp = (struct sigcontext *)(oldsp - rndfsize); 146476d52da2Smartin if ((u_long)scp <= USRSTACK - ptoa(p->p_vmspace->vm_ssize)) 1465aed035abSart (void)uvm_grow(p, (u_long)scp); 1466df930be7Sderaadt #ifdef DEBUG 1467df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 146850ce9ee0Sniklas printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, 14691eaa59e7Sguenther sig, &ksc, scp); 1470df930be7Sderaadt #endif 1471df930be7Sderaadt 1472df930be7Sderaadt /* 1473df930be7Sderaadt * Build the signal context to be used by sigreturn. 1474df930be7Sderaadt */ 14751eaa59e7Sguenther bzero(&ksc, sizeof(ksc)); 1476df930be7Sderaadt ksc.sc_mask = mask; 147750ce9ee0Sniklas ksc.sc_pc = frame->tf_regs[FRAME_PC]; 147850ce9ee0Sniklas ksc.sc_ps = frame->tf_regs[FRAME_PS]; 1479df930be7Sderaadt 1480df930be7Sderaadt /* copy the registers. */ 1481df930be7Sderaadt frametoreg(frame, (struct reg *)ksc.sc_regs); 1482df930be7Sderaadt ksc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ 14831eaa59e7Sguenther ksc.sc_regs[R_SP] = oldsp; 1484df930be7Sderaadt 1485df930be7Sderaadt /* save the floating-point state, if necessary, then copy it. */ 1486433075b6Spvalchev if (p->p_addr->u_pcb.pcb_fpcpu != NULL) 1487433075b6Spvalchev fpusave_proc(p, 1); 1488df930be7Sderaadt ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED; 1489e7e08221Smiod memcpy(/*ksc.sc_*/fpregs, &p->p_addr->u_pcb.pcb_fp, 1490df930be7Sderaadt sizeof(struct fpreg)); 1491433075b6Spvalchev #ifndef NO_IEEE 1492433075b6Spvalchev ksc.sc_fp_control = alpha_read_fp_c(p); 1493433075b6Spvalchev #else 1494433075b6Spvalchev ksc.sc_fp_control = 0; 1495433075b6Spvalchev #endif 1496433075b6Spvalchev memset(ksc.sc_reserved, 0, sizeof ksc.sc_reserved); /* XXX */ 1497433075b6Spvalchev memset(ksc.sc_xxx, 0, sizeof ksc.sc_xxx); /* XXX */ 1498df930be7Sderaadt 14992bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 15002bf9c155Sderaadt initsiginfo(&ksi, sig, code, type, val); 15012bf9c155Sderaadt sip = (void *)scp + kscsize; 1502679ebc41Smiod if (copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize) != 0) 1503679ebc41Smiod goto trash; 1504aa540fb8Sart } else 1505aa540fb8Sart sip = NULL; 15062bf9c155Sderaadt 1507df930be7Sderaadt /* 1508df930be7Sderaadt * copy the frame out to userland. 1509df930be7Sderaadt */ 1510679ebc41Smiod if (copyout((caddr_t)&ksc, (caddr_t)scp, kscsize) != 0) { 1511679ebc41Smiod trash: 1512679ebc41Smiod #ifdef DEBUG 1513679ebc41Smiod if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1514679ebc41Smiod printf("sendsig(%d): copyout failed on sig %d\n", 1515679ebc41Smiod p->p_pid, sig); 1516679ebc41Smiod #endif 1517679ebc41Smiod /* 1518679ebc41Smiod * Process has trashed its stack; give it an illegal 1519679ebc41Smiod * instruction to halt it in its tracks. 1520679ebc41Smiod */ 152186fd84b3Smiod sigexit(p, SIGILL); 152286fd84b3Smiod /* NOTREACHED */ 1523679ebc41Smiod } 1524df930be7Sderaadt #ifdef DEBUG 1525df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 152650ce9ee0Sniklas printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig, 1527df930be7Sderaadt scp, code); 1528df930be7Sderaadt #endif 1529df930be7Sderaadt 1530df930be7Sderaadt /* 1531df930be7Sderaadt * Set up the registers to return to sigcode. 1532df930be7Sderaadt */ 15334a5480feSart frame->tf_regs[FRAME_PC] = p->p_sigcode; 153450ce9ee0Sniklas frame->tf_regs[FRAME_A0] = sig; 1535aa540fb8Sart frame->tf_regs[FRAME_A1] = (u_int64_t)sip; 153650ce9ee0Sniklas frame->tf_regs[FRAME_A2] = (u_int64_t)scp; 1537df930be7Sderaadt frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */ 153850ce9ee0Sniklas alpha_pal_wrusp((unsigned long)scp); 1539df930be7Sderaadt 1540df930be7Sderaadt #ifdef DEBUG 1541df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1542df930be7Sderaadt printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, 154350ce9ee0Sniklas frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]); 1544df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1545df930be7Sderaadt printf("sendsig(%d): sig %d returns\n", 1546df930be7Sderaadt p->p_pid, sig); 1547df930be7Sderaadt #endif 1548df930be7Sderaadt } 1549df930be7Sderaadt 1550df930be7Sderaadt /* 1551df930be7Sderaadt * System call to cleanup state after a signal 1552df930be7Sderaadt * has been taken. Reset signal mask and 1553df930be7Sderaadt * stack state from context left by sendsig (above). 1554df930be7Sderaadt * Return to previous pc and psl as specified by 1555df930be7Sderaadt * context left by sendsig. Check carefully to 1556df930be7Sderaadt * make sure that the user has not modified the 1557125cd19fSderaadt * psl to gain improper privileges or to cause 1558df930be7Sderaadt * a machine fault. 1559df930be7Sderaadt */ 1560df930be7Sderaadt /* ARGSUSED */ 1561df930be7Sderaadt int 1562df930be7Sderaadt sys_sigreturn(p, v, retval) 1563df930be7Sderaadt struct proc *p; 1564df930be7Sderaadt void *v; 1565df930be7Sderaadt register_t *retval; 1566df930be7Sderaadt { 1567df930be7Sderaadt struct sys_sigreturn_args /* { 1568df930be7Sderaadt syscallarg(struct sigcontext *) sigcntxp; 1569df930be7Sderaadt } */ *uap = v; 1570aa540fb8Sart struct sigcontext ksc; 1571e7e08221Smiod struct fpreg *fpregs = (struct fpreg *)&ksc.sc_fpregs; 157260959295Smartin #ifdef DEBUG 157360959295Smartin struct sigcontext *scp; 157460959295Smartin #endif 1575aa540fb8Sart int error; 1576df930be7Sderaadt 1577df930be7Sderaadt #ifdef DEBUG 1578df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 157950ce9ee0Sniklas printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 1580df930be7Sderaadt #endif 1581df930be7Sderaadt 1582df930be7Sderaadt /* 1583df930be7Sderaadt * Test and fetch the context structure. 1584df930be7Sderaadt * We grab it all at once for speed. 1585df930be7Sderaadt */ 1586aa540fb8Sart if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0) 1587aa540fb8Sart return (error); 1588df930be7Sderaadt 1589df930be7Sderaadt if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */ 1590df930be7Sderaadt return (EINVAL); 1591df930be7Sderaadt /* 1592df930be7Sderaadt * Restore the user-supplied information 1593df930be7Sderaadt */ 1594df930be7Sderaadt p->p_sigmask = ksc.sc_mask &~ sigcantmask; 1595df930be7Sderaadt 159650ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc; 159750ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PS] = 159850ce9ee0Sniklas (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; 1599df930be7Sderaadt 1600df930be7Sderaadt regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf); 160150ce9ee0Sniklas alpha_pal_wrusp(ksc.sc_regs[R_SP]); 1602df930be7Sderaadt 1603df930be7Sderaadt /* XXX ksc.sc_ownedfp ? */ 1604433075b6Spvalchev if (p->p_addr->u_pcb.pcb_fpcpu != NULL) 1605433075b6Spvalchev fpusave_proc(p, 0); 1606e7e08221Smiod memcpy(&p->p_addr->u_pcb.pcb_fp, /*ksc.sc_*/fpregs, 1607df930be7Sderaadt sizeof(struct fpreg)); 1608433075b6Spvalchev #ifndef NO_IEEE 1609433075b6Spvalchev p->p_addr->u_pcb.pcb_fp.fpr_cr = ksc.sc_fpcr; 1610433075b6Spvalchev p->p_md.md_flags = ksc.sc_fp_control & MDP_FP_C; 1611433075b6Spvalchev #endif 1612df930be7Sderaadt 1613df930be7Sderaadt #ifdef DEBUG 1614df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1615df930be7Sderaadt printf("sigreturn(%d): returns\n", p->p_pid); 1616df930be7Sderaadt #endif 1617df930be7Sderaadt return (EJUSTRETURN); 1618df930be7Sderaadt } 1619df930be7Sderaadt 1620df930be7Sderaadt /* 1621df930be7Sderaadt * machine dependent system variables. 1622df930be7Sderaadt */ 162350ce9ee0Sniklas int 1624df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 1625df930be7Sderaadt int *name; 1626df930be7Sderaadt u_int namelen; 1627df930be7Sderaadt void *oldp; 1628df930be7Sderaadt size_t *oldlenp; 1629df930be7Sderaadt void *newp; 1630df930be7Sderaadt size_t newlen; 1631df930be7Sderaadt struct proc *p; 1632df930be7Sderaadt { 1633df930be7Sderaadt dev_t consdev; 1634a072164aSmiod #if NIOASIC > 0 1635a072164aSmiod int oldval, ret; 1636a072164aSmiod #endif 1637df930be7Sderaadt 163845e5a1a0Sart if (name[0] != CPU_CHIPSET && namelen != 1) 1639df930be7Sderaadt return (ENOTDIR); /* overloaded */ 1640df930be7Sderaadt 1641df930be7Sderaadt switch (name[0]) { 1642df930be7Sderaadt case CPU_CONSDEV: 1643df930be7Sderaadt if (cn_tab != NULL) 1644df930be7Sderaadt consdev = cn_tab->cn_dev; 1645df930be7Sderaadt else 1646df930be7Sderaadt consdev = NODEV; 1647df930be7Sderaadt return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 1648df930be7Sderaadt sizeof consdev)); 1649417eba8cSderaadt 1650a37778bcSderaadt #ifndef SMALL_KERNEL 165150ce9ee0Sniklas case CPU_UNALIGNED_PRINT: 165250ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 165350ce9ee0Sniklas &alpha_unaligned_print)); 165450ce9ee0Sniklas 165550ce9ee0Sniklas case CPU_UNALIGNED_FIX: 165650ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 165750ce9ee0Sniklas &alpha_unaligned_fix)); 165850ce9ee0Sniklas 165950ce9ee0Sniklas case CPU_UNALIGNED_SIGBUS: 166050ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 166150ce9ee0Sniklas &alpha_unaligned_sigbus)); 166250ce9ee0Sniklas 16633a630e3fSniklas case CPU_BOOTED_KERNEL: 1664aed035abSart return (sysctl_rdstring(oldp, oldlenp, newp, 1665aed035abSart bootinfo.booted_kernel)); 16663a630e3fSniklas 166745e5a1a0Sart case CPU_CHIPSET: 166845e5a1a0Sart return (alpha_sysctl_chipset(name + 1, namelen - 1, oldp, 166945e5a1a0Sart oldlenp)); 1670a37778bcSderaadt #endif /* SMALL_KERNEL */ 1671433075b6Spvalchev 1672433075b6Spvalchev #ifndef NO_IEEE 1673433075b6Spvalchev case CPU_FP_SYNC_COMPLETE: 1674433075b6Spvalchev return (sysctl_int(oldp, oldlenp, newp, newlen, 1675433075b6Spvalchev &alpha_fp_sync_complete)); 1676433075b6Spvalchev #endif 167727626149Smatthieu case CPU_ALLOWAPERTURE: 167827626149Smatthieu #ifdef APERTURE 167927626149Smatthieu if (securelevel > 0) 16801546ceefSderaadt return (sysctl_int_lower(oldp, oldlenp, newp, newlen, 16811546ceefSderaadt &allowaperture)); 168227626149Smatthieu else 168327626149Smatthieu return (sysctl_int(oldp, oldlenp, newp, newlen, 168427626149Smatthieu &allowaperture)); 168527626149Smatthieu #else 168627626149Smatthieu return (sysctl_rdint(oldp, oldlenp, newp, 0)); 168727626149Smatthieu #endif 1688a072164aSmiod #if NIOASIC > 0 1689a072164aSmiod case CPU_LED_BLINK: 1690a072164aSmiod oldval = alpha_led_blink; 1691a072164aSmiod ret = sysctl_int(oldp, oldlenp, newp, newlen, &alpha_led_blink); 1692a072164aSmiod if (oldval != alpha_led_blink) 1693a072164aSmiod ioasic_led_blink(NULL); 1694a072164aSmiod return (ret); 1695a072164aSmiod #endif 1696df930be7Sderaadt default: 1697df930be7Sderaadt return (EOPNOTSUPP); 1698df930be7Sderaadt } 1699df930be7Sderaadt /* NOTREACHED */ 1700df930be7Sderaadt } 1701df930be7Sderaadt 1702df930be7Sderaadt /* 1703df930be7Sderaadt * Set registers on exec. 1704df930be7Sderaadt */ 1705df930be7Sderaadt void 1706df930be7Sderaadt setregs(p, pack, stack, retval) 1707df930be7Sderaadt register struct proc *p; 1708df930be7Sderaadt struct exec_package *pack; 1709df930be7Sderaadt u_long stack; 1710df930be7Sderaadt register_t *retval; 1711df930be7Sderaadt { 1712df930be7Sderaadt struct trapframe *tfp = p->p_md.md_tf; 17133a630e3fSniklas #ifdef DEBUG 17143a630e3fSniklas int i; 17153a630e3fSniklas #endif 1716df930be7Sderaadt 1717df930be7Sderaadt #ifdef DEBUG 171850ce9ee0Sniklas /* 171950ce9ee0Sniklas * Crash and dump, if the user requested it. 172050ce9ee0Sniklas */ 172150ce9ee0Sniklas if (boothowto & RB_DUMP) 172250ce9ee0Sniklas panic("crash requested by boot flags"); 172350ce9ee0Sniklas #endif 172450ce9ee0Sniklas 172550ce9ee0Sniklas #ifdef DEBUG 172650ce9ee0Sniklas for (i = 0; i < FRAME_SIZE; i++) 1727df930be7Sderaadt tfp->tf_regs[i] = 0xbabefacedeadbeef; 17286334622bSguenther tfp->tf_regs[FRAME_A1] = 0; 1729df930be7Sderaadt #else 173050ce9ee0Sniklas bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]); 1731df930be7Sderaadt #endif 1732df930be7Sderaadt bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp); 173350ce9ee0Sniklas alpha_pal_wrusp(stack); 173450ce9ee0Sniklas tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; 173550ce9ee0Sniklas tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; 1736df930be7Sderaadt 173750ce9ee0Sniklas tfp->tf_regs[FRAME_A0] = stack; 173850ce9ee0Sniklas /* a1 and a2 already zeroed */ 173950ce9ee0Sniklas tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ 174050ce9ee0Sniklas 174150ce9ee0Sniklas p->p_md.md_flags &= ~MDP_FPUSED; 1742433075b6Spvalchev #ifndef NO_IEEE 1743433075b6Spvalchev if (__predict_true((p->p_md.md_flags & IEEE_INHERIT) == 0)) { 1744433075b6Spvalchev p->p_md.md_flags &= ~MDP_FP_C; 1745433075b6Spvalchev p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_DYN(FP_RN); 1746433075b6Spvalchev } 1747433075b6Spvalchev #endif 1748433075b6Spvalchev if (p->p_addr->u_pcb.pcb_fpcpu != NULL) 1749433075b6Spvalchev fpusave_proc(p, 0); 1750ee2d823aSmiod 1751ee2d823aSmiod retval[1] = 0; 1752433075b6Spvalchev } 1753df930be7Sderaadt 1754433075b6Spvalchev /* 1755433075b6Spvalchev * Release the FPU. 1756433075b6Spvalchev */ 1757433075b6Spvalchev void 1758433075b6Spvalchev fpusave_cpu(struct cpu_info *ci, int save) 1759433075b6Spvalchev { 1760433075b6Spvalchev struct proc *p; 176121c23d01Smiod #if defined(MULTIPROCESSOR) 176221c23d01Smiod int s; 176321c23d01Smiod #endif 1764433075b6Spvalchev 1765433075b6Spvalchev KDASSERT(ci == curcpu()); 1766433075b6Spvalchev 1767433075b6Spvalchev #if defined(MULTIPROCESSOR) 176821c23d01Smiod /* Need to block IPIs */ 17692d7472daSmiod s = splipi(); 1770433075b6Spvalchev atomic_setbits_ulong(&ci->ci_flags, CPUF_FPUSAVE); 1771433075b6Spvalchev #endif 1772433075b6Spvalchev 1773433075b6Spvalchev p = ci->ci_fpcurproc; 1774433075b6Spvalchev if (p == NULL) 1775433075b6Spvalchev goto out; 1776433075b6Spvalchev 1777433075b6Spvalchev if (save) { 1778433075b6Spvalchev alpha_pal_wrfen(1); 1779433075b6Spvalchev savefpstate(&p->p_addr->u_pcb.pcb_fp); 1780433075b6Spvalchev } 1781433075b6Spvalchev 1782433075b6Spvalchev alpha_pal_wrfen(0); 1783433075b6Spvalchev 1784433075b6Spvalchev p->p_addr->u_pcb.pcb_fpcpu = NULL; 1785433075b6Spvalchev ci->ci_fpcurproc = NULL; 1786433075b6Spvalchev 1787433075b6Spvalchev out: 1788433075b6Spvalchev #if defined(MULTIPROCESSOR) 1789433075b6Spvalchev atomic_clearbits_ulong(&ci->ci_flags, CPUF_FPUSAVE); 1790*4fa86cc0Smiod alpha_pal_swpipl(s); 1791433075b6Spvalchev #endif 1792433075b6Spvalchev return; 1793433075b6Spvalchev } 1794433075b6Spvalchev 1795433075b6Spvalchev /* 1796433075b6Spvalchev * Synchronize FP state for this process. 1797433075b6Spvalchev */ 1798433075b6Spvalchev void 1799433075b6Spvalchev fpusave_proc(struct proc *p, int save) 1800433075b6Spvalchev { 1801433075b6Spvalchev struct cpu_info *ci = curcpu(); 1802433075b6Spvalchev struct cpu_info *oci; 1803433075b6Spvalchev #if defined(MULTIPROCESSOR) 1804433075b6Spvalchev u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU; 18052d7472daSmiod int s; 1806433075b6Spvalchev #endif 1807433075b6Spvalchev 1808433075b6Spvalchev KDASSERT(p->p_addr != NULL); 1809433075b6Spvalchev 18102d7472daSmiod for (;;) { 181121c23d01Smiod #if defined(MULTIPROCESSOR) 181221c23d01Smiod /* Need to block IPIs */ 18132d7472daSmiod s = splipi(); 181421c23d01Smiod #endif 181521c23d01Smiod 1816433075b6Spvalchev oci = p->p_addr->u_pcb.pcb_fpcpu; 1817433075b6Spvalchev if (oci == NULL) { 181821c23d01Smiod #if defined(MULTIPROCESSOR) 1819*4fa86cc0Smiod alpha_pal_swpipl(s); 182021c23d01Smiod #endif 1821433075b6Spvalchev return; 1822433075b6Spvalchev } 1823433075b6Spvalchev 1824433075b6Spvalchev #if defined(MULTIPROCESSOR) 1825433075b6Spvalchev if (oci == ci) { 1826433075b6Spvalchev KASSERT(ci->ci_fpcurproc == p); 1827*4fa86cc0Smiod alpha_pal_swpipl(s); 1828433075b6Spvalchev fpusave_cpu(ci, save); 1829433075b6Spvalchev return; 1830433075b6Spvalchev } 1831433075b6Spvalchev 18322d7472daSmiod /* 18332d7472daSmiod * The other cpu may still be running and could have 18342d7472daSmiod * discarded the fpu context on its own. 18352d7472daSmiod */ 18362d7472daSmiod if (oci->ci_fpcurproc != p) 18372d7472daSmiod continue; 18382d7472daSmiod 1839433075b6Spvalchev alpha_send_ipi(oci->ci_cpuid, ipi); 1840*4fa86cc0Smiod alpha_pal_swpipl(s); 1841433075b6Spvalchev 18422d7472daSmiod while (p->p_addr->u_pcb.pcb_fpcpu != NULL) 18432d7472daSmiod SPINLOCK_SPIN_HOOK; 1844433075b6Spvalchev #else 1845433075b6Spvalchev KASSERT(ci->ci_fpcurproc == p); 1846433075b6Spvalchev fpusave_cpu(ci, save); 1847433075b6Spvalchev #endif /* MULTIPROCESSOR */ 18482d7472daSmiod 18492d7472daSmiod break; 18502d7472daSmiod } 1851df930be7Sderaadt } 1852df930be7Sderaadt 1853df930be7Sderaadt int 1854df930be7Sderaadt spl0() 1855df930be7Sderaadt { 1856df930be7Sderaadt 1857aed035abSart if (ssir) { 1858aed035abSart (void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT); 18592a2685f2Sart softintr_dispatch(); 1860aed035abSart } 1861df930be7Sderaadt 186250ce9ee0Sniklas return (alpha_pal_swpipl(ALPHA_PSL_IPL_0)); 1863df930be7Sderaadt } 1864df930be7Sderaadt 1865df930be7Sderaadt /* 1866417eba8cSderaadt * Wait "n" microseconds. 1867417eba8cSderaadt */ 186850ce9ee0Sniklas void 1869417eba8cSderaadt delay(n) 187050ce9ee0Sniklas unsigned long n; 1871417eba8cSderaadt { 18725d097e9eSmiod unsigned long pcc0, pcc1, curcycle, cycles, usec; 18735d097e9eSmiod 18745d097e9eSmiod if (n == 0) 18755d097e9eSmiod return; 18765d097e9eSmiod 18775d097e9eSmiod pcc0 = alpha_rpcc() & 0xffffffffUL; 18785d097e9eSmiod cycles = 0; 18795d097e9eSmiod usec = 0; 18805d097e9eSmiod 18815d097e9eSmiod while (usec <= n) { 18825d097e9eSmiod /* 18835d097e9eSmiod * Get the next CPU cycle count - assumes that we can not 18845d097e9eSmiod * have had more than one 32 bit overflow. 18855d097e9eSmiod */ 18865d097e9eSmiod pcc1 = alpha_rpcc() & 0xffffffffUL; 18875d097e9eSmiod if (pcc1 < pcc0) 18885d097e9eSmiod curcycle = (pcc1 + 0x100000000UL) - pcc0; 18895d097e9eSmiod else 18905d097e9eSmiod curcycle = pcc1 - pcc0; 1891417eba8cSderaadt 1892aed035abSart /* 18935d097e9eSmiod * We now have the number of processor cycles since we 18945d097e9eSmiod * last checked. Add the current cycle count to the 18955d097e9eSmiod * running total. If it's over cycles_per_usec, increment 18965d097e9eSmiod * the usec counter. 1897aed035abSart */ 18985d097e9eSmiod cycles += curcycle; 189921c23d01Smiod while (cycles >= cycles_per_usec) { 19005d097e9eSmiod usec++; 19015d097e9eSmiod cycles -= cycles_per_usec; 19025d097e9eSmiod } 19035d097e9eSmiod pcc0 = pcc1; 19045d097e9eSmiod } 1905417eba8cSderaadt } 1906417eba8cSderaadt 1907aed035abSart int 1908aed035abSart alpha_pa_access(pa) 1909aed035abSart u_long pa; 1910aed035abSart { 1911aed035abSart int i; 1912aed035abSart 1913aed035abSart for (i = 0; i < mem_cluster_cnt; i++) { 1914aed035abSart if (pa < mem_clusters[i].start) 1915aed035abSart continue; 1916aed035abSart if ((pa - mem_clusters[i].start) >= 1917aed035abSart (mem_clusters[i].size & ~PAGE_MASK)) 1918aed035abSart continue; 1919aed035abSart return (mem_clusters[i].size & PAGE_MASK); /* prot */ 1920aed035abSart } 1921aed035abSart 1922aed035abSart /* 1923aed035abSart * Address is not a memory address. If we're secure, disallow 1924aed035abSart * access. Otherwise, grant read/write. 1925aed035abSart */ 1926aed035abSart if (securelevel > 0) 1927aed035abSart return (VM_PROT_NONE); 1928aed035abSart else 1929aed035abSart return (VM_PROT_READ | VM_PROT_WRITE); 1930aed035abSart } 1931aed035abSart 1932e464495eSniklas /* XXX XXX BEGIN XXX XXX */ 1933aed035abSart paddr_t alpha_XXX_dmamap_or; /* XXX */ 1934e464495eSniklas /* XXX */ 1935aed035abSart paddr_t /* XXX */ 1936e464495eSniklas alpha_XXX_dmamap(v) /* XXX */ 1937aed035abSart vaddr_t v; /* XXX */ 1938e464495eSniklas { /* XXX */ 1939e464495eSniklas /* XXX */ 1940e464495eSniklas return (vtophys(v) | alpha_XXX_dmamap_or); /* XXX */ 1941e464495eSniklas } /* XXX */ 1942e464495eSniklas /* XXX XXX END XXX XXX */ 1943