1*aed035abSart /* $NetBSD: machdep.c,v 1.206 2000/05/23 05:12:54 thorpej Exp $ */ 2*aed035abSart 3*aed035abSart /*- 4*aed035abSart * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 5*aed035abSart * All rights reserved. 6*aed035abSart * 7*aed035abSart * This code is derived from software contributed to The NetBSD Foundation 8*aed035abSart * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9*aed035abSart * NASA Ames Research Center and by Chris G. Demetriou. 10*aed035abSart * 11*aed035abSart * Redistribution and use in source and binary forms, with or without 12*aed035abSart * modification, are permitted provided that the following conditions 13*aed035abSart * are met: 14*aed035abSart * 1. Redistributions of source code must retain the above copyright 15*aed035abSart * notice, this list of conditions and the following disclaimer. 16*aed035abSart * 2. Redistributions in binary form must reproduce the above copyright 17*aed035abSart * notice, this list of conditions and the following disclaimer in the 18*aed035abSart * documentation and/or other materials provided with the distribution. 19*aed035abSart * 3. All advertising materials mentioning features or use of this software 20*aed035abSart * must display the following acknowledgement: 21*aed035abSart * This product includes software developed by the NetBSD 22*aed035abSart * Foundation, Inc. and its contributors. 23*aed035abSart * 4. Neither the name of The NetBSD Foundation nor the names of its 24*aed035abSart * contributors may be used to endorse or promote products derived 25*aed035abSart * from this software without specific prior written permission. 26*aed035abSart * 27*aed035abSart * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28*aed035abSart * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29*aed035abSart * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30*aed035abSart * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31*aed035abSart * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32*aed035abSart * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33*aed035abSart * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34*aed035abSart * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35*aed035abSart * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36*aed035abSart * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37*aed035abSart * POSSIBILITY OF SUCH DAMAGE. 38*aed035abSart */ 39df930be7Sderaadt 40df930be7Sderaadt /* 41417eba8cSderaadt * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 42df930be7Sderaadt * All rights reserved. 43df930be7Sderaadt * 44df930be7Sderaadt * Author: Chris G. Demetriou 45df930be7Sderaadt * 46df930be7Sderaadt * Permission to use, copy, modify and distribute this software and 47df930be7Sderaadt * its documentation is hereby granted, provided that both the copyright 48df930be7Sderaadt * notice and this permission notice appear in all copies of the 49df930be7Sderaadt * software, derivative works or modified versions, and any portions 50df930be7Sderaadt * thereof, and that both notices appear in supporting documentation. 51df930be7Sderaadt * 52df930be7Sderaadt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 53df930be7Sderaadt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 54df930be7Sderaadt * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 55df930be7Sderaadt * 56df930be7Sderaadt * Carnegie Mellon requests users of this software to return to 57df930be7Sderaadt * 58df930be7Sderaadt * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 59df930be7Sderaadt * School of Computer Science 60df930be7Sderaadt * Carnegie Mellon University 61df930be7Sderaadt * Pittsburgh PA 15213-3890 62df930be7Sderaadt * 63df930be7Sderaadt * any improvements or extensions that they make and grant Carnegie the 64df930be7Sderaadt * rights to redistribute these changes. 65df930be7Sderaadt */ 66df930be7Sderaadt 67df930be7Sderaadt #include <sys/param.h> 68df930be7Sderaadt #include <sys/systm.h> 69df930be7Sderaadt #include <sys/signalvar.h> 70df930be7Sderaadt #include <sys/kernel.h> 71df930be7Sderaadt #include <sys/map.h> 72df930be7Sderaadt #include <sys/proc.h> 73df930be7Sderaadt #include <sys/buf.h> 74df930be7Sderaadt #include <sys/reboot.h> 75417eba8cSderaadt #include <sys/device.h> 76df930be7Sderaadt #include <sys/conf.h> 77df930be7Sderaadt #include <sys/file.h> 78df930be7Sderaadt #ifdef REAL_CLISTS 79df930be7Sderaadt #include <sys/clist.h> 80df930be7Sderaadt #endif 81d66eba84Sart #include <sys/timeout.h> 82df930be7Sderaadt #include <sys/malloc.h> 83df930be7Sderaadt #include <sys/mbuf.h> 84df930be7Sderaadt #include <sys/msgbuf.h> 85df930be7Sderaadt #include <sys/ioctl.h> 86df930be7Sderaadt #include <sys/tty.h> 87df930be7Sderaadt #include <sys/user.h> 88df930be7Sderaadt #include <sys/exec.h> 89df930be7Sderaadt #include <sys/exec_ecoff.h> 90*aed035abSart #include <vm/vm.h> 91df930be7Sderaadt #include <sys/sysctl.h> 9250ce9ee0Sniklas #include <sys/core.h> 9350ce9ee0Sniklas #include <sys/kcore.h> 9450ce9ee0Sniklas #include <machine/kcore.h> 95df930be7Sderaadt #ifdef SYSVMSG 96df930be7Sderaadt #include <sys/msg.h> 97df930be7Sderaadt #endif 98df930be7Sderaadt #ifdef SYSVSEM 99df930be7Sderaadt #include <sys/sem.h> 100df930be7Sderaadt #endif 101df930be7Sderaadt #ifdef SYSVSHM 102df930be7Sderaadt #include <sys/shm.h> 103df930be7Sderaadt #endif 104df930be7Sderaadt 105df930be7Sderaadt #include <sys/mount.h> 106df930be7Sderaadt #include <sys/syscallargs.h> 107df930be7Sderaadt 108df930be7Sderaadt #include <vm/vm_kern.h> 109*aed035abSart #include <uvm/uvm_extern.h> 110df930be7Sderaadt 111df930be7Sderaadt #include <dev/cons.h> 112df930be7Sderaadt 11350ce9ee0Sniklas #include <machine/autoconf.h> 114df930be7Sderaadt #include <machine/cpu.h> 115df930be7Sderaadt #include <machine/reg.h> 116df930be7Sderaadt #include <machine/rpb.h> 117df930be7Sderaadt #include <machine/prom.h> 1183a630e3fSniklas #include <machine/cpuconf.h> 119df930be7Sderaadt 12012f8bbedSniklas #ifdef DDB 12112f8bbedSniklas #include <machine/db_machdep.h> 12212f8bbedSniklas #include <ddb/db_access.h> 12312f8bbedSniklas #include <ddb/db_sym.h> 12412f8bbedSniklas #include <ddb/db_extern.h> 12512f8bbedSniklas #endif 12612f8bbedSniklas 127df930be7Sderaadt #include <net/netisr.h> 12850ce9ee0Sniklas #include <net/if.h> 12950ce9ee0Sniklas 13050ce9ee0Sniklas #ifdef INET 13150ce9ee0Sniklas #include <netinet/in.h> 13250ce9ee0Sniklas #include <netinet/if_ether.h> 13350ce9ee0Sniklas #include <netinet/ip_var.h> 13450ce9ee0Sniklas #endif 135287546eaSitojun 136287546eaSitojun #ifdef INET6 137287546eaSitojun # ifndef INET 138287546eaSitojun # include <netinet/in.h> 139287546eaSitojun # endif 1408038b434Sitojun #include <netinet/ip6.h> 141287546eaSitojun #include <netinet6/ip6_var.h> 142287546eaSitojun #endif 143287546eaSitojun 14450ce9ee0Sniklas #include "ppp.h" 145661c8891Sjason #include "bridge.h" 146df930be7Sderaadt 147417eba8cSderaadt #include "le_ioasic.h" /* for le_iomem creation */ 148df930be7Sderaadt 14950ce9ee0Sniklas int cpu_dump __P((void)); 1503a630e3fSniklas int cpu_dumpsize __P((void)); 151*aed035abSart u_long cpu_dump_mempagecnt __P((void)); 15250ce9ee0Sniklas void do_sir __P((void)); 1533a630e3fSniklas void dumpsys __P((void)); 154*aed035abSart caddr_t allocsys __P((caddr_t)); 1553a630e3fSniklas void identifycpu __P((void)); 1563a630e3fSniklas void netintr __P((void)); 1573a630e3fSniklas void regdump __P((struct trapframe *framep)); 1583a630e3fSniklas void printregs __P((struct reg *)); 159df930be7Sderaadt 160df930be7Sderaadt /* 161df930be7Sderaadt * Declare these as initialized data so we can patch them. 162df930be7Sderaadt */ 163df930be7Sderaadt #ifdef NBUF 164df930be7Sderaadt int nbuf = NBUF; 165df930be7Sderaadt #else 166df930be7Sderaadt int nbuf = 0; 167df930be7Sderaadt #endif 168df930be7Sderaadt #ifdef BUFPAGES 169df930be7Sderaadt int bufpages = BUFPAGES; 170df930be7Sderaadt #else 171df930be7Sderaadt int bufpages = 0; 172df930be7Sderaadt #endif 173*aed035abSart 174*aed035abSart vm_map_t exec_map = NULL; 175*aed035abSart vm_map_t mb_map = NULL; 176*aed035abSart vm_map_t phys_map = NULL; 177*aed035abSart 178df930be7Sderaadt int maxmem; /* max memory per process */ 179df930be7Sderaadt 180df930be7Sderaadt int totalphysmem; /* total amount of physical memory in system */ 18174652a67Sniklas int physmem; /* physical mem used by OpenBSD + some rsvd */ 182df930be7Sderaadt int resvmem; /* amount of memory reserved for PROM */ 183df930be7Sderaadt int unusedmem; /* amount of memory for OS that we don't use */ 184df930be7Sderaadt int unknownmem; /* amount of memory with an unknown use */ 185df930be7Sderaadt 186df930be7Sderaadt int cputype; /* system type, from the RPB */ 187df930be7Sderaadt 188df930be7Sderaadt /* 189df930be7Sderaadt * XXX We need an address to which we can assign things so that they 190df930be7Sderaadt * won't be optimized away because we didn't use the value. 191df930be7Sderaadt */ 192df930be7Sderaadt u_int32_t no_optimize; 193df930be7Sderaadt 194df930be7Sderaadt /* the following is used externally (sysctl_hw) */ 195*aed035abSart char machine[] = MACHINE; /* from <machine/param.h> */ 196417eba8cSderaadt char cpu_model[128]; 197*aed035abSart char root_device[17]; 198df930be7Sderaadt 199df930be7Sderaadt struct user *proc0paddr; 200df930be7Sderaadt 201df930be7Sderaadt /* Number of machine cycles per microsecond */ 202df930be7Sderaadt u_int64_t cycles_per_usec; 203df930be7Sderaadt 204df930be7Sderaadt /* number of cpus in the box. really! */ 205df930be7Sderaadt int ncpus; 206df930be7Sderaadt 207*aed035abSart #if !defined(MULTIPROCESSOR) 208*aed035abSart /* A single machine check info structure for single CPU configurations. */ 209*aed035abSart struct mchkinfo mchkinfo_store; 210*aed035abSart #endif 211*aed035abSart 212*aed035abSart struct bootinfo_kernel bootinfo; 213*aed035abSart 214*aed035abSart /* For built-in TCDS */ 215*aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500) 216*aed035abSart u_int8_t dec_3000_scsiid[2], dec_3000_scsifast[2]; 217*aed035abSart #endif 218*aed035abSart 219*aed035abSart struct platform platform; 220417eba8cSderaadt 221417eba8cSderaadt /* for cpu_sysctl() */ 22250ce9ee0Sniklas int alpha_unaligned_print = 1; /* warn about unaligned accesses */ 22350ce9ee0Sniklas int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ 22450ce9ee0Sniklas int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ 22550ce9ee0Sniklas 226*aed035abSart /* 227*aed035abSart * XXX This should be dynamically sized, but we have the chicken-egg problem! 228*aed035abSart * XXX it should also be larger than it is, because not all of the mddt 229*aed035abSart * XXX clusters end up being used for VM. 230*aed035abSart */ 231*aed035abSart phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; /* low size bits overloaded */ 232*aed035abSart int mem_cluster_cnt; 233*aed035abSart 2343a630e3fSniklas void 235*aed035abSart alpha_init(pfn, ptb, bim, bip, biv) 236df930be7Sderaadt u_long pfn; /* first free PFN number */ 237df930be7Sderaadt u_long ptb; /* PFN of current level 1 page table */ 238*aed035abSart u_long bim; /* bootinfo magic */ 239*aed035abSart u_long bip; /* bootinfo pointer */ 240*aed035abSart u_long biv; /* bootinfo version */ 241df930be7Sderaadt { 242*aed035abSart extern char kernel_text[], _end[]; 243df930be7Sderaadt struct mddt *mddtp; 244*aed035abSart struct mddt_cluster *memc; 245df930be7Sderaadt int i, mddtweird; 246*aed035abSart struct vm_physseg *vps; 247*aed035abSart vaddr_t kernstart, kernend; 248*aed035abSart paddr_t kernstartpfn, kernendpfn, pfn0, pfn1; 249*aed035abSart vsize_t size; 250df930be7Sderaadt char *p; 251*aed035abSart caddr_t v; 252*aed035abSart char *bootinfo_msg; 253*aed035abSart const struct cpuinit *c; 254*aed035abSart extern caddr_t esym; 255*aed035abSart struct cpu_info *ci; 256*aed035abSart cpuid_t cpu_id; 257df930be7Sderaadt 258*aed035abSart /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ 259f3914c62Sniklas 260df930be7Sderaadt /* 261*aed035abSart * Turn off interrupts (not mchecks) and floating point. 262df930be7Sderaadt * Make sure the instruction and data streams are consistent. 263df930be7Sderaadt */ 264*aed035abSart (void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); 26550ce9ee0Sniklas alpha_pal_wrfen(0); 26650ce9ee0Sniklas ALPHA_TBIA(); 26750ce9ee0Sniklas alpha_pal_imb(); 268df930be7Sderaadt 269*aed035abSart cpu_id = cpu_number(); 270*aed035abSart 271*aed035abSart #if defined(MULTIPROCESSOR) 272df930be7Sderaadt /* 273*aed035abSart * Set our SysValue to the address of our cpu_info structure. 274*aed035abSart * Secondary processors do this in their spinup trampoline. 275df930be7Sderaadt */ 276*aed035abSart alpha_pal_wrval((u_long)&cpu_info[cpu_id]); 277*aed035abSart #endif 278*aed035abSart 279*aed035abSart ci = curcpu(); 280*aed035abSart ci->ci_cpuid = cpu_id; 281*aed035abSart 282*aed035abSart /* 283*aed035abSart * Get critical system information (if possible, from the 284*aed035abSart * information provided by the boot program). 285*aed035abSart */ 286*aed035abSart bootinfo_msg = NULL; 287*aed035abSart if (bim == BOOTINFO_MAGIC) { 288*aed035abSart if (biv == 0) { /* backward compat */ 289*aed035abSart biv = *(u_long *)bip; 290*aed035abSart bip += 8; 291*aed035abSart } 292*aed035abSart switch (biv) { 293*aed035abSart case 1: { 294*aed035abSart struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip; 295*aed035abSart 296*aed035abSart bootinfo.ssym = v1p->ssym; 297*aed035abSart bootinfo.esym = v1p->esym; 298*aed035abSart /* hwrpb may not be provided by boot block in v1 */ 299*aed035abSart if (v1p->hwrpb != NULL) { 300*aed035abSart bootinfo.hwrpb_phys = 301*aed035abSart ((struct rpb *)v1p->hwrpb)->rpb_phys; 302*aed035abSart bootinfo.hwrpb_size = v1p->hwrpbsize; 303*aed035abSart } else { 304*aed035abSart bootinfo.hwrpb_phys = 305*aed035abSart ((struct rpb *)HWRPB_ADDR)->rpb_phys; 306*aed035abSart bootinfo.hwrpb_size = 307*aed035abSart ((struct rpb *)HWRPB_ADDR)->rpb_size; 308*aed035abSart } 309*aed035abSart bcopy(v1p->boot_flags, bootinfo.boot_flags, 310*aed035abSart min(sizeof v1p->boot_flags, 311*aed035abSart sizeof bootinfo.boot_flags)); 312*aed035abSart bcopy(v1p->booted_kernel, bootinfo.booted_kernel, 313*aed035abSart min(sizeof v1p->booted_kernel, 314*aed035abSart sizeof bootinfo.booted_kernel)); 315*aed035abSart /* booted dev not provided in bootinfo */ 316*aed035abSart init_prom_interface((struct rpb *) 317*aed035abSart ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys)); 318*aed035abSart prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, 319*aed035abSart sizeof bootinfo.booted_dev); 320*aed035abSart break; 321*aed035abSart } 322*aed035abSart default: 323*aed035abSart bootinfo_msg = "unknown bootinfo version"; 324*aed035abSart goto nobootinfo; 325*aed035abSart } 326*aed035abSart } else { 327*aed035abSart bootinfo_msg = "boot program did not pass bootinfo"; 328*aed035abSart nobootinfo: 329*aed035abSart bootinfo.ssym = (u_long)_end; 330*aed035abSart bootinfo.esym = (u_long)_end; 331*aed035abSart bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys; 332*aed035abSart bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size; 333*aed035abSart init_prom_interface((struct rpb *)HWRPB_ADDR); 334*aed035abSart prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags, 335*aed035abSart sizeof bootinfo.boot_flags); 336*aed035abSart prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel, 337*aed035abSart sizeof bootinfo.booted_kernel); 338*aed035abSart prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, 339*aed035abSart sizeof bootinfo.booted_dev); 340*aed035abSart } 341*aed035abSart 342*aed035abSart esym = (caddr_t)bootinfo.esym; 343*aed035abSart /* 344*aed035abSart * Initialize the kernel's mapping of the RPB. It's needed for 345*aed035abSart * lots of things. 346*aed035abSart */ 347*aed035abSart hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys); 348*aed035abSart 349*aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500) 350*aed035abSart if (hwrpb->rpb_type == ST_DEC_3000_300 || 351*aed035abSart hwrpb->rpb_type == ST_DEC_3000_500) { 352*aed035abSart prom_getenv(PROM_E_SCSIID, dec_3000_scsiid, 353*aed035abSart sizeof(dec_3000_scsiid)); 354*aed035abSart prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast, 355*aed035abSart sizeof(dec_3000_scsifast)); 356*aed035abSart } 357*aed035abSart #endif 358df930be7Sderaadt 359df930be7Sderaadt /* 360df930be7Sderaadt * Remember how many cycles there are per microsecond, 361df930be7Sderaadt * so that we can use delay(). Round up, for safety. 362df930be7Sderaadt */ 363df930be7Sderaadt cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000; 364df930be7Sderaadt 365df930be7Sderaadt /* 366*aed035abSart * Initalize the (temporary) bootstrap console interface, so 367*aed035abSart * we can use printf until the VM system starts being setup. 368*aed035abSart * The real console is initialized before then. 369df930be7Sderaadt */ 370*aed035abSart init_bootstrap_console(); 371*aed035abSart 372*aed035abSart /* OUTPUT NOW ALLOWED */ 373*aed035abSart 374*aed035abSart /* delayed from above */ 375*aed035abSart if (bootinfo_msg) 376*aed035abSart printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n", 377*aed035abSart bootinfo_msg, bim, bip, biv); 378*aed035abSart 379*aed035abSart /* Initialize the trap vectors on the primary processor. */ 380*aed035abSart trap_init(); 381df930be7Sderaadt 382df930be7Sderaadt /* 383*aed035abSart * Find out what hardware we're on, and do basic initialization. 384df930be7Sderaadt */ 385*aed035abSart cputype = hwrpb->rpb_type; 386*aed035abSart if (cputype < 0) { 387*aed035abSart /* 388*aed035abSart * At least some white-box systems have SRM which 389*aed035abSart * reports a systype that's the negative of their 390*aed035abSart * blue-box counterpart. 391*aed035abSart */ 392*aed035abSart cputype = -cputype; 393*aed035abSart } 394*aed035abSart c = platform_lookup(cputype); 395*aed035abSart if (c == NULL) { 396*aed035abSart platform_not_supported(); 397*aed035abSart /* NOTREACHED */ 398*aed035abSart } 399*aed035abSart (*c->init)(); 400*aed035abSart strcpy(cpu_model, platform.model); 40150ce9ee0Sniklas 40250ce9ee0Sniklas /* 403*aed035abSart * Initalize the real console, so that the bootstrap console is 404*aed035abSart * no longer necessary. 40550ce9ee0Sniklas */ 406*aed035abSart (*platform.cons_init)(); 407*aed035abSart 408*aed035abSart #ifdef DIAGNOSTIC 409*aed035abSart /* Paranoid sanity checking */ 410*aed035abSart 411*aed035abSart /* We should always be running on the primary. */ 412*aed035abSart assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami()); 413*aed035abSart 414*aed035abSart /* 415*aed035abSart * On single-CPU systypes, the primary should always be CPU 0, 416*aed035abSart * except on Alpha 8200 systems where the CPU id is related 417*aed035abSart * to the VID, which is related to the Turbo Laser node id. 418*aed035abSart */ 419*aed035abSart if (cputype != ST_DEC_21000) 420*aed035abSart assert(hwrpb->rpb_primary_cpu_id == 0); 421*aed035abSart #endif 422*aed035abSart 423*aed035abSart /* NO MORE FIRMWARE ACCESS ALLOWED */ 424*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 425*aed035abSart /* 426*aed035abSart * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and 427*aed035abSart * XXX pmap_uses_prom_console() evaluates to non-zero.) 428*aed035abSart */ 429*aed035abSart #endif 430*aed035abSart 431*aed035abSart /* 432*aed035abSart * find out this system's page size 433*aed035abSart */ 434*aed035abSart PAGE_SIZE = hwrpb->rpb_page_size; 435*aed035abSart if (PAGE_SIZE != 8192) 436*aed035abSart panic("page size %d != 8192?!", PAGE_SIZE); 437*aed035abSart 438*aed035abSart /* 439*aed035abSart * Initialize PAGE_SIZE-dependent variables. 440*aed035abSart */ 441*aed035abSart uvm_setpagesize(); 442*aed035abSart 443*aed035abSart /* 444*aed035abSart * Find the beginning and end of the kernel (and leave a 445*aed035abSart * bit of space before the beginning for the bootstrap 446*aed035abSart * stack). 447*aed035abSart */ 448*aed035abSart kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE; 449*aed035abSart #ifdef DDB 450*aed035abSart kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym); 451*aed035abSart #else 452*aed035abSart kernend = (vaddr_t)round_page((vaddr_t)_end); 453*aed035abSart #endif 454*aed035abSart 455*aed035abSart kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart)); 456*aed035abSart kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend)); 457df930be7Sderaadt 458df930be7Sderaadt /* 459df930be7Sderaadt * Find out how much memory is available, by looking at 460df930be7Sderaadt * the memory cluster descriptors. This also tries to do 461df930be7Sderaadt * its best to detect things things that have never been seen 462df930be7Sderaadt * before... 463df930be7Sderaadt */ 464df930be7Sderaadt mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off); 465df930be7Sderaadt 466*aed035abSart /* MDDT SANITY CHECKING */ 467df930be7Sderaadt mddtweird = 0; 468*aed035abSart if (mddtp->mddt_cluster_cnt < 2) { 469df930be7Sderaadt mddtweird = 1; 470*aed035abSart printf("WARNING: weird number of mem clusters: %lu\n", 471*aed035abSart mddtp->mddt_cluster_cnt); 472df930be7Sderaadt } 473df930be7Sderaadt 474*aed035abSart #if 0 475*aed035abSart printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt); 476*aed035abSart #endif 477df930be7Sderaadt 478*aed035abSart for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 479*aed035abSart memc = &mddtp->mddt_clusters[i]; 480*aed035abSart #if 0 481*aed035abSart printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i, 482*aed035abSart memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage); 483*aed035abSart #endif 484*aed035abSart totalphysmem += memc->mddt_pg_cnt; 485*aed035abSart if (mem_cluster_cnt < VM_PHYSSEG_MAX) { /* XXX */ 486*aed035abSart mem_clusters[mem_cluster_cnt].start = 487*aed035abSart ptoa(memc->mddt_pfn); 488*aed035abSart mem_clusters[mem_cluster_cnt].size = 489*aed035abSart ptoa(memc->mddt_pg_cnt); 490*aed035abSart if (memc->mddt_usage & MDDT_mbz || 491*aed035abSart memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */ 492*aed035abSart memc->mddt_usage & MDDT_PALCODE) 493*aed035abSart mem_clusters[mem_cluster_cnt].size |= 494*aed035abSart VM_PROT_READ; 495*aed035abSart else 496*aed035abSart mem_clusters[mem_cluster_cnt].size |= 497*aed035abSart VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; 498*aed035abSart mem_cluster_cnt++; 499*aed035abSart } 500*aed035abSart 501*aed035abSart if (memc->mddt_usage & MDDT_mbz) { 502*aed035abSart mddtweird = 1; 503*aed035abSart printf("WARNING: mem cluster %d has weird " 504*aed035abSart "usage 0x%lx\n", i, memc->mddt_usage); 505*aed035abSart unknownmem += memc->mddt_pg_cnt; 506*aed035abSart continue; 507*aed035abSart } 508*aed035abSart if (memc->mddt_usage & MDDT_NONVOLATILE) { 509*aed035abSart /* XXX should handle these... */ 510*aed035abSart printf("WARNING: skipping non-volatile mem " 511*aed035abSart "cluster %d\n", i); 512*aed035abSart unusedmem += memc->mddt_pg_cnt; 513*aed035abSart continue; 514*aed035abSart } 515*aed035abSart if (memc->mddt_usage & MDDT_PALCODE) { 516*aed035abSart resvmem += memc->mddt_pg_cnt; 517*aed035abSart continue; 518*aed035abSart } 519*aed035abSart 520*aed035abSart /* 521*aed035abSart * We have a memory cluster available for system 522*aed035abSart * software use. We must determine if this cluster 523*aed035abSart * holds the kernel. 524*aed035abSart */ 525*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 526*aed035abSart /* 527*aed035abSart * XXX If the kernel uses the PROM console, we only use the 528*aed035abSart * XXX memory after the kernel in the first system segment, 529*aed035abSart * XXX to avoid clobbering prom mapping, data, etc. 530*aed035abSart */ 531*aed035abSart if (!pmap_uses_prom_console() || physmem == 0) { 532*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 533*aed035abSart physmem += memc->mddt_pg_cnt; 534*aed035abSart pfn0 = memc->mddt_pfn; 535*aed035abSart pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt; 536*aed035abSart if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) { 537*aed035abSart /* 538*aed035abSart * Must compute the location of the kernel 539*aed035abSart * within the segment. 540*aed035abSart */ 541*aed035abSart #if 0 542*aed035abSart printf("Cluster %d contains kernel\n", i); 543*aed035abSart #endif 544*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 545*aed035abSart if (!pmap_uses_prom_console()) { 546*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 547*aed035abSart if (pfn0 < kernstartpfn) { 548*aed035abSart /* 549*aed035abSart * There is a chunk before the kernel. 550*aed035abSart */ 551*aed035abSart #if 0 552*aed035abSart printf("Loading chunk before kernel: " 553*aed035abSart "0x%lx / 0x%lx\n", pfn0, kernstartpfn); 554*aed035abSart #endif 555*aed035abSart uvm_page_physload(pfn0, kernstartpfn, 556*aed035abSart pfn0, kernstartpfn, VM_FREELIST_DEFAULT); 557*aed035abSart } 558*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 559*aed035abSart } 560*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 561*aed035abSart if (kernendpfn < pfn1) { 562*aed035abSart /* 563*aed035abSart * There is a chunk after the kernel. 564*aed035abSart */ 565*aed035abSart #if 0 566*aed035abSart printf("Loading chunk after kernel: " 567*aed035abSart "0x%lx / 0x%lx\n", kernendpfn, pfn1); 568*aed035abSart #endif 569*aed035abSart uvm_page_physload(kernendpfn, pfn1, 570*aed035abSart kernendpfn, pfn1, VM_FREELIST_DEFAULT); 571*aed035abSart } 572*aed035abSart } else { 573*aed035abSart /* 574*aed035abSart * Just load this cluster as one chunk. 575*aed035abSart */ 576*aed035abSart #if 0 577*aed035abSart printf("Loading cluster %d: 0x%lx / 0x%lx\n", i, 578*aed035abSart pfn0, pfn1); 579*aed035abSart #endif 580*aed035abSart uvm_page_physload(pfn0, pfn1, pfn0, pfn1, 581*aed035abSart VM_FREELIST_DEFAULT); 582*aed035abSart } 583*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE 584*aed035abSart } 585*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */ 586*aed035abSart } 587*aed035abSart 588*aed035abSart /* 589*aed035abSart * Dump out the MDDT if it looks odd... 590*aed035abSart */ 591df930be7Sderaadt if (mddtweird) { 592df930be7Sderaadt printf("\n"); 593df930be7Sderaadt printf("complete memory cluster information:\n"); 594df930be7Sderaadt for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 595df930be7Sderaadt printf("mddt %d:\n", i); 596df930be7Sderaadt printf("\tpfn %lx\n", 597df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pfn); 598df930be7Sderaadt printf("\tcnt %lx\n", 599df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_cnt); 600df930be7Sderaadt printf("\ttest %lx\n", 601df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_test); 602df930be7Sderaadt printf("\tbva %lx\n", 603df930be7Sderaadt mddtp->mddt_clusters[i].mddt_v_bitaddr); 604df930be7Sderaadt printf("\tbpa %lx\n", 605df930be7Sderaadt mddtp->mddt_clusters[i].mddt_p_bitaddr); 606df930be7Sderaadt printf("\tbcksum %lx\n", 607df930be7Sderaadt mddtp->mddt_clusters[i].mddt_bit_cksum); 608df930be7Sderaadt printf("\tusage %lx\n", 609df930be7Sderaadt mddtp->mddt_clusters[i].mddt_usage); 610df930be7Sderaadt } 611df930be7Sderaadt printf("\n"); 612df930be7Sderaadt } 613df930be7Sderaadt 614df930be7Sderaadt if (totalphysmem == 0) 615df930be7Sderaadt panic("can't happen: system seems to have no memory!"); 616df930be7Sderaadt maxmem = physmem; 617df930be7Sderaadt #if 0 618df930be7Sderaadt printf("totalphysmem = %d\n", totalphysmem); 619df930be7Sderaadt printf("physmem = %d\n", physmem); 620df930be7Sderaadt printf("resvmem = %d\n", resvmem); 621df930be7Sderaadt printf("unusedmem = %d\n", unusedmem); 622df930be7Sderaadt printf("unknownmem = %d\n", unknownmem); 623df930be7Sderaadt #endif 624df930be7Sderaadt 625df930be7Sderaadt /* 626*aed035abSart * Initialize error message buffer (at end of core). 627df930be7Sderaadt */ 628*aed035abSart { 629*aed035abSart vsize_t sz = (vsize_t)round_page(MSGBUFSIZE); 630*aed035abSart vsize_t reqsz = sz; 631df930be7Sderaadt 632*aed035abSart vps = &vm_physmem[vm_nphysseg - 1]; 633e1da84e1Salex 634*aed035abSart /* shrink so that it'll fit in the last segment */ 635*aed035abSart if ((vps->avail_end - vps->avail_start) < atop(sz)) 636*aed035abSart sz = ptoa(vps->avail_end - vps->avail_start); 637*aed035abSart 638*aed035abSart vps->end -= atop(sz); 639*aed035abSart vps->avail_end -= atop(sz); 640*aed035abSart initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz); 641*aed035abSart 642*aed035abSart /* Remove the last segment if it now has no pages. */ 643*aed035abSart if (vps->start == vps->end) 644*aed035abSart vm_nphysseg--; 645*aed035abSart 646*aed035abSart /* warn if the message buffer had to be shrunk */ 647*aed035abSart if (sz != reqsz) 648*aed035abSart printf("WARNING: %ld bytes not available for msgbuf " 649*aed035abSart "in last cluster (%ld used)\n", reqsz, sz); 650*aed035abSart 651*aed035abSart } 652*aed035abSart 653df930be7Sderaadt /* 654df930be7Sderaadt * Init mapping for u page(s) for proc 0 655df930be7Sderaadt */ 656*aed035abSart proc0.p_addr = proc0paddr = 657*aed035abSart (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL); 658df930be7Sderaadt 659df930be7Sderaadt /* 660*aed035abSart * Allocate space for system data structures. These data structures 661*aed035abSart * are allocated here instead of cpu_startup() because physical 662*aed035abSart * memory is directly addressable. We don't have to map these into 663*aed035abSart * virtual address space. 664df930be7Sderaadt */ 665*aed035abSart size = (vsize_t)allocsys(NULL); 666*aed035abSart v = (caddr_t)pmap_steal_memory(size, NULL, NULL); 667*aed035abSart if ((allocsys(v) - v) != size) 668*aed035abSart panic("alpha_init: table size inconsistency"); 669df930be7Sderaadt 670df930be7Sderaadt /* 671df930be7Sderaadt * Clear allocated memory. 672df930be7Sderaadt */ 673*aed035abSart bzero(v, size); 674df930be7Sderaadt 675df930be7Sderaadt /* 676df930be7Sderaadt * Initialize the virtual memory system, and set the 677df930be7Sderaadt * page table base register in proc 0's PCB. 678df930be7Sderaadt */ 679*aed035abSart pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), 680*aed035abSart hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt); 681df930be7Sderaadt 682df930be7Sderaadt /* 683df930be7Sderaadt * Initialize the rest of proc 0's PCB, and cache its physical 684df930be7Sderaadt * address. 685df930be7Sderaadt */ 686df930be7Sderaadt proc0.p_md.md_pcbpaddr = 687*aed035abSart (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb); 688df930be7Sderaadt 689df930be7Sderaadt /* 690df930be7Sderaadt * Set the kernel sp, reserving space for an (empty) trapframe, 691df930be7Sderaadt * and make proc0's trapframe pointer point to it for sanity. 692df930be7Sderaadt */ 69350ce9ee0Sniklas proc0paddr->u_pcb.pcb_hw.apcb_ksp = 694df930be7Sderaadt (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe); 69574652a67Sniklas proc0.p_md.md_tf = 69674652a67Sniklas (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp; 69750ce9ee0Sniklas 698*aed035abSart /* 699*aed035abSart * Initialize the primary CPU's idle PCB to proc0's. In a 700*aed035abSart * MULTIPROCESSOR configuration, each CPU will later get 701*aed035abSart * its own idle PCB when autoconfiguration runs. 702*aed035abSart */ 703*aed035abSart ci->ci_idle_pcb = &proc0paddr->u_pcb; 704*aed035abSart ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr; 705df930be7Sderaadt 706df930be7Sderaadt /* 707df930be7Sderaadt * Look at arguments passed to us and compute boothowto. 708df930be7Sderaadt */ 709417eba8cSderaadt 710417eba8cSderaadt boothowto = RB_SINGLE; 711df930be7Sderaadt #ifdef KADB 712df930be7Sderaadt boothowto |= RB_KDB; 713df930be7Sderaadt #endif 714*aed035abSart for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { 715417eba8cSderaadt /* 716417eba8cSderaadt * Note that we'd really like to differentiate case here, 717417eba8cSderaadt * but the Alpha AXP Architecture Reference Manual 718417eba8cSderaadt * says that we shouldn't. 719417eba8cSderaadt */ 720df930be7Sderaadt switch (*p) { 721df930be7Sderaadt case 'a': /* autoboot */ 722417eba8cSderaadt case 'A': 723df930be7Sderaadt boothowto &= ~RB_SINGLE; 724df930be7Sderaadt break; 725df930be7Sderaadt 72612f8bbedSniklas case 'b': /* Enter DDB as soon as the console is initialised */ 72712f8bbedSniklas case 'B': 72812f8bbedSniklas boothowto |= RB_KDB; 72912f8bbedSniklas break; 73012f8bbedSniklas 73150ce9ee0Sniklas case 'c': /* enter user kernel configuration */ 73250ce9ee0Sniklas case 'C': 73350ce9ee0Sniklas boothowto |= RB_CONFIG; 73450ce9ee0Sniklas break; 73550ce9ee0Sniklas 73650ce9ee0Sniklas #ifdef DEBUG 73750ce9ee0Sniklas case 'd': /* crash dump immediately after autoconfig */ 73850ce9ee0Sniklas case 'D': 73950ce9ee0Sniklas boothowto |= RB_DUMP; 74050ce9ee0Sniklas break; 74150ce9ee0Sniklas #endif 74250ce9ee0Sniklas 74350ce9ee0Sniklas case 'h': /* always halt, never reboot */ 74450ce9ee0Sniklas case 'H': 74550ce9ee0Sniklas boothowto |= RB_HALT; 746df930be7Sderaadt break; 747df930be7Sderaadt 748417eba8cSderaadt #if 0 749417eba8cSderaadt case 'm': /* mini root present in memory */ 750417eba8cSderaadt case 'M': 751417eba8cSderaadt boothowto |= RB_MINIROOT; 752417eba8cSderaadt break; 753417eba8cSderaadt #endif 75450ce9ee0Sniklas 75550ce9ee0Sniklas case 'n': /* askname */ 75650ce9ee0Sniklas case 'N': 75750ce9ee0Sniklas boothowto |= RB_ASKNAME; 75850ce9ee0Sniklas break; 759*aed035abSart 760*aed035abSart case 's': /* single-user (default, supported for sanity) */ 761*aed035abSart case 'S': 762*aed035abSart boothowto |= RB_SINGLE; 763*aed035abSart break; 764*aed035abSart 765*aed035abSart case '-': 766*aed035abSart /* 767*aed035abSart * Just ignore this. It's not required, but it's 768*aed035abSart * common for it to be passed regardless. 769*aed035abSart */ 770*aed035abSart break; 771*aed035abSart 772*aed035abSart default: 773*aed035abSart printf("Unrecognized boot flag '%c'.\n", *p); 774*aed035abSart break; 775df930be7Sderaadt } 776df930be7Sderaadt } 777df930be7Sderaadt 778*aed035abSart 779df930be7Sderaadt /* 780df930be7Sderaadt * Figure out the number of cpus in the box, from RPB fields. 781df930be7Sderaadt * Really. We mean it. 782df930be7Sderaadt */ 783df930be7Sderaadt for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { 784df930be7Sderaadt struct pcs *pcsp; 785df930be7Sderaadt 786*aed035abSart pcsp = LOCATE_PCS(hwrpb, i); 787df930be7Sderaadt if ((pcsp->pcs_flags & PCS_PP) != 0) 788df930be7Sderaadt ncpus++; 789df930be7Sderaadt } 790*aed035abSart 791*aed035abSart /* 792*aed035abSart * Initialize debuggers, and break into them if appropriate. 793*aed035abSart */ 794*aed035abSart #ifdef DDB 795*aed035abSart ddb_init(); 796*aed035abSart 797*aed035abSart if (boothowto & RB_KDB) 798*aed035abSart Debugger(); 799*aed035abSart #endif 800*aed035abSart #ifdef KGDB 801*aed035abSart if (boothowto & RB_KDB) 802*aed035abSart kgdb_connect(0); 803*aed035abSart #endif 804*aed035abSart /* 805*aed035abSart * Figure out our clock frequency, from RPB fields. 806*aed035abSart */ 807*aed035abSart hz = hwrpb->rpb_intr_freq >> 12; 808*aed035abSart if (!(60 <= hz && hz <= 10240)) { 809*aed035abSart hz = 1024; 810*aed035abSart #ifdef DIAGNOSTIC 811*aed035abSart printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n", 812*aed035abSart hwrpb->rpb_intr_freq, hz); 813*aed035abSart #endif 814*aed035abSart } 815*aed035abSart } 816*aed035abSart 817*aed035abSart caddr_t 818*aed035abSart allocsys(v) 819*aed035abSart caddr_t v; 820*aed035abSart { 821*aed035abSart /* 822*aed035abSart * Allocate space for system data structures. 823*aed035abSart * The first available kernel virtual address is in "v". 824*aed035abSart * As pages of kernel virtual memory are allocated, "v" is incremented. 825*aed035abSart * 826*aed035abSart * These data structures are allocated here instead of cpu_startup() 827*aed035abSart * because physical memory is directly addressable. We don't have 828*aed035abSart * to map these into virtual address space. 829*aed035abSart */ 830*aed035abSart #define valloc(name, type, num) \ 831*aed035abSart (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num)) 832*aed035abSart 833*aed035abSart #ifdef REAL_CLISTS 834*aed035abSart valloc(cfree, struct cblock, nclist); 835*aed035abSart #endif 836*aed035abSart valloc(timeouts, struct timeout, ntimeout); 837*aed035abSart #ifdef SYSVSHM 838*aed035abSart valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 839*aed035abSart #endif 840*aed035abSart #ifdef SYSVSEM 841*aed035abSart valloc(sema, struct semid_ds, seminfo.semmni); 842*aed035abSart valloc(sem, struct sem, seminfo.semmns); 843*aed035abSart /* This is pretty disgusting! */ 844*aed035abSart valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 845*aed035abSart #endif 846*aed035abSart #ifdef SYSVMSG 847*aed035abSart valloc(msgpool, char, msginfo.msgmax); 848*aed035abSart valloc(msgmaps, struct msgmap, msginfo.msgseg); 849*aed035abSart valloc(msghdrs, struct msg, msginfo.msgtql); 850*aed035abSart valloc(msqids, struct msqid_ds, msginfo.msgmni); 851*aed035abSart #endif 852*aed035abSart 853*aed035abSart #ifndef BUFCACHEPERCENT 854*aed035abSart #define BUFCACHEPERCENT 10 855*aed035abSart #endif 856*aed035abSart /* 857*aed035abSart * Determine how many buffers to allocate. 858*aed035abSart * We allocate 10% of memory for buffer space. Insure a 859*aed035abSart * minimum of 16 buffers. 860*aed035abSart */ 861*aed035abSart if (bufpages == 0) 862*aed035abSart bufpages = (physmem / ((100/BUFCACHEPERCENT) / CLSIZE)); 863*aed035abSart if (nbuf == 0) { 864*aed035abSart nbuf = bufpages; 865*aed035abSart if (nbuf < 16) 866*aed035abSart nbuf = 16; 867*aed035abSart } 868*aed035abSart valloc(buf, struct buf, nbuf); 869*aed035abSart 870*aed035abSart #undef valloc 871*aed035abSart 872*aed035abSart return v; 873df930be7Sderaadt } 874df930be7Sderaadt 875417eba8cSderaadt void 876df930be7Sderaadt consinit() 877df930be7Sderaadt { 878*aed035abSart 879*aed035abSart /* 880*aed035abSart * Everything related to console initialization is done 881*aed035abSart * in alpha_init(). 882*aed035abSart */ 883*aed035abSart #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE) 884*aed035abSart printf("consinit: %susing prom console\n", 885*aed035abSart pmap_uses_prom_console() ? "" : "not "); 88612f8bbedSniklas #endif 887df930be7Sderaadt } 888df930be7Sderaadt 889417eba8cSderaadt void 890df930be7Sderaadt cpu_startup() 891df930be7Sderaadt { 892df930be7Sderaadt register unsigned i; 893df930be7Sderaadt int base, residual; 894*aed035abSart vaddr_t minaddr, maxaddr; 895*aed035abSart vsize_t size; 89650ce9ee0Sniklas #if defined(DEBUG) 897df930be7Sderaadt extern int pmapdebug; 898df930be7Sderaadt int opmapdebug = pmapdebug; 899df930be7Sderaadt 900df930be7Sderaadt pmapdebug = 0; 901df930be7Sderaadt #endif 902df930be7Sderaadt 903df930be7Sderaadt /* 904df930be7Sderaadt * Good {morning,afternoon,evening,night}. 905df930be7Sderaadt */ 906df930be7Sderaadt printf(version); 907df930be7Sderaadt identifycpu(); 908*aed035abSart printf("total memory = %d\n", ptoa(totalphysmem)); 909*aed035abSart printf("(%d reserved for PROM, ", ptoa(resvmem)); 910*aed035abSart printf("%d used by OpenBSD)\n", ptoa(physmem)); 911*aed035abSart if (unusedmem) { 912*aed035abSart printf("WARNING: unused memory = %d\n", ptoa(unusedmem)); 913*aed035abSart } 914*aed035abSart if (unknownmem) { 915*aed035abSart printf("WARNING: %d of memory with unknown purpose\n", ptoa(unknownmem)); 916*aed035abSart } 917df930be7Sderaadt 918df930be7Sderaadt /* 919df930be7Sderaadt * Allocate virtual address space for file I/O buffers. 920df930be7Sderaadt * Note they are different than the array of headers, 'buf', 921df930be7Sderaadt * and usually occupy more virtual memory than physical. 922df930be7Sderaadt */ 923df930be7Sderaadt size = MAXBSIZE * nbuf; 924*aed035abSart if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), 925*aed035abSart NULL, UVM_UNKNOWN_OFFSET, 926*aed035abSart UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 927*aed035abSart UVM_ADV_NORMAL, 0)) != KERN_SUCCESS) 928*aed035abSart panic("startup: cannot allocate VM for buffers"); 929df930be7Sderaadt base = bufpages / nbuf; 930df930be7Sderaadt residual = bufpages % nbuf; 931df930be7Sderaadt for (i = 0; i < nbuf; i++) { 932*aed035abSart vsize_t curbufsize; 933*aed035abSart vaddr_t curbuf; 934*aed035abSart struct vm_page *pg; 935df930be7Sderaadt 936df930be7Sderaadt /* 937*aed035abSart * Each buffer has MAXBSIZE bytes of VM space allocated. Of 938*aed035abSart * that MAXBSIZE space, we allocate and map (base+1) pages 939*aed035abSart * for the first "residual" buffers, and then we allocate 940*aed035abSart * "base" pages for the rest. 941df930be7Sderaadt */ 942*aed035abSart curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 943*aed035abSart curbufsize = NBPG * ((i < residual) ? (base+1) : base); 944*aed035abSart 945*aed035abSart while (curbufsize) { 946*aed035abSart pg = uvm_pagealloc(NULL, 0, NULL, 0); 947*aed035abSart if (pg == NULL) 948*aed035abSart panic("cpu_startup: not enough memory for " 949*aed035abSart "buffer cache"); 950*aed035abSart pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 951*aed035abSart VM_PROT_READ|VM_PROT_WRITE); 952*aed035abSart curbuf += PAGE_SIZE; 953*aed035abSart curbufsize -= PAGE_SIZE; 954*aed035abSart } 955df930be7Sderaadt } 956df930be7Sderaadt /* 957df930be7Sderaadt * Allocate a submap for exec arguments. This map effectively 958df930be7Sderaadt * limits the number of processes exec'ing at any time. 959df930be7Sderaadt */ 960*aed035abSart exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 961*aed035abSart 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 962df930be7Sderaadt 963df930be7Sderaadt /* 964df930be7Sderaadt * Allocate a submap for physio 965df930be7Sderaadt */ 966*aed035abSart phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 967*aed035abSart VM_PHYS_SIZE, 0, FALSE, NULL); 968df930be7Sderaadt 969df930be7Sderaadt /* 970df930be7Sderaadt * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 971df930be7Sderaadt * we use the more space efficient malloc in place of kmem_alloc. 972df930be7Sderaadt */ 973df930be7Sderaadt mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 974df930be7Sderaadt M_MBUF, M_NOWAIT); 975df930be7Sderaadt bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 976*aed035abSart mb_map = uvm_km_suballoc(kernel_map, (vaddr_t *)&mbutl, &maxaddr, 977*aed035abSart VM_MBUF_SIZE, VM_MAP_INTRSAFE, FALSE, NULL); 978*aed035abSart 979df930be7Sderaadt /* 980d66eba84Sart * Initialize timeouts 981df930be7Sderaadt */ 982d66eba84Sart timeout_init(); 983df930be7Sderaadt 98450ce9ee0Sniklas #if defined(DEBUG) 985df930be7Sderaadt pmapdebug = opmapdebug; 986df930be7Sderaadt #endif 987*aed035abSart printf("avail memory = %d\n", ptoa(uvmexp.free)); 988*aed035abSart #if 0 989*aed035abSart { 990*aed035abSart extern u_long pmap_pages_stolen; 991*aed035abSart 992*aed035abSart printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE); 993*aed035abSart } 994*aed035abSart #endif 995*aed035abSart printf("using %ld buffers containing %d of memory\n", (long)nbuf, bufpages * NBPG); 996df930be7Sderaadt 997df930be7Sderaadt /* 998df930be7Sderaadt * Set up buffers, so they can be used to read disk labels. 999df930be7Sderaadt */ 1000df930be7Sderaadt bufinit(); 1001df930be7Sderaadt 1002df930be7Sderaadt /* 1003df930be7Sderaadt * Configure the system. 1004df930be7Sderaadt */ 100541033391Sderaadt if (boothowto & RB_CONFIG) { 100641033391Sderaadt #ifdef BOOT_CONFIG 100741033391Sderaadt user_config(); 100841033391Sderaadt #else 100941033391Sderaadt printf("kernel does not support -c; continuing..\n"); 101041033391Sderaadt #endif 101141033391Sderaadt } 1012df930be7Sderaadt configure(); 101350ce9ee0Sniklas 101450ce9ee0Sniklas /* 1015*aed035abSart * Set up the HWPCB so that it's safe to configure secondary 1016*aed035abSart * CPUs. 101750ce9ee0Sniklas */ 1018*aed035abSart hwrpb_primary_init(); 1019*aed035abSart } 1020*aed035abSart 1021*aed035abSart /* 1022*aed035abSart * Retrieve the platform name from the DSR. 1023*aed035abSart */ 1024*aed035abSart const char * 1025*aed035abSart alpha_dsr_sysname() 1026*aed035abSart { 1027*aed035abSart struct dsrdb *dsr; 1028*aed035abSart const char *sysname; 1029*aed035abSart 1030*aed035abSart /* 1031*aed035abSart * DSR does not exist on early HWRPB versions. 1032*aed035abSart */ 1033*aed035abSart if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS) 1034*aed035abSart return (NULL); 1035*aed035abSart 1036*aed035abSart dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off); 1037*aed035abSart sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off + 1038*aed035abSart sizeof(u_int64_t))); 1039*aed035abSart return (sysname); 1040*aed035abSart } 1041*aed035abSart 1042*aed035abSart /* 1043*aed035abSart * Lookup the system specified system variation in the provided table, 1044*aed035abSart * returning the model string on match. 1045*aed035abSart */ 1046*aed035abSart const char * 1047*aed035abSart alpha_variation_name(variation, avtp) 1048*aed035abSart u_int64_t variation; 1049*aed035abSart const struct alpha_variation_table *avtp; 1050*aed035abSart { 1051*aed035abSart int i; 1052*aed035abSart 1053*aed035abSart for (i = 0; avtp[i].avt_model != NULL; i++) 1054*aed035abSart if (avtp[i].avt_variation == variation) 1055*aed035abSart return (avtp[i].avt_model); 1056*aed035abSart return (NULL); 1057*aed035abSart } 1058*aed035abSart 1059*aed035abSart /* 1060*aed035abSart * Generate a default platform name based for unknown system variations. 1061*aed035abSart */ 1062*aed035abSart const char * 1063*aed035abSart alpha_unknown_sysname() 1064*aed035abSart { 1065*aed035abSart static char s[128]; /* safe size */ 1066*aed035abSart 1067*aed035abSart sprintf(s, "%s family, unknown model variation 0x%lx", 1068*aed035abSart platform.family, hwrpb->rpb_variation & SV_ST_MASK); 1069*aed035abSart return ((const char *)s); 1070df930be7Sderaadt } 1071df930be7Sderaadt 107250ce9ee0Sniklas void 1073df930be7Sderaadt identifycpu() 1074df930be7Sderaadt { 1075*aed035abSart char *s; 1076df930be7Sderaadt 1077df930be7Sderaadt /* 1078df930be7Sderaadt * print out CPU identification information. 1079df930be7Sderaadt */ 1080*aed035abSart printf("%s", cpu_model); 1081*aed035abSart for(s = cpu_model; *s; ++s) 1082*aed035abSart if(strncasecmp(s, "MHz", 3) == 0) 1083*aed035abSart goto skipMHz; 1084*aed035abSart printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000); 1085*aed035abSart skipMHz: 1086*aed035abSart printf("\n"); 108750ce9ee0Sniklas printf("%ld byte page size, %d processor%s.\n", 1088df930be7Sderaadt hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s"); 1089df930be7Sderaadt #if 0 1090df930be7Sderaadt /* this isn't defined for any systems that we run on? */ 1091df930be7Sderaadt printf("serial number 0x%lx 0x%lx\n", 1092df930be7Sderaadt ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]); 1093df930be7Sderaadt 1094df930be7Sderaadt /* and these aren't particularly useful! */ 1095df930be7Sderaadt printf("variation: 0x%lx, revision 0x%lx\n", 1096df930be7Sderaadt hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision); 1097df930be7Sderaadt #endif 1098df930be7Sderaadt } 1099df930be7Sderaadt 1100df930be7Sderaadt int waittime = -1; 1101df930be7Sderaadt struct pcb dumppcb; 1102df930be7Sderaadt 1103417eba8cSderaadt void 1104*aed035abSart boot(howto) 1105df930be7Sderaadt int howto; 1106df930be7Sderaadt { 1107df930be7Sderaadt extern int cold; 1108df930be7Sderaadt 1109*aed035abSart #if defined(MULTIPROCESSOR) 1110*aed035abSart #if 0 /* XXX See below. */ 1111*aed035abSart u_long cpu_id; 1112*aed035abSart #endif 1113*aed035abSart #endif 1114*aed035abSart 1115*aed035abSart #if defined(MULTIPROCESSOR) 1116*aed035abSart /* We must be running on the primary CPU. */ 1117*aed035abSart if (alpha_pal_whami() != hwrpb->rpb_primary_cpu_id) 1118*aed035abSart panic("cpu_reboot: not on primary CPU!"); 1119*aed035abSart #endif 1120*aed035abSart 1121df930be7Sderaadt /* If system is cold, just halt. */ 1122df930be7Sderaadt if (cold) { 1123df930be7Sderaadt howto |= RB_HALT; 1124df930be7Sderaadt goto haltsys; 1125df930be7Sderaadt } 1126df930be7Sderaadt 112750ce9ee0Sniklas /* If "always halt" was specified as a boot flag, obey. */ 112850ce9ee0Sniklas if ((boothowto & RB_HALT) != 0) 112950ce9ee0Sniklas howto |= RB_HALT; 113050ce9ee0Sniklas 1131df930be7Sderaadt boothowto = howto; 1132df930be7Sderaadt if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 1133df930be7Sderaadt waittime = 0; 1134df930be7Sderaadt vfs_shutdown(); 1135df930be7Sderaadt /* 1136df930be7Sderaadt * If we've been adjusting the clock, the todr 1137*aed035abSart * will be out of synch; adjust it now. 1138df930be7Sderaadt */ 1139df930be7Sderaadt resettodr(); 1140df930be7Sderaadt } 1141df930be7Sderaadt 1142df930be7Sderaadt /* Disable interrupts. */ 1143df930be7Sderaadt splhigh(); 1144df930be7Sderaadt 1145df930be7Sderaadt /* If rebooting and a dump is requested do it. */ 114650ce9ee0Sniklas #if 0 114750ce9ee0Sniklas if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 114850ce9ee0Sniklas #else 114950ce9ee0Sniklas if (howto & RB_DUMP) 115050ce9ee0Sniklas #endif 1151df930be7Sderaadt dumpsys(); 1152df930be7Sderaadt 115334fbf6deSderaadt haltsys: 115434fbf6deSderaadt 1155df930be7Sderaadt /* run any shutdown hooks */ 1156df930be7Sderaadt doshutdownhooks(); 1157df930be7Sderaadt 1158*aed035abSart #if defined(MULTIPROCESSOR) 1159*aed035abSart #if 0 /* XXX doesn't work when called from here?! */ 1160*aed035abSart /* Kill off any secondary CPUs. */ 1161*aed035abSart for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) { 1162*aed035abSart if (cpu_id == hwrpb->rpb_primary_cpu_id || 1163*aed035abSart cpu_info[cpu_id].ci_softc == NULL) 1164*aed035abSart continue; 1165*aed035abSart cpu_halt_secondary(cpu_id); 1166*aed035abSart } 1167*aed035abSart #endif 1168*aed035abSart #endif 1169*aed035abSart 1170df930be7Sderaadt #ifdef BOOTKEY 1171df930be7Sderaadt printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot"); 1172*aed035abSart cnpollc(1); /* for proper keyboard command handling */ 1173df930be7Sderaadt cngetc(); 1174*aed035abSart cnpollc(0); 1175df930be7Sderaadt printf("\n"); 1176df930be7Sderaadt #endif 1177df930be7Sderaadt 1178*aed035abSart /* Finally, powerdown/halt/reboot the system. */ 1179*aed035abSart if ((howto & RB_POWERDOWN) == RB_POWERDOWN && 1180*aed035abSart platform.powerdown != NULL) { 1181*aed035abSart (*platform.powerdown)(); 1182*aed035abSart printf("WARNING: powerdown failed!\n"); 1183*aed035abSart } 1184df930be7Sderaadt printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 1185df930be7Sderaadt prom_halt(howto & RB_HALT); 1186df930be7Sderaadt /*NOTREACHED*/ 1187df930be7Sderaadt } 1188df930be7Sderaadt 1189df930be7Sderaadt /* 1190df930be7Sderaadt * These variables are needed by /sbin/savecore 1191df930be7Sderaadt */ 1192df930be7Sderaadt u_long dumpmag = 0x8fca0101; /* magic number */ 1193df930be7Sderaadt int dumpsize = 0; /* pages */ 1194df930be7Sderaadt long dumplo = 0; /* blocks */ 1195df930be7Sderaadt 1196df930be7Sderaadt /* 119750ce9ee0Sniklas * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. 119850ce9ee0Sniklas */ 119950ce9ee0Sniklas int 120050ce9ee0Sniklas cpu_dumpsize() 120150ce9ee0Sniklas { 120250ce9ee0Sniklas int size; 120350ce9ee0Sniklas 1204*aed035abSart size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) + 1205*aed035abSart ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); 120650ce9ee0Sniklas if (roundup(size, dbtob(1)) != dbtob(1)) 120750ce9ee0Sniklas return -1; 120850ce9ee0Sniklas 120950ce9ee0Sniklas return (1); 121050ce9ee0Sniklas } 121150ce9ee0Sniklas 121250ce9ee0Sniklas /* 1213*aed035abSart * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped. 1214*aed035abSart */ 1215*aed035abSart u_long 1216*aed035abSart cpu_dump_mempagecnt() 1217*aed035abSart { 1218*aed035abSart u_long i, n; 1219*aed035abSart 1220*aed035abSart n = 0; 1221*aed035abSart for (i = 0; i < mem_cluster_cnt; i++) 1222*aed035abSart n += atop(mem_clusters[i].size); 1223*aed035abSart return (n); 1224*aed035abSart } 1225*aed035abSart 1226*aed035abSart /* 122750ce9ee0Sniklas * cpu_dump: dump machine-dependent kernel core dump headers. 122850ce9ee0Sniklas */ 122950ce9ee0Sniklas int 123050ce9ee0Sniklas cpu_dump() 123150ce9ee0Sniklas { 123250ce9ee0Sniklas int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 1233*aed035abSart char buf[dbtob(1)]; 123450ce9ee0Sniklas kcore_seg_t *segp; 123550ce9ee0Sniklas cpu_kcore_hdr_t *cpuhdrp; 1236*aed035abSart phys_ram_seg_t *memsegp; 1237*aed035abSart int i; 123850ce9ee0Sniklas 123950ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 124050ce9ee0Sniklas 1241*aed035abSart bzero(buf, sizeof buf); 124250ce9ee0Sniklas segp = (kcore_seg_t *)buf; 1243*aed035abSart cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; 1244*aed035abSart memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) + 1245*aed035abSart ALIGN(sizeof(*cpuhdrp))]; 124650ce9ee0Sniklas 124750ce9ee0Sniklas /* 124850ce9ee0Sniklas * Generate a segment header. 124950ce9ee0Sniklas */ 125050ce9ee0Sniklas CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 125150ce9ee0Sniklas segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); 125250ce9ee0Sniklas 125350ce9ee0Sniklas /* 1254*aed035abSart * Add the machine-dependent header info. 125550ce9ee0Sniklas */ 1256*aed035abSart cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map); 125750ce9ee0Sniklas cpuhdrp->page_size = PAGE_SIZE; 1258*aed035abSart cpuhdrp->nmemsegs = mem_cluster_cnt; 1259*aed035abSart 1260*aed035abSart /* 1261*aed035abSart * Fill in the memory segment descriptors. 1262*aed035abSart */ 1263*aed035abSart for (i = 0; i < mem_cluster_cnt; i++) { 1264*aed035abSart memsegp[i].start = mem_clusters[i].start; 1265*aed035abSart memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK; 1266*aed035abSart } 126750ce9ee0Sniklas 126850ce9ee0Sniklas return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1))); 126950ce9ee0Sniklas } 127050ce9ee0Sniklas 127150ce9ee0Sniklas /* 1272*aed035abSart * This is called by main to set dumplo and dumpsize. 1273*aed035abSart * Dumps always skip the first NBPG of disk space 1274df930be7Sderaadt * in case there might be a disk label stored there. 1275df930be7Sderaadt * If there is extra space, put dump at the end to 1276df930be7Sderaadt * reduce the chance that swapping trashes it. 1277df930be7Sderaadt */ 1278df930be7Sderaadt void 1279df930be7Sderaadt dumpconf() 1280df930be7Sderaadt { 128150ce9ee0Sniklas int nblks, dumpblks; /* size of dump area */ 1282df930be7Sderaadt int maj; 1283df930be7Sderaadt 1284df930be7Sderaadt if (dumpdev == NODEV) 128550ce9ee0Sniklas goto bad; 1286df930be7Sderaadt maj = major(dumpdev); 1287df930be7Sderaadt if (maj < 0 || maj >= nblkdev) 1288df930be7Sderaadt panic("dumpconf: bad dumpdev=0x%x", dumpdev); 1289df930be7Sderaadt if (bdevsw[maj].d_psize == NULL) 129050ce9ee0Sniklas goto bad; 1291df930be7Sderaadt nblks = (*bdevsw[maj].d_psize)(dumpdev); 1292df930be7Sderaadt if (nblks <= ctod(1)) 129350ce9ee0Sniklas goto bad; 129450ce9ee0Sniklas 129550ce9ee0Sniklas dumpblks = cpu_dumpsize(); 129650ce9ee0Sniklas if (dumpblks < 0) 129750ce9ee0Sniklas goto bad; 1298*aed035abSart dumpblks += ctod(cpu_dump_mempagecnt()); 129950ce9ee0Sniklas 130050ce9ee0Sniklas /* If dump won't fit (incl. room for possible label), punt. */ 130150ce9ee0Sniklas if (dumpblks > (nblks - ctod(1))) 130250ce9ee0Sniklas goto bad; 130350ce9ee0Sniklas 130450ce9ee0Sniklas /* Put dump at end of partition */ 130550ce9ee0Sniklas dumplo = nblks - dumpblks; 130650ce9ee0Sniklas 130750ce9ee0Sniklas /* dumpsize is in page units, and doesn't include headers. */ 1308*aed035abSart dumpsize = cpu_dump_mempagecnt(); 1309df930be7Sderaadt return; 1310df930be7Sderaadt 131150ce9ee0Sniklas bad: 131250ce9ee0Sniklas dumpsize = 0; 131350ce9ee0Sniklas return; 1314df930be7Sderaadt } 1315df930be7Sderaadt 1316df930be7Sderaadt /* 131750ce9ee0Sniklas * Dump the kernel's image to the swap partition. 1318df930be7Sderaadt */ 131950ce9ee0Sniklas #define BYTES_PER_DUMP NBPG 132050ce9ee0Sniklas 1321df930be7Sderaadt void 1322df930be7Sderaadt dumpsys() 1323df930be7Sderaadt { 1324*aed035abSart u_long totalbytesleft, bytes, i, n, memcl; 1325*aed035abSart u_long maddr; 1326*aed035abSart int psize; 132750ce9ee0Sniklas daddr_t blkno; 132850ce9ee0Sniklas int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 132950ce9ee0Sniklas int error; 1330067cbd75Sderaadt extern int msgbufmapped; 1331df930be7Sderaadt 133250ce9ee0Sniklas /* Save registers. */ 133350ce9ee0Sniklas savectx(&dumppcb); 133450ce9ee0Sniklas 133550ce9ee0Sniklas msgbufmapped = 0; /* don't record dump msgs in msgbuf */ 1336df930be7Sderaadt if (dumpdev == NODEV) 1337df930be7Sderaadt return; 133850ce9ee0Sniklas 133950ce9ee0Sniklas /* 134050ce9ee0Sniklas * For dumps during autoconfiguration, 134150ce9ee0Sniklas * if dump device has already configured... 134250ce9ee0Sniklas */ 1343df930be7Sderaadt if (dumpsize == 0) 134450ce9ee0Sniklas dumpconf(); 134550ce9ee0Sniklas if (dumplo <= 0) { 1346*aed035abSart printf("\ndump to dev %u,%u not possible\n", major(dumpdev), 1347*aed035abSart minor(dumpdev)); 1348df930be7Sderaadt return; 1349df930be7Sderaadt } 1350*aed035abSart printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), 1351*aed035abSart minor(dumpdev), dumplo); 1352df930be7Sderaadt 135350ce9ee0Sniklas psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 1354df930be7Sderaadt printf("dump "); 135550ce9ee0Sniklas if (psize == -1) { 135650ce9ee0Sniklas printf("area unavailable\n"); 135750ce9ee0Sniklas return; 135850ce9ee0Sniklas } 135950ce9ee0Sniklas 136050ce9ee0Sniklas /* XXX should purge all outstanding keystrokes. */ 136150ce9ee0Sniklas 136250ce9ee0Sniklas if ((error = cpu_dump()) != 0) 136350ce9ee0Sniklas goto err; 136450ce9ee0Sniklas 1365*aed035abSart totalbytesleft = ptoa(cpu_dump_mempagecnt()); 136650ce9ee0Sniklas blkno = dumplo + cpu_dumpsize(); 136750ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 136850ce9ee0Sniklas error = 0; 1369*aed035abSart 1370*aed035abSart for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { 1371*aed035abSart maddr = mem_clusters[memcl].start; 1372*aed035abSart bytes = mem_clusters[memcl].size & ~PAGE_MASK; 1373*aed035abSart 1374*aed035abSart for (i = 0; i < bytes; i += n, totalbytesleft -= n) { 137550ce9ee0Sniklas 137650ce9ee0Sniklas /* Print out how many MBs we to go. */ 1377*aed035abSart if ((totalbytesleft % (1024*1024)) == 0) 1378*aed035abSart printf("%ld ", totalbytesleft / (1024 * 1024)); 137950ce9ee0Sniklas 138050ce9ee0Sniklas /* Limit size for next transfer. */ 1381*aed035abSart n = bytes - i; 138250ce9ee0Sniklas if (n > BYTES_PER_DUMP) 138350ce9ee0Sniklas n = BYTES_PER_DUMP; 138450ce9ee0Sniklas 138550ce9ee0Sniklas error = (*dump)(dumpdev, blkno, 138650ce9ee0Sniklas (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n); 138750ce9ee0Sniklas if (error) 1388*aed035abSart goto err; 138950ce9ee0Sniklas maddr += n; 139050ce9ee0Sniklas blkno += btodb(n); /* XXX? */ 139150ce9ee0Sniklas 139250ce9ee0Sniklas /* XXX should look for keystrokes, to cancel. */ 139350ce9ee0Sniklas } 1394*aed035abSart } 139550ce9ee0Sniklas 139650ce9ee0Sniklas err: 139750ce9ee0Sniklas switch (error) { 1398df930be7Sderaadt 1399df930be7Sderaadt case ENXIO: 1400df930be7Sderaadt printf("device bad\n"); 1401df930be7Sderaadt break; 1402df930be7Sderaadt 1403df930be7Sderaadt case EFAULT: 1404df930be7Sderaadt printf("device not ready\n"); 1405df930be7Sderaadt break; 1406df930be7Sderaadt 1407df930be7Sderaadt case EINVAL: 1408df930be7Sderaadt printf("area improper\n"); 1409df930be7Sderaadt break; 1410df930be7Sderaadt 1411df930be7Sderaadt case EIO: 1412df930be7Sderaadt printf("i/o error\n"); 1413df930be7Sderaadt break; 1414df930be7Sderaadt 1415df930be7Sderaadt case EINTR: 1416df930be7Sderaadt printf("aborted from console\n"); 1417df930be7Sderaadt break; 1418df930be7Sderaadt 141950ce9ee0Sniklas case 0: 1420df930be7Sderaadt printf("succeeded\n"); 1421df930be7Sderaadt break; 142250ce9ee0Sniklas 142350ce9ee0Sniklas default: 142450ce9ee0Sniklas printf("error %d\n", error); 142550ce9ee0Sniklas break; 1426df930be7Sderaadt } 1427df930be7Sderaadt printf("\n\n"); 1428df930be7Sderaadt delay(1000); 1429df930be7Sderaadt } 1430df930be7Sderaadt 1431df930be7Sderaadt void 1432df930be7Sderaadt frametoreg(framep, regp) 1433df930be7Sderaadt struct trapframe *framep; 1434df930be7Sderaadt struct reg *regp; 1435df930be7Sderaadt { 1436df930be7Sderaadt 1437df930be7Sderaadt regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0]; 1438df930be7Sderaadt regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0]; 1439df930be7Sderaadt regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1]; 1440df930be7Sderaadt regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2]; 1441df930be7Sderaadt regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3]; 1442df930be7Sderaadt regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4]; 1443df930be7Sderaadt regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5]; 1444df930be7Sderaadt regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6]; 1445df930be7Sderaadt regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7]; 1446df930be7Sderaadt regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0]; 1447df930be7Sderaadt regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1]; 1448df930be7Sderaadt regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2]; 1449df930be7Sderaadt regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3]; 1450df930be7Sderaadt regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; 1451df930be7Sderaadt regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; 1452df930be7Sderaadt regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; 145350ce9ee0Sniklas regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; 145450ce9ee0Sniklas regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; 145550ce9ee0Sniklas regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; 1456df930be7Sderaadt regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; 1457df930be7Sderaadt regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; 1458df930be7Sderaadt regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; 1459df930be7Sderaadt regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8]; 1460df930be7Sderaadt regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9]; 1461df930be7Sderaadt regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10]; 1462df930be7Sderaadt regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11]; 1463df930be7Sderaadt regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; 1464df930be7Sderaadt regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; 1465df930be7Sderaadt regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; 146650ce9ee0Sniklas regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; 146750ce9ee0Sniklas /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ 1468df930be7Sderaadt regp->r_regs[R_ZERO] = 0; 1469df930be7Sderaadt } 1470df930be7Sderaadt 1471df930be7Sderaadt void 1472df930be7Sderaadt regtoframe(regp, framep) 1473df930be7Sderaadt struct reg *regp; 1474df930be7Sderaadt struct trapframe *framep; 1475df930be7Sderaadt { 1476df930be7Sderaadt 1477df930be7Sderaadt framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0]; 1478df930be7Sderaadt framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0]; 1479df930be7Sderaadt framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1]; 1480df930be7Sderaadt framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2]; 1481df930be7Sderaadt framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3]; 1482df930be7Sderaadt framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4]; 1483df930be7Sderaadt framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5]; 1484df930be7Sderaadt framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6]; 1485df930be7Sderaadt framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7]; 1486df930be7Sderaadt framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0]; 1487df930be7Sderaadt framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1]; 1488df930be7Sderaadt framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2]; 1489df930be7Sderaadt framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3]; 1490df930be7Sderaadt framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; 1491df930be7Sderaadt framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; 1492df930be7Sderaadt framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; 149350ce9ee0Sniklas framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; 149450ce9ee0Sniklas framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; 149550ce9ee0Sniklas framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; 1496df930be7Sderaadt framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; 1497df930be7Sderaadt framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; 1498df930be7Sderaadt framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; 1499df930be7Sderaadt framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8]; 1500df930be7Sderaadt framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9]; 1501df930be7Sderaadt framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10]; 1502df930be7Sderaadt framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11]; 1503df930be7Sderaadt framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; 1504df930be7Sderaadt framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; 1505df930be7Sderaadt framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; 150650ce9ee0Sniklas framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; 150750ce9ee0Sniklas /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ 1508df930be7Sderaadt /* ??? = regp->r_regs[R_ZERO]; */ 1509df930be7Sderaadt } 1510df930be7Sderaadt 1511df930be7Sderaadt void 1512df930be7Sderaadt printregs(regp) 1513df930be7Sderaadt struct reg *regp; 1514df930be7Sderaadt { 1515df930be7Sderaadt int i; 1516df930be7Sderaadt 1517df930be7Sderaadt for (i = 0; i < 32; i++) 1518df930be7Sderaadt printf("R%d:\t0x%016lx%s", i, regp->r_regs[i], 1519df930be7Sderaadt i & 1 ? "\n" : "\t"); 1520df930be7Sderaadt } 1521df930be7Sderaadt 1522df930be7Sderaadt void 1523df930be7Sderaadt regdump(framep) 1524df930be7Sderaadt struct trapframe *framep; 1525df930be7Sderaadt { 1526df930be7Sderaadt struct reg reg; 1527df930be7Sderaadt 1528df930be7Sderaadt frametoreg(framep, ®); 152950ce9ee0Sniklas reg.r_regs[R_SP] = alpha_pal_rdusp(); 153050ce9ee0Sniklas 1531df930be7Sderaadt printf("REGISTERS:\n"); 1532df930be7Sderaadt printregs(®); 1533df930be7Sderaadt } 1534df930be7Sderaadt 1535df930be7Sderaadt #ifdef DEBUG 1536df930be7Sderaadt int sigdebug = 0; 1537df930be7Sderaadt int sigpid = 0; 1538df930be7Sderaadt #define SDB_FOLLOW 0x01 1539df930be7Sderaadt #define SDB_KSTACK 0x02 1540df930be7Sderaadt #endif 1541df930be7Sderaadt 1542df930be7Sderaadt /* 1543df930be7Sderaadt * Send an interrupt to process. 1544df930be7Sderaadt */ 1545df930be7Sderaadt void 15465e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val) 1547df930be7Sderaadt sig_t catcher; 1548df930be7Sderaadt int sig, mask; 1549df930be7Sderaadt u_long code; 15505e1760a6Sderaadt int type; 15515e1760a6Sderaadt union sigval val; 1552df930be7Sderaadt { 1553df930be7Sderaadt struct proc *p = curproc; 1554df930be7Sderaadt struct sigcontext *scp, ksc; 1555df930be7Sderaadt struct trapframe *frame; 1556df930be7Sderaadt struct sigacts *psp = p->p_sigacts; 15572bf9c155Sderaadt int oonstack, fsize, rndfsize, kscsize; 1558df930be7Sderaadt extern char sigcode[], esigcode[]; 15592bf9c155Sderaadt siginfo_t *sip, ksi; 1560df930be7Sderaadt 1561df930be7Sderaadt frame = p->p_md.md_tf; 1562df930be7Sderaadt oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 1563df930be7Sderaadt fsize = sizeof ksc; 1564df930be7Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 15652bf9c155Sderaadt kscsize = rndfsize; 15662bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 15672bf9c155Sderaadt fsize += sizeof ksi; 15682bf9c155Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 15692bf9c155Sderaadt } 157074652a67Sniklas 1571df930be7Sderaadt /* 1572df930be7Sderaadt * Allocate and validate space for the signal handler 1573df930be7Sderaadt * context. Note that if the stack is in P0 space, the 1574*aed035abSart * call to uvm_grow() is a nop, and the useracc() check 1575df930be7Sderaadt * will fail if the process has not already allocated 1576df930be7Sderaadt * the space with a `brk'. 1577df930be7Sderaadt */ 1578df930be7Sderaadt if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 1579df930be7Sderaadt (psp->ps_sigonstack & sigmask(sig))) { 15808bc2093aSderaadt scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp + 1581df930be7Sderaadt psp->ps_sigstk.ss_size - rndfsize); 1582df930be7Sderaadt psp->ps_sigstk.ss_flags |= SS_ONSTACK; 1583df930be7Sderaadt } else 158450ce9ee0Sniklas scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize); 1585df930be7Sderaadt if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 1586*aed035abSart (void)uvm_grow(p, (u_long)scp); 1587df930be7Sderaadt #ifdef DEBUG 1588df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 158950ce9ee0Sniklas printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, 1590df930be7Sderaadt sig, &oonstack, scp); 1591df930be7Sderaadt #endif 1592*aed035abSart if (uvm_useracc((caddr_t)scp, fsize, B_WRITE) == 0) { 1593df930be7Sderaadt #ifdef DEBUG 1594df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1595*aed035abSart printf("sendsig(%d): uvm_useracc failed on sig %d\n", 1596df930be7Sderaadt p->p_pid, sig); 1597df930be7Sderaadt #endif 1598df930be7Sderaadt /* 1599df930be7Sderaadt * Process has trashed its stack; give it an illegal 1600df930be7Sderaadt * instruction to halt it in its tracks. 1601df930be7Sderaadt */ 1602df930be7Sderaadt SIGACTION(p, SIGILL) = SIG_DFL; 1603df930be7Sderaadt sig = sigmask(SIGILL); 1604df930be7Sderaadt p->p_sigignore &= ~sig; 1605df930be7Sderaadt p->p_sigcatch &= ~sig; 1606df930be7Sderaadt p->p_sigmask &= ~sig; 1607df930be7Sderaadt psignal(p, SIGILL); 1608df930be7Sderaadt return; 1609df930be7Sderaadt } 1610df930be7Sderaadt 1611df930be7Sderaadt /* 1612df930be7Sderaadt * Build the signal context to be used by sigreturn. 1613df930be7Sderaadt */ 1614df930be7Sderaadt ksc.sc_onstack = oonstack; 1615df930be7Sderaadt ksc.sc_mask = mask; 161650ce9ee0Sniklas ksc.sc_pc = frame->tf_regs[FRAME_PC]; 161750ce9ee0Sniklas ksc.sc_ps = frame->tf_regs[FRAME_PS]; 1618df930be7Sderaadt 1619df930be7Sderaadt /* copy the registers. */ 1620df930be7Sderaadt frametoreg(frame, (struct reg *)ksc.sc_regs); 1621df930be7Sderaadt ksc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ 162250ce9ee0Sniklas ksc.sc_regs[R_SP] = alpha_pal_rdusp(); 1623df930be7Sderaadt 1624df930be7Sderaadt /* save the floating-point state, if necessary, then copy it. */ 1625df930be7Sderaadt if (p == fpcurproc) { 162650ce9ee0Sniklas alpha_pal_wrfen(1); 1627df930be7Sderaadt savefpstate(&p->p_addr->u_pcb.pcb_fp); 162850ce9ee0Sniklas alpha_pal_wrfen(0); 1629df930be7Sderaadt fpcurproc = NULL; 1630df930be7Sderaadt } 1631df930be7Sderaadt ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED; 1632df930be7Sderaadt bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs, 1633df930be7Sderaadt sizeof(struct fpreg)); 1634df930be7Sderaadt ksc.sc_fp_control = 0; /* XXX ? */ 1635df930be7Sderaadt bzero(ksc.sc_reserved, sizeof ksc.sc_reserved); /* XXX */ 1636df930be7Sderaadt bzero(ksc.sc_xxx, sizeof ksc.sc_xxx); /* XXX */ 1637df930be7Sderaadt 1638df930be7Sderaadt 1639df930be7Sderaadt #ifdef COMPAT_OSF1 1640df930be7Sderaadt /* 1641df930be7Sderaadt * XXX Create an OSF/1-style sigcontext and associated goo. 1642df930be7Sderaadt */ 1643df930be7Sderaadt #endif 1644df930be7Sderaadt 16452bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 16462bf9c155Sderaadt initsiginfo(&ksi, sig, code, type, val); 16472bf9c155Sderaadt sip = (void *)scp + kscsize; 16482bf9c155Sderaadt (void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize); 16492bf9c155Sderaadt } 16502bf9c155Sderaadt 1651df930be7Sderaadt /* 1652df930be7Sderaadt * copy the frame out to userland. 1653df930be7Sderaadt */ 16542bf9c155Sderaadt (void) copyout((caddr_t)&ksc, (caddr_t)scp, kscsize); 1655df930be7Sderaadt #ifdef DEBUG 1656df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 165750ce9ee0Sniklas printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig, 1658df930be7Sderaadt scp, code); 1659df930be7Sderaadt #endif 1660df930be7Sderaadt 1661df930be7Sderaadt /* 1662df930be7Sderaadt * Set up the registers to return to sigcode. 1663df930be7Sderaadt */ 166450ce9ee0Sniklas frame->tf_regs[FRAME_PC] = 166550ce9ee0Sniklas (u_int64_t)PS_STRINGS - (esigcode - sigcode); 166650ce9ee0Sniklas frame->tf_regs[FRAME_A0] = sig; 16672bf9c155Sderaadt frame->tf_regs[FRAME_A1] = (psp->ps_siginfo & sigmask(sig)) ? 16682bf9c155Sderaadt (u_int64_t)sip : NULL; 166950ce9ee0Sniklas frame->tf_regs[FRAME_A2] = (u_int64_t)scp; 1670df930be7Sderaadt frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */ 167150ce9ee0Sniklas alpha_pal_wrusp((unsigned long)scp); 1672df930be7Sderaadt 1673df930be7Sderaadt #ifdef DEBUG 1674df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1675df930be7Sderaadt printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, 167650ce9ee0Sniklas frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]); 1677df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1678df930be7Sderaadt printf("sendsig(%d): sig %d returns\n", 1679df930be7Sderaadt p->p_pid, sig); 1680df930be7Sderaadt #endif 1681df930be7Sderaadt } 1682df930be7Sderaadt 1683df930be7Sderaadt /* 1684df930be7Sderaadt * System call to cleanup state after a signal 1685df930be7Sderaadt * has been taken. Reset signal mask and 1686df930be7Sderaadt * stack state from context left by sendsig (above). 1687df930be7Sderaadt * Return to previous pc and psl as specified by 1688df930be7Sderaadt * context left by sendsig. Check carefully to 1689df930be7Sderaadt * make sure that the user has not modified the 1690df930be7Sderaadt * psl to gain improper priviledges or to cause 1691df930be7Sderaadt * a machine fault. 1692df930be7Sderaadt */ 1693df930be7Sderaadt /* ARGSUSED */ 1694df930be7Sderaadt int 1695df930be7Sderaadt sys_sigreturn(p, v, retval) 1696df930be7Sderaadt struct proc *p; 1697df930be7Sderaadt void *v; 1698df930be7Sderaadt register_t *retval; 1699df930be7Sderaadt { 1700df930be7Sderaadt struct sys_sigreturn_args /* { 1701df930be7Sderaadt syscallarg(struct sigcontext *) sigcntxp; 1702df930be7Sderaadt } */ *uap = v; 1703df930be7Sderaadt struct sigcontext *scp, ksc; 1704df930be7Sderaadt 1705df930be7Sderaadt scp = SCARG(uap, sigcntxp); 1706df930be7Sderaadt #ifdef DEBUG 1707df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 170850ce9ee0Sniklas printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 1709df930be7Sderaadt #endif 1710df930be7Sderaadt 1711df930be7Sderaadt if (ALIGN(scp) != (u_int64_t)scp) 1712df930be7Sderaadt return (EINVAL); 1713df930be7Sderaadt 1714df930be7Sderaadt /* 1715df930be7Sderaadt * Test and fetch the context structure. 1716df930be7Sderaadt * We grab it all at once for speed. 1717df930be7Sderaadt */ 1718*aed035abSart if (uvm_useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 || 1719df930be7Sderaadt copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)) 1720df930be7Sderaadt return (EINVAL); 1721df930be7Sderaadt 1722df930be7Sderaadt if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */ 1723df930be7Sderaadt return (EINVAL); 1724df930be7Sderaadt /* 1725df930be7Sderaadt * Restore the user-supplied information 1726df930be7Sderaadt */ 1727df930be7Sderaadt if (ksc.sc_onstack) 1728df930be7Sderaadt p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; 1729df930be7Sderaadt else 1730df930be7Sderaadt p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 1731df930be7Sderaadt p->p_sigmask = ksc.sc_mask &~ sigcantmask; 1732df930be7Sderaadt 173350ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc; 173450ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PS] = 173550ce9ee0Sniklas (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; 1736df930be7Sderaadt 1737df930be7Sderaadt regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf); 173850ce9ee0Sniklas alpha_pal_wrusp(ksc.sc_regs[R_SP]); 1739df930be7Sderaadt 1740df930be7Sderaadt /* XXX ksc.sc_ownedfp ? */ 1741df930be7Sderaadt if (p == fpcurproc) 1742df930be7Sderaadt fpcurproc = NULL; 1743df930be7Sderaadt bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp, 1744df930be7Sderaadt sizeof(struct fpreg)); 1745df930be7Sderaadt /* XXX ksc.sc_fp_control ? */ 1746df930be7Sderaadt 1747df930be7Sderaadt #ifdef DEBUG 1748df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1749df930be7Sderaadt printf("sigreturn(%d): returns\n", p->p_pid); 1750df930be7Sderaadt #endif 1751df930be7Sderaadt return (EJUSTRETURN); 1752df930be7Sderaadt } 1753df930be7Sderaadt 1754df930be7Sderaadt /* 1755df930be7Sderaadt * machine dependent system variables. 1756df930be7Sderaadt */ 175750ce9ee0Sniklas int 1758df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 1759df930be7Sderaadt int *name; 1760df930be7Sderaadt u_int namelen; 1761df930be7Sderaadt void *oldp; 1762df930be7Sderaadt size_t *oldlenp; 1763df930be7Sderaadt void *newp; 1764df930be7Sderaadt size_t newlen; 1765df930be7Sderaadt struct proc *p; 1766df930be7Sderaadt { 1767df930be7Sderaadt dev_t consdev; 1768df930be7Sderaadt 1769df930be7Sderaadt /* all sysctl names at this level are terminal */ 1770df930be7Sderaadt if (namelen != 1) 1771df930be7Sderaadt return (ENOTDIR); /* overloaded */ 1772df930be7Sderaadt 1773df930be7Sderaadt switch (name[0]) { 1774df930be7Sderaadt case CPU_CONSDEV: 1775df930be7Sderaadt if (cn_tab != NULL) 1776df930be7Sderaadt consdev = cn_tab->cn_dev; 1777df930be7Sderaadt else 1778df930be7Sderaadt consdev = NODEV; 1779df930be7Sderaadt return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 1780df930be7Sderaadt sizeof consdev)); 1781417eba8cSderaadt 1782417eba8cSderaadt case CPU_ROOT_DEVICE: 1783*aed035abSart return (sysctl_rdstring(oldp, oldlenp, newp, 1784*aed035abSart root_device)); 1785417eba8cSderaadt 178650ce9ee0Sniklas case CPU_UNALIGNED_PRINT: 178750ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 178850ce9ee0Sniklas &alpha_unaligned_print)); 178950ce9ee0Sniklas 179050ce9ee0Sniklas case CPU_UNALIGNED_FIX: 179150ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 179250ce9ee0Sniklas &alpha_unaligned_fix)); 179350ce9ee0Sniklas 179450ce9ee0Sniklas case CPU_UNALIGNED_SIGBUS: 179550ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 179650ce9ee0Sniklas &alpha_unaligned_sigbus)); 179750ce9ee0Sniklas 17983a630e3fSniklas case CPU_BOOTED_KERNEL: 1799*aed035abSart return (sysctl_rdstring(oldp, oldlenp, newp, 1800*aed035abSart bootinfo.booted_kernel)); 18013a630e3fSniklas 1802df930be7Sderaadt default: 1803df930be7Sderaadt return (EOPNOTSUPP); 1804df930be7Sderaadt } 1805df930be7Sderaadt /* NOTREACHED */ 1806df930be7Sderaadt } 1807df930be7Sderaadt 1808df930be7Sderaadt /* 1809df930be7Sderaadt * Set registers on exec. 1810df930be7Sderaadt */ 1811df930be7Sderaadt void 1812df930be7Sderaadt setregs(p, pack, stack, retval) 1813df930be7Sderaadt register struct proc *p; 1814df930be7Sderaadt struct exec_package *pack; 1815df930be7Sderaadt u_long stack; 1816df930be7Sderaadt register_t *retval; 1817df930be7Sderaadt { 1818df930be7Sderaadt struct trapframe *tfp = p->p_md.md_tf; 18193a630e3fSniklas #ifdef DEBUG 18203a630e3fSniklas int i; 18213a630e3fSniklas #endif 1822df930be7Sderaadt 1823df930be7Sderaadt #ifdef DEBUG 182450ce9ee0Sniklas /* 182550ce9ee0Sniklas * Crash and dump, if the user requested it. 182650ce9ee0Sniklas */ 182750ce9ee0Sniklas if (boothowto & RB_DUMP) 182850ce9ee0Sniklas panic("crash requested by boot flags"); 182950ce9ee0Sniklas #endif 183050ce9ee0Sniklas 183150ce9ee0Sniklas #ifdef DEBUG 183250ce9ee0Sniklas for (i = 0; i < FRAME_SIZE; i++) 1833df930be7Sderaadt tfp->tf_regs[i] = 0xbabefacedeadbeef; 1834df930be7Sderaadt #else 183550ce9ee0Sniklas bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]); 1836df930be7Sderaadt #endif 1837df930be7Sderaadt bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp); 1838df930be7Sderaadt #define FP_RN 2 /* XXX */ 1839df930be7Sderaadt p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58; 184050ce9ee0Sniklas alpha_pal_wrusp(stack); 184150ce9ee0Sniklas tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; 184250ce9ee0Sniklas tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; 1843df930be7Sderaadt 184450ce9ee0Sniklas tfp->tf_regs[FRAME_A0] = stack; 184550ce9ee0Sniklas /* a1 and a2 already zeroed */ 184650ce9ee0Sniklas tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ 184750ce9ee0Sniklas 184850ce9ee0Sniklas p->p_md.md_flags &= ~MDP_FPUSED; 1849df930be7Sderaadt if (fpcurproc == p) 1850df930be7Sderaadt fpcurproc = NULL; 1851df930be7Sderaadt 1852df930be7Sderaadt retval[0] = retval[1] = 0; 1853df930be7Sderaadt } 1854df930be7Sderaadt 1855df930be7Sderaadt void 1856df930be7Sderaadt netintr() 1857df930be7Sderaadt { 185850ce9ee0Sniklas int n, s; 185950ce9ee0Sniklas 186050ce9ee0Sniklas s = splhigh(); 186150ce9ee0Sniklas n = netisr; 186250ce9ee0Sniklas netisr = 0; 186350ce9ee0Sniklas splx(s); 186450ce9ee0Sniklas 186550ce9ee0Sniklas #define DONETISR(bit, fn) \ 186650ce9ee0Sniklas do { \ 186750ce9ee0Sniklas if (n & (1 << (bit))) \ 1868*aed035abSart fn(); \ 186950ce9ee0Sniklas } while (0) 187050ce9ee0Sniklas 1871*aed035abSart #include <net/netisr_dispatch.h> 187250ce9ee0Sniklas 187350ce9ee0Sniklas #undef DONETISR 1874df930be7Sderaadt } 1875df930be7Sderaadt 1876df930be7Sderaadt void 1877df930be7Sderaadt do_sir() 1878df930be7Sderaadt { 18793a630e3fSniklas u_int64_t n; 1880df930be7Sderaadt 1881*aed035abSart while ((n = atomic_loadlatch_ulong(&ssir, 0)) != 0) { 1882*aed035abSart #define COUNT_SOFT uvmexp.softs++ 18833a630e3fSniklas 18843a630e3fSniklas #define DO_SIR(bit, fn) \ 18853a630e3fSniklas do { \ 18863a630e3fSniklas if (n & (bit)) { \ 1887*aed035abSart COUNT_SOFT; \ 18883a630e3fSniklas fn; \ 18893a630e3fSniklas } \ 18903a630e3fSniklas } while (0) 18913a630e3fSniklas 18923a630e3fSniklas DO_SIR(SIR_NET, netintr()); 18933a630e3fSniklas DO_SIR(SIR_CLOCK, softclock()); 18943a630e3fSniklas 1895*aed035abSart #undef COUNT_SOFT 18963a630e3fSniklas #undef DO_SIR 1897*aed035abSart } 1898df930be7Sderaadt } 1899df930be7Sderaadt 1900df930be7Sderaadt int 1901df930be7Sderaadt spl0() 1902df930be7Sderaadt { 1903df930be7Sderaadt 1904*aed035abSart if (ssir) { 1905*aed035abSart (void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT); 1906*aed035abSart do_sir(); 1907*aed035abSart } 1908df930be7Sderaadt 190950ce9ee0Sniklas return (alpha_pal_swpipl(ALPHA_PSL_IPL_0)); 1910df930be7Sderaadt } 1911df930be7Sderaadt 1912df930be7Sderaadt /* 1913df930be7Sderaadt * The following primitives manipulate the run queues. _whichqs tells which 1914df930be7Sderaadt * of the 32 queues _qs have processes in them. Setrunqueue puts processes 1915e464495eSniklas * into queues, Remrunqueue removes them from queues. The running process is 1916e464495eSniklas * on no queue, other processes are on a queue related to p->p_priority, 1917e464495eSniklas * divided by 4 actually to shrink the 0-127 range of priorities into the 32 1918e464495eSniklas * available queues. 1919df930be7Sderaadt */ 1920df930be7Sderaadt /* 1921df930be7Sderaadt * setrunqueue(p) 1922df930be7Sderaadt * proc *p; 1923df930be7Sderaadt * 1924df930be7Sderaadt * Call should be made at splclock(), and p->p_stat should be SRUN. 1925df930be7Sderaadt */ 1926df930be7Sderaadt 1927df930be7Sderaadt void 1928df930be7Sderaadt setrunqueue(p) 1929df930be7Sderaadt struct proc *p; 1930df930be7Sderaadt { 1931df930be7Sderaadt int bit; 1932df930be7Sderaadt 1933df930be7Sderaadt /* firewall: p->p_back must be NULL */ 1934df930be7Sderaadt if (p->p_back != NULL) 1935df930be7Sderaadt panic("setrunqueue"); 1936df930be7Sderaadt 1937df930be7Sderaadt bit = p->p_priority >> 2; 1938df930be7Sderaadt whichqs |= (1 << bit); 1939df930be7Sderaadt p->p_forw = (struct proc *)&qs[bit]; 1940df930be7Sderaadt p->p_back = qs[bit].ph_rlink; 1941df930be7Sderaadt p->p_back->p_forw = p; 1942df930be7Sderaadt qs[bit].ph_rlink = p; 1943df930be7Sderaadt } 1944df930be7Sderaadt 1945df930be7Sderaadt /* 1946e464495eSniklas * remrunqueue(p) 1947df930be7Sderaadt * 1948df930be7Sderaadt * Call should be made at splclock(). 1949df930be7Sderaadt */ 1950df930be7Sderaadt void 1951d3cbbad5Skstailey remrunqueue(p) 1952df930be7Sderaadt struct proc *p; 1953df930be7Sderaadt { 1954df930be7Sderaadt int bit; 1955df930be7Sderaadt 1956df930be7Sderaadt bit = p->p_priority >> 2; 1957df930be7Sderaadt if ((whichqs & (1 << bit)) == 0) 1958d3cbbad5Skstailey panic("remrunqueue"); 1959df930be7Sderaadt 1960df930be7Sderaadt p->p_back->p_forw = p->p_forw; 1961df930be7Sderaadt p->p_forw->p_back = p->p_back; 1962df930be7Sderaadt p->p_back = NULL; /* for firewall checking. */ 1963df930be7Sderaadt 1964df930be7Sderaadt if ((struct proc *)&qs[bit] == qs[bit].ph_link) 1965df930be7Sderaadt whichqs &= ~(1 << bit); 1966df930be7Sderaadt } 1967df930be7Sderaadt 1968df930be7Sderaadt /* 1969df930be7Sderaadt * Return the best possible estimate of the time in the timeval 1970df930be7Sderaadt * to which tvp points. Unfortunately, we can't read the hardware registers. 1971df930be7Sderaadt * We guarantee that the time will be greater than the value obtained by a 1972df930be7Sderaadt * previous call. 1973df930be7Sderaadt */ 1974df930be7Sderaadt void 1975df930be7Sderaadt microtime(tvp) 1976df930be7Sderaadt register struct timeval *tvp; 1977df930be7Sderaadt { 1978df930be7Sderaadt int s = splclock(); 1979df930be7Sderaadt static struct timeval lasttime; 1980df930be7Sderaadt 1981df930be7Sderaadt *tvp = time; 1982df930be7Sderaadt #ifdef notdef 1983df930be7Sderaadt tvp->tv_usec += clkread(); 19844c891e15Spjanzen while (tvp->tv_usec >= 1000000) { 1985df930be7Sderaadt tvp->tv_sec++; 1986df930be7Sderaadt tvp->tv_usec -= 1000000; 1987df930be7Sderaadt } 1988df930be7Sderaadt #endif 1989df930be7Sderaadt if (tvp->tv_sec == lasttime.tv_sec && 1990df930be7Sderaadt tvp->tv_usec <= lasttime.tv_usec && 19914c891e15Spjanzen (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 1992df930be7Sderaadt tvp->tv_sec++; 1993df930be7Sderaadt tvp->tv_usec -= 1000000; 1994df930be7Sderaadt } 1995df930be7Sderaadt lasttime = *tvp; 1996df930be7Sderaadt splx(s); 1997df930be7Sderaadt } 1998df930be7Sderaadt 1999417eba8cSderaadt /* 2000417eba8cSderaadt * Wait "n" microseconds. 2001417eba8cSderaadt */ 200250ce9ee0Sniklas void 2003417eba8cSderaadt delay(n) 200450ce9ee0Sniklas unsigned long n; 2005417eba8cSderaadt { 2006417eba8cSderaadt long N = cycles_per_usec * (n); 2007417eba8cSderaadt 2008*aed035abSart /* 2009*aed035abSart * XXX Should be written to use RPCC? 2010*aed035abSart */ 2011*aed035abSart 2012*aed035abSart __asm __volatile( 2013*aed035abSart "# The 2 corresponds to the insn count\n" 2014*aed035abSart "1: subq %2, %1, %0 \n" 2015*aed035abSart " bgt %0, 1b" 2016*aed035abSart : "=r" (N) 2017*aed035abSart : "i" (2), "0" (N)); 2018417eba8cSderaadt } 2019417eba8cSderaadt 2020df930be7Sderaadt #if defined(COMPAT_OSF1) || 1 /* XXX */ 20213a630e3fSniklas void cpu_exec_ecoff_setregs __P((struct proc *, struct exec_package *, 20223a630e3fSniklas u_long, register_t *)); 20233a630e3fSniklas 2024df930be7Sderaadt void 2025417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval) 2026df930be7Sderaadt struct proc *p; 2027417eba8cSderaadt struct exec_package *epp; 2028df930be7Sderaadt u_long stack; 2029df930be7Sderaadt register_t *retval; 2030df930be7Sderaadt { 2031417eba8cSderaadt struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; 2032df930be7Sderaadt 2033417eba8cSderaadt setregs(p, epp, stack, retval); 203450ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value; 2035df930be7Sderaadt } 2036df930be7Sderaadt 2037df930be7Sderaadt /* 2038df930be7Sderaadt * cpu_exec_ecoff_hook(): 2039df930be7Sderaadt * cpu-dependent ECOFF format hook for execve(). 2040df930be7Sderaadt * 2041df930be7Sderaadt * Do any machine-dependent diddling of the exec package when doing ECOFF. 2042df930be7Sderaadt * 2043df930be7Sderaadt */ 2044df930be7Sderaadt int 2045417eba8cSderaadt cpu_exec_ecoff_hook(p, epp) 2046df930be7Sderaadt struct proc *p; 2047df930be7Sderaadt struct exec_package *epp; 2048df930be7Sderaadt { 2049417eba8cSderaadt struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; 2050*aed035abSart extern struct emul emul_native, emul_osf1; 2051*aed035abSart int error; 2052*aed035abSart extern int osf1_exec_ecoff_hook(struct proc *p, 2053*aed035abSart struct exec_package *epp); 2054df930be7Sderaadt 2055417eba8cSderaadt switch (execp->f.f_magic) { 2056df930be7Sderaadt #ifdef COMPAT_OSF1 2057df930be7Sderaadt case ECOFF_MAGIC_ALPHA: 2058df930be7Sderaadt epp->ep_emul = &emul_osf1; 2059df930be7Sderaadt break; 2060df930be7Sderaadt #endif 2061df930be7Sderaadt 206250ce9ee0Sniklas case ECOFF_MAGIC_NATIVE_ALPHA: 2063a2f8ce8dSderaadt epp->ep_emul = &emul_native; 2064*aed035abSart error = 0; 2065df930be7Sderaadt break; 2066df930be7Sderaadt 2067df930be7Sderaadt default: 2068*aed035abSart error = ENOEXEC; 2069df930be7Sderaadt } 2070*aed035abSart return (error); 2071df930be7Sderaadt } 2072df930be7Sderaadt #endif 2073e464495eSniklas 2074*aed035abSart int 2075*aed035abSart alpha_pa_access(pa) 2076*aed035abSart u_long pa; 2077*aed035abSart { 2078*aed035abSart int i; 2079*aed035abSart 2080*aed035abSart for (i = 0; i < mem_cluster_cnt; i++) { 2081*aed035abSart if (pa < mem_clusters[i].start) 2082*aed035abSart continue; 2083*aed035abSart if ((pa - mem_clusters[i].start) >= 2084*aed035abSart (mem_clusters[i].size & ~PAGE_MASK)) 2085*aed035abSart continue; 2086*aed035abSart return (mem_clusters[i].size & PAGE_MASK); /* prot */ 2087*aed035abSart } 2088*aed035abSart 2089*aed035abSart /* 2090*aed035abSart * Address is not a memory address. If we're secure, disallow 2091*aed035abSart * access. Otherwise, grant read/write. 2092*aed035abSart */ 2093*aed035abSart if (securelevel > 0) 2094*aed035abSart return (VM_PROT_NONE); 2095*aed035abSart else 2096*aed035abSart return (VM_PROT_READ | VM_PROT_WRITE); 2097*aed035abSart } 2098*aed035abSart 2099e464495eSniklas /* XXX XXX BEGIN XXX XXX */ 2100*aed035abSart paddr_t alpha_XXX_dmamap_or; /* XXX */ 2101e464495eSniklas /* XXX */ 2102*aed035abSart paddr_t /* XXX */ 2103e464495eSniklas alpha_XXX_dmamap(v) /* XXX */ 2104*aed035abSart vaddr_t v; /* XXX */ 2105e464495eSniklas { /* XXX */ 2106e464495eSniklas /* XXX */ 2107e464495eSniklas return (vtophys(v) | alpha_XXX_dmamap_or); /* XXX */ 2108e464495eSniklas } /* XXX */ 2109e464495eSniklas /* XXX XXX END XXX XXX */ 2110*aed035abSart 2111*aed035abSart char * 2112*aed035abSart dot_conv(x) 2113*aed035abSart unsigned long x; 2114*aed035abSart { 2115*aed035abSart int i; 2116*aed035abSart char *xc; 2117*aed035abSart static int next; 2118*aed035abSart static char space[2][20]; 2119*aed035abSart 2120*aed035abSart xc = space[next ^= 1] + sizeof space[0]; 2121*aed035abSart *--xc = '\0'; 2122*aed035abSart for (i = 0;; ++i) { 2123*aed035abSart if (i && (i & 3) == 0) 2124*aed035abSart *--xc = '.'; 2125*aed035abSart *--xc = "0123456789abcdef"[x & 0xf]; 2126*aed035abSart x >>= 4; 2127*aed035abSart if (x == 0) 2128*aed035abSart break; 2129*aed035abSart } 2130*aed035abSart return xc; 2131*aed035abSart } 2132