1*f3914c62Sniklas /* $OpenBSD: machdep.c,v 1.21 1997/07/08 10:55:54 niklas Exp $ */ 23a630e3fSniklas /* $NetBSD: machdep.c,v 1.61 1996/12/07 01:54:49 cgd Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /* 5417eba8cSderaadt * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 6df930be7Sderaadt * All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * Author: Chris G. Demetriou 9df930be7Sderaadt * 10df930be7Sderaadt * Permission to use, copy, modify and distribute this software and 11df930be7Sderaadt * its documentation is hereby granted, provided that both the copyright 12df930be7Sderaadt * notice and this permission notice appear in all copies of the 13df930be7Sderaadt * software, derivative works or modified versions, and any portions 14df930be7Sderaadt * thereof, and that both notices appear in supporting documentation. 15df930be7Sderaadt * 16df930be7Sderaadt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17df930be7Sderaadt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18df930be7Sderaadt * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19df930be7Sderaadt * 20df930be7Sderaadt * Carnegie Mellon requests users of this software to return to 21df930be7Sderaadt * 22df930be7Sderaadt * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23df930be7Sderaadt * School of Computer Science 24df930be7Sderaadt * Carnegie Mellon University 25df930be7Sderaadt * Pittsburgh PA 15213-3890 26df930be7Sderaadt * 27df930be7Sderaadt * any improvements or extensions that they make and grant Carnegie the 28df930be7Sderaadt * rights to redistribute these changes. 29df930be7Sderaadt */ 30df930be7Sderaadt 31df930be7Sderaadt #include <sys/param.h> 32df930be7Sderaadt #include <sys/systm.h> 33df930be7Sderaadt #include <sys/signalvar.h> 34df930be7Sderaadt #include <sys/kernel.h> 35df930be7Sderaadt #include <sys/map.h> 36df930be7Sderaadt #include <sys/proc.h> 37df930be7Sderaadt #include <sys/buf.h> 38df930be7Sderaadt #include <sys/reboot.h> 39417eba8cSderaadt #include <sys/device.h> 40df930be7Sderaadt #include <sys/conf.h> 41df930be7Sderaadt #include <sys/file.h> 42df930be7Sderaadt #ifdef REAL_CLISTS 43df930be7Sderaadt #include <sys/clist.h> 44df930be7Sderaadt #endif 45df930be7Sderaadt #include <sys/callout.h> 46df930be7Sderaadt #include <sys/malloc.h> 47df930be7Sderaadt #include <sys/mbuf.h> 48df930be7Sderaadt #include <sys/msgbuf.h> 49df930be7Sderaadt #include <sys/ioctl.h> 50df930be7Sderaadt #include <sys/tty.h> 51df930be7Sderaadt #include <sys/user.h> 52df930be7Sderaadt #include <sys/exec.h> 53df930be7Sderaadt #include <sys/exec_ecoff.h> 54df930be7Sderaadt #include <sys/sysctl.h> 5550ce9ee0Sniklas #include <sys/core.h> 5650ce9ee0Sniklas #include <sys/kcore.h> 5750ce9ee0Sniklas #include <machine/kcore.h> 58df930be7Sderaadt #ifdef SYSVMSG 59df930be7Sderaadt #include <sys/msg.h> 60df930be7Sderaadt #endif 61df930be7Sderaadt #ifdef SYSVSEM 62df930be7Sderaadt #include <sys/sem.h> 63df930be7Sderaadt #endif 64df930be7Sderaadt #ifdef SYSVSHM 65df930be7Sderaadt #include <sys/shm.h> 66df930be7Sderaadt #endif 67df930be7Sderaadt 68df930be7Sderaadt #include <sys/mount.h> 69df930be7Sderaadt #include <sys/syscallargs.h> 70df930be7Sderaadt 7150ce9ee0Sniklas #include <vm/pmap.h> 72df930be7Sderaadt #include <vm/vm_kern.h> 73df930be7Sderaadt 74df930be7Sderaadt #include <dev/cons.h> 75df930be7Sderaadt 7650ce9ee0Sniklas #include <machine/autoconf.h> 77df930be7Sderaadt #include <machine/cpu.h> 78df930be7Sderaadt #include <machine/reg.h> 79df930be7Sderaadt #include <machine/rpb.h> 80df930be7Sderaadt #include <machine/prom.h> 813a630e3fSniklas #include <machine/cpuconf.h> 82df930be7Sderaadt 8312f8bbedSniklas #ifdef DDB 8412f8bbedSniklas #include <machine/db_machdep.h> 8512f8bbedSniklas #include <ddb/db_access.h> 8612f8bbedSniklas #include <ddb/db_sym.h> 8712f8bbedSniklas #include <ddb/db_extern.h> 8812f8bbedSniklas #endif 8912f8bbedSniklas 90df930be7Sderaadt #include <net/netisr.h> 9150ce9ee0Sniklas #include <net/if.h> 9250ce9ee0Sniklas 9350ce9ee0Sniklas #ifdef INET 9450ce9ee0Sniklas #include <netinet/in.h> 9550ce9ee0Sniklas #include <netinet/if_ether.h> 9650ce9ee0Sniklas #include <netinet/ip_var.h> 9750ce9ee0Sniklas #endif 9850ce9ee0Sniklas #ifdef NS 9950ce9ee0Sniklas #include <netns/ns_var.h> 10050ce9ee0Sniklas #endif 10150ce9ee0Sniklas #ifdef ISO 10250ce9ee0Sniklas #include <netiso/iso.h> 10350ce9ee0Sniklas #include <netiso/clnp.h> 10450ce9ee0Sniklas #endif 1053a630e3fSniklas #ifdef CCITT 1063a630e3fSniklas #include <netccitt/x25.h> 1073a630e3fSniklas #include <netccitt/pk.h> 1083a630e3fSniklas #include <netccitt/pk_extern.h> 1093a630e3fSniklas #endif 1103a630e3fSniklas #ifdef NATM 1113a630e3fSniklas #include <netnatm/natm.h> 1123a630e3fSniklas #endif 11350ce9ee0Sniklas #include "ppp.h" 11450ce9ee0Sniklas #if NPPP > 0 11550ce9ee0Sniklas #include <net/ppp_defs.h> 11650ce9ee0Sniklas #include <net/if_ppp.h> 11750ce9ee0Sniklas #endif 118df930be7Sderaadt 119417eba8cSderaadt #include "le_ioasic.h" /* for le_iomem creation */ 120df930be7Sderaadt 121df930be7Sderaadt vm_map_t buffer_map; 122df930be7Sderaadt 12350ce9ee0Sniklas int cpu_dump __P((void)); 1243a630e3fSniklas int cpu_dumpsize __P((void)); 12550ce9ee0Sniklas void do_sir __P((void)); 1263a630e3fSniklas void dumpsys __P((void)); 1273a630e3fSniklas void identifycpu __P((void)); 1283a630e3fSniklas void netintr __P((void)); 1293a630e3fSniklas void regdump __P((struct trapframe *framep)); 1303a630e3fSniklas void printregs __P((struct reg *)); 131df930be7Sderaadt 132df930be7Sderaadt /* 133df930be7Sderaadt * Declare these as initialized data so we can patch them. 134df930be7Sderaadt */ 135df930be7Sderaadt int nswbuf = 0; 136df930be7Sderaadt #ifdef NBUF 137df930be7Sderaadt int nbuf = NBUF; 138df930be7Sderaadt #else 139df930be7Sderaadt int nbuf = 0; 140df930be7Sderaadt #endif 141df930be7Sderaadt #ifdef BUFPAGES 142df930be7Sderaadt int bufpages = BUFPAGES; 143df930be7Sderaadt #else 144df930be7Sderaadt int bufpages = 0; 145df930be7Sderaadt #endif 146df930be7Sderaadt int msgbufmapped = 0; /* set when safe to use msgbuf */ 147df930be7Sderaadt int maxmem; /* max memory per process */ 148df930be7Sderaadt 149df930be7Sderaadt int totalphysmem; /* total amount of physical memory in system */ 15074652a67Sniklas int physmem; /* physical mem used by OpenBSD + some rsvd */ 151df930be7Sderaadt int firstusablepage; /* first usable memory page */ 152df930be7Sderaadt int lastusablepage; /* last usable memory page */ 153df930be7Sderaadt int resvmem; /* amount of memory reserved for PROM */ 154df930be7Sderaadt int unusedmem; /* amount of memory for OS that we don't use */ 155df930be7Sderaadt int unknownmem; /* amount of memory with an unknown use */ 156df930be7Sderaadt 157df930be7Sderaadt int cputype; /* system type, from the RPB */ 158df930be7Sderaadt 159df930be7Sderaadt /* 160df930be7Sderaadt * XXX We need an address to which we can assign things so that they 161df930be7Sderaadt * won't be optimized away because we didn't use the value. 162df930be7Sderaadt */ 163df930be7Sderaadt u_int32_t no_optimize; 164df930be7Sderaadt 165df930be7Sderaadt /* the following is used externally (sysctl_hw) */ 166df930be7Sderaadt char machine[] = "alpha"; 167417eba8cSderaadt char cpu_model[128]; 1683a630e3fSniklas const struct cpusw *cpu_fn_switch; /* function switch */ 169df930be7Sderaadt 170df930be7Sderaadt struct user *proc0paddr; 171df930be7Sderaadt 172df930be7Sderaadt /* Number of machine cycles per microsecond */ 173df930be7Sderaadt u_int64_t cycles_per_usec; 174df930be7Sderaadt 175df930be7Sderaadt /* some memory areas for device DMA. "ick." */ 176df930be7Sderaadt caddr_t le_iomem; /* XXX iomem for LANCE DMA */ 177df930be7Sderaadt 178df930be7Sderaadt /* number of cpus in the box. really! */ 179df930be7Sderaadt int ncpus; 180df930be7Sderaadt 181417eba8cSderaadt char boot_flags[64]; 1823a630e3fSniklas char booted_kernel[64]; 183417eba8cSderaadt 184417eba8cSderaadt /* for cpu_sysctl() */ 185417eba8cSderaadt char root_device[17]; 18650ce9ee0Sniklas int alpha_unaligned_print = 1; /* warn about unaligned accesses */ 18750ce9ee0Sniklas int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ 18850ce9ee0Sniklas int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ 18950ce9ee0Sniklas 1903a630e3fSniklas void 191*f3914c62Sniklas alpha_init(pfn, ptb, symend) 192df930be7Sderaadt u_long pfn; /* first free PFN number */ 193df930be7Sderaadt u_long ptb; /* PFN of current level 1 page table */ 194*f3914c62Sniklas char *symend; /* end of the symbol table */ 195df930be7Sderaadt { 196df930be7Sderaadt extern char _end[]; 197*f3914c62Sniklas extern char *esym; 198df930be7Sderaadt caddr_t start, v; 199df930be7Sderaadt struct mddt *mddtp; 200df930be7Sderaadt int i, mddtweird; 201df930be7Sderaadt char *p; 202df930be7Sderaadt 203*f3914c62Sniklas /* Save the symbol table end */ 204*f3914c62Sniklas esym = symend; 205*f3914c62Sniklas 206df930be7Sderaadt /* 207df930be7Sderaadt * Turn off interrupts and floating point. 208df930be7Sderaadt * Make sure the instruction and data streams are consistent. 209df930be7Sderaadt */ 210df930be7Sderaadt (void)splhigh(); 21150ce9ee0Sniklas alpha_pal_wrfen(0); 21250ce9ee0Sniklas ALPHA_TBIA(); 21350ce9ee0Sniklas alpha_pal_imb(); 214df930be7Sderaadt 215df930be7Sderaadt /* 216df930be7Sderaadt * get address of the restart block, while we the bootstrap 217df930be7Sderaadt * mapping is still around. 218df930be7Sderaadt */ 21950ce9ee0Sniklas hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG( 22050ce9ee0Sniklas (vm_offset_t)(*(struct rpb **)HWRPB_ADDR)); 221df930be7Sderaadt 222df930be7Sderaadt /* 223df930be7Sderaadt * Remember how many cycles there are per microsecond, 224df930be7Sderaadt * so that we can use delay(). Round up, for safety. 225df930be7Sderaadt */ 226df930be7Sderaadt cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000; 227df930be7Sderaadt 228df930be7Sderaadt /* 229df930be7Sderaadt * Init the PROM interface, so we can use printf 230df930be7Sderaadt * until PROM mappings go away in consinit. 231df930be7Sderaadt */ 232df930be7Sderaadt init_prom_interface(); 233df930be7Sderaadt 234df930be7Sderaadt /* 235df930be7Sderaadt * Point interrupt/exception vectors to our own. 236df930be7Sderaadt */ 23750ce9ee0Sniklas alpha_pal_wrent(XentInt, ALPHA_KENTRY_INT); 23850ce9ee0Sniklas alpha_pal_wrent(XentArith, ALPHA_KENTRY_ARITH); 23950ce9ee0Sniklas alpha_pal_wrent(XentMM, ALPHA_KENTRY_MM); 24050ce9ee0Sniklas alpha_pal_wrent(XentIF, ALPHA_KENTRY_IF); 24150ce9ee0Sniklas alpha_pal_wrent(XentUna, ALPHA_KENTRY_UNA); 24250ce9ee0Sniklas alpha_pal_wrent(XentSys, ALPHA_KENTRY_SYS); 24350ce9ee0Sniklas 24450ce9ee0Sniklas /* 24550ce9ee0Sniklas * Disable System and Processor Correctable Error reporting. 24650ce9ee0Sniklas * Clear pending machine checks and error reports, etc. 24750ce9ee0Sniklas */ 24850ce9ee0Sniklas alpha_pal_wrmces(alpha_pal_rdmces() | ALPHA_MCES_DSC | ALPHA_MCES_DPC); 249df930be7Sderaadt 250df930be7Sderaadt /* 251df930be7Sderaadt * Find out how much memory is available, by looking at 252df930be7Sderaadt * the memory cluster descriptors. This also tries to do 253df930be7Sderaadt * its best to detect things things that have never been seen 254df930be7Sderaadt * before... 255df930be7Sderaadt * 256df930be7Sderaadt * XXX Assumes that the first "system" cluster is the 257df930be7Sderaadt * only one we can use. Is the second (etc.) system cluster 258df930be7Sderaadt * (if one happens to exist) guaranteed to be contiguous? or...? 259df930be7Sderaadt */ 260df930be7Sderaadt mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off); 261df930be7Sderaadt 262df930be7Sderaadt /* 263df930be7Sderaadt * BEGIN MDDT WEIRDNESS CHECKING 264df930be7Sderaadt */ 265df930be7Sderaadt mddtweird = 0; 266df930be7Sderaadt 267df930be7Sderaadt #define cnt mddtp->mddt_cluster_cnt 268df930be7Sderaadt #define usage(n) mddtp->mddt_clusters[(n)].mddt_usage 269df930be7Sderaadt if (cnt != 2 && cnt != 3) { 27050ce9ee0Sniklas printf("WARNING: weird number (%ld) of mem clusters\n", cnt); 271df930be7Sderaadt mddtweird = 1; 272df930be7Sderaadt } else if (usage(0) != MDDT_PALCODE || 273df930be7Sderaadt usage(1) != MDDT_SYSTEM || 274df930be7Sderaadt (cnt == 3 && usage(2) != MDDT_PALCODE)) { 275df930be7Sderaadt mddtweird = 1; 27650ce9ee0Sniklas printf("WARNING: %ld mem clusters, but weird config\n", cnt); 277df930be7Sderaadt } 278df930be7Sderaadt 279df930be7Sderaadt for (i = 0; i < cnt; i++) { 280df930be7Sderaadt if ((usage(i) & MDDT_mbz) != 0) { 281df930be7Sderaadt printf("WARNING: mem cluster %d has weird usage %lx\n", 282df930be7Sderaadt i, usage(i)); 283df930be7Sderaadt mddtweird = 1; 284df930be7Sderaadt } 285df930be7Sderaadt if (mddtp->mddt_clusters[i].mddt_pg_cnt == 0) { 286df930be7Sderaadt printf("WARNING: mem cluster %d has pg cnt == 0\n", i); 287df930be7Sderaadt mddtweird = 1; 288df930be7Sderaadt } 289df930be7Sderaadt /* XXX other things to check? */ 290df930be7Sderaadt } 291df930be7Sderaadt #undef cnt 292df930be7Sderaadt #undef usage 293df930be7Sderaadt 294df930be7Sderaadt if (mddtweird) { 295df930be7Sderaadt printf("\n"); 296df930be7Sderaadt printf("complete memory cluster information:\n"); 297df930be7Sderaadt for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 298df930be7Sderaadt printf("mddt %d:\n", i); 299df930be7Sderaadt printf("\tpfn %lx\n", 300df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pfn); 301df930be7Sderaadt printf("\tcnt %lx\n", 302df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_cnt); 303df930be7Sderaadt printf("\ttest %lx\n", 304df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pg_test); 305df930be7Sderaadt printf("\tbva %lx\n", 306df930be7Sderaadt mddtp->mddt_clusters[i].mddt_v_bitaddr); 307df930be7Sderaadt printf("\tbpa %lx\n", 308df930be7Sderaadt mddtp->mddt_clusters[i].mddt_p_bitaddr); 309df930be7Sderaadt printf("\tbcksum %lx\n", 310df930be7Sderaadt mddtp->mddt_clusters[i].mddt_bit_cksum); 311df930be7Sderaadt printf("\tusage %lx\n", 312df930be7Sderaadt mddtp->mddt_clusters[i].mddt_usage); 313df930be7Sderaadt } 314df930be7Sderaadt printf("\n"); 315df930be7Sderaadt } 316df930be7Sderaadt /* 317df930be7Sderaadt * END MDDT WEIRDNESS CHECKING 318df930be7Sderaadt */ 319df930be7Sderaadt 320df930be7Sderaadt for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { 321df930be7Sderaadt totalphysmem += mddtp->mddt_clusters[i].mddt_pg_cnt; 322df930be7Sderaadt #define usage(n) mddtp->mddt_clusters[(n)].mddt_usage 323df930be7Sderaadt #define pgcnt(n) mddtp->mddt_clusters[(n)].mddt_pg_cnt 324df930be7Sderaadt if ((usage(i) & MDDT_mbz) != 0) 325df930be7Sderaadt unknownmem += pgcnt(i); 326df930be7Sderaadt else if ((usage(i) & ~MDDT_mbz) == MDDT_PALCODE) 327df930be7Sderaadt resvmem += pgcnt(i); 328df930be7Sderaadt else if ((usage(i) & ~MDDT_mbz) == MDDT_SYSTEM) { 329df930be7Sderaadt /* 330df930be7Sderaadt * assumes that the system cluster listed is 331df930be7Sderaadt * one we're in... 332df930be7Sderaadt */ 333df930be7Sderaadt if (physmem != resvmem) { 334df930be7Sderaadt physmem += pgcnt(i); 335df930be7Sderaadt firstusablepage = 336df930be7Sderaadt mddtp->mddt_clusters[i].mddt_pfn; 33774652a67Sniklas lastusablepage = 33874652a67Sniklas firstusablepage + pgcnt(i) - 1; 339df930be7Sderaadt } else 340df930be7Sderaadt unusedmem += pgcnt(i); 341df930be7Sderaadt } 342df930be7Sderaadt #undef usage 343df930be7Sderaadt #undef pgcnt 344df930be7Sderaadt } 345df930be7Sderaadt if (totalphysmem == 0) 346df930be7Sderaadt panic("can't happen: system seems to have no memory!"); 347df930be7Sderaadt maxmem = physmem; 348df930be7Sderaadt 349df930be7Sderaadt #if 0 350df930be7Sderaadt printf("totalphysmem = %d\n", totalphysmem); 351df930be7Sderaadt printf("physmem = %d\n", physmem); 352df930be7Sderaadt printf("firstusablepage = %d\n", firstusablepage); 353df930be7Sderaadt printf("lastusablepage = %d\n", lastusablepage); 354df930be7Sderaadt printf("resvmem = %d\n", resvmem); 355df930be7Sderaadt printf("unusedmem = %d\n", unusedmem); 356df930be7Sderaadt printf("unknownmem = %d\n", unknownmem); 357df930be7Sderaadt #endif 358df930be7Sderaadt 359df930be7Sderaadt /* 360df930be7Sderaadt * find out this CPU's page size 361df930be7Sderaadt */ 362df930be7Sderaadt PAGE_SIZE = hwrpb->rpb_page_size; 36334fbf6deSderaadt if (PAGE_SIZE != 8192) 36434fbf6deSderaadt panic("page size %d != 8192?!", PAGE_SIZE); 365df930be7Sderaadt 366*f3914c62Sniklas v = (caddr_t)alpha_round_page(symend ? symend : _end); 367df930be7Sderaadt /* 368df930be7Sderaadt * Init mapping for u page(s) for proc 0 369df930be7Sderaadt */ 370df930be7Sderaadt start = v; 371df930be7Sderaadt curproc->p_addr = proc0paddr = (struct user *)v; 372df930be7Sderaadt v += UPAGES * NBPG; 373df930be7Sderaadt 374df930be7Sderaadt /* 375df930be7Sderaadt * Find out what hardware we're on, and remember its type name. 376df930be7Sderaadt */ 377df930be7Sderaadt cputype = hwrpb->rpb_type; 3783a630e3fSniklas if (cputype < 0 || cputype > ncpusw) { 3793a630e3fSniklas unknown_cputype: 3803a630e3fSniklas printf("\n"); 3813a630e3fSniklas printf("Unknown system type %d.\n", cputype); 3823a630e3fSniklas printf("\n"); 3833a630e3fSniklas panic("unknown system type"); 3843a630e3fSniklas } 3853a630e3fSniklas cpu_fn_switch = &cpusw[cputype]; 3863a630e3fSniklas if (cpu_fn_switch->family == NULL) 3873a630e3fSniklas goto unknown_cputype; 3883a630e3fSniklas if (cpu_fn_switch->option == NULL) { 3893a630e3fSniklas printf("\n"); 3900bc98093Smichaels printf("OpenBSD does not currently support system type %d\n", 3913a630e3fSniklas cputype); 3923a630e3fSniklas printf("(%s family).\n", cpu_fn_switch->family); 3933a630e3fSniklas printf("\n"); 3943a630e3fSniklas panic("unsupported system type"); 3953a630e3fSniklas } 3963a630e3fSniklas if (!cpu_fn_switch->present) { 3973a630e3fSniklas printf("\n"); 3983a630e3fSniklas printf("Support for system type %d (%s family) is\n", cputype, 3993a630e3fSniklas cpu_fn_switch->family); 40074652a67Sniklas printf("not present in this kernel. Build a kernel with " 40174652a67Sniklas "\"options %s\"\n", cpu_fn_switch->option); 4023a630e3fSniklas printf("to include support for this system type.\n"); 4033a630e3fSniklas printf("\n"); 4043a630e3fSniklas panic("support for system not present"); 405df930be7Sderaadt } 406df930be7Sderaadt 4073a630e3fSniklas if ((*cpu_fn_switch->model_name)() != NULL) 4083a630e3fSniklas strncpy(cpu_model, (*cpu_fn_switch->model_name)(), 4093a630e3fSniklas sizeof cpu_model - 1); 4103a630e3fSniklas else { 41174652a67Sniklas strncpy(cpu_model, cpu_fn_switch->family, 41274652a67Sniklas sizeof cpu_model - 1); 4133a630e3fSniklas strcat(cpu_model, " family"); /* XXX */ 4143a630e3fSniklas } 415417eba8cSderaadt cpu_model[sizeof cpu_model - 1] = '\0'; 416df930be7Sderaadt 417417eba8cSderaadt #if NLE_IOASIC > 0 418df930be7Sderaadt /* 419df930be7Sderaadt * Grab 128K at the top of physical memory for the lance chip 420df930be7Sderaadt * on machines where it does dma through the I/O ASIC. 421df930be7Sderaadt * It must be physically contiguous and aligned on a 128K boundary. 422417eba8cSderaadt * 423417eba8cSderaadt * Note that since this is conditional on the presence of 424417eba8cSderaadt * IOASIC-attached 'le' units in the kernel config, the 425417eba8cSderaadt * message buffer may move on these systems. This shouldn't 426417eba8cSderaadt * be a problem, because once people have a kernel config that 427417eba8cSderaadt * they use, they're going to stick with it. 428df930be7Sderaadt */ 429df930be7Sderaadt if (cputype == ST_DEC_3000_500 || 430df930be7Sderaadt cputype == ST_DEC_3000_300) { /* XXX possibly others? */ 431df930be7Sderaadt lastusablepage -= btoc(128 * 1024); 43250ce9ee0Sniklas le_iomem = 43350ce9ee0Sniklas (caddr_t)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1)); 434df930be7Sderaadt } 435417eba8cSderaadt #endif /* NLE_IOASIC */ 436df930be7Sderaadt 437df930be7Sderaadt /* 438df930be7Sderaadt * Initialize error message buffer (at end of core). 439df930be7Sderaadt */ 440df930be7Sderaadt lastusablepage -= btoc(sizeof (struct msgbuf)); 44150ce9ee0Sniklas msgbufp = 44250ce9ee0Sniklas (struct msgbuf *)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1)); 443df930be7Sderaadt msgbufmapped = 1; 444df930be7Sderaadt 445df930be7Sderaadt /* 446df930be7Sderaadt * Allocate space for system data structures. 447df930be7Sderaadt * The first available kernel virtual address is in "v". 448df930be7Sderaadt * As pages of kernel virtual memory are allocated, "v" is incremented. 449df930be7Sderaadt * 450df930be7Sderaadt * These data structures are allocated here instead of cpu_startup() 451df930be7Sderaadt * because physical memory is directly addressable. We don't have 452df930be7Sderaadt * to map these into virtual address space. 453df930be7Sderaadt */ 454df930be7Sderaadt #define valloc(name, type, num) \ 45534fbf6deSderaadt (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num)) 456df930be7Sderaadt #define valloclim(name, type, num, lim) \ 45734fbf6deSderaadt (name) = (type *)v; v = (caddr_t)ALIGN((lim) = ((name)+(num))) 458df930be7Sderaadt #ifdef REAL_CLISTS 459df930be7Sderaadt valloc(cfree, struct cblock, nclist); 460df930be7Sderaadt #endif 461df930be7Sderaadt valloc(callout, struct callout, ncallout); 462df930be7Sderaadt valloc(swapmap, struct map, nswapmap = maxproc * 2); 463df930be7Sderaadt #ifdef SYSVSHM 464df930be7Sderaadt valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 465df930be7Sderaadt #endif 466df930be7Sderaadt #ifdef SYSVSEM 467df930be7Sderaadt valloc(sema, struct semid_ds, seminfo.semmni); 468df930be7Sderaadt valloc(sem, struct sem, seminfo.semmns); 469df930be7Sderaadt /* This is pretty disgusting! */ 470df930be7Sderaadt valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 471df930be7Sderaadt #endif 472df930be7Sderaadt #ifdef SYSVMSG 473df930be7Sderaadt valloc(msgpool, char, msginfo.msgmax); 474df930be7Sderaadt valloc(msgmaps, struct msgmap, msginfo.msgseg); 475df930be7Sderaadt valloc(msghdrs, struct msg, msginfo.msgtql); 476df930be7Sderaadt valloc(msqids, struct msqid_ds, msginfo.msgmni); 477df930be7Sderaadt #endif 478df930be7Sderaadt 479df930be7Sderaadt /* 480df930be7Sderaadt * Determine how many buffers to allocate. 481417eba8cSderaadt * We allocate 10% of memory for buffer space. Insure a 482df930be7Sderaadt * minimum of 16 buffers. We allocate 1/2 as many swap buffer 483df930be7Sderaadt * headers as file i/o buffers. 484df930be7Sderaadt */ 485df930be7Sderaadt if (bufpages == 0) 486417eba8cSderaadt bufpages = (physmem * 10) / (CLSIZE * 100); 487df930be7Sderaadt if (nbuf == 0) { 488df930be7Sderaadt nbuf = bufpages; 489df930be7Sderaadt if (nbuf < 16) 490df930be7Sderaadt nbuf = 16; 491df930be7Sderaadt } 492df930be7Sderaadt if (nswbuf == 0) { 493df930be7Sderaadt nswbuf = (nbuf / 2) &~ 1; /* force even */ 494df930be7Sderaadt if (nswbuf > 256) 495df930be7Sderaadt nswbuf = 256; /* sanity */ 496df930be7Sderaadt } 497df930be7Sderaadt valloc(swbuf, struct buf, nswbuf); 498df930be7Sderaadt valloc(buf, struct buf, nbuf); 499df930be7Sderaadt 500df930be7Sderaadt /* 501df930be7Sderaadt * Clear allocated memory. 502df930be7Sderaadt */ 503df930be7Sderaadt bzero(start, v - start); 504df930be7Sderaadt 505df930be7Sderaadt /* 506df930be7Sderaadt * Initialize the virtual memory system, and set the 507df930be7Sderaadt * page table base register in proc 0's PCB. 508df930be7Sderaadt */ 50950ce9ee0Sniklas #ifndef NEW_PMAP 51050ce9ee0Sniklas pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT)); 51150ce9ee0Sniklas #else 51250ce9ee0Sniklas pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), 51350ce9ee0Sniklas hwrpb->rpb_max_asn); 51450ce9ee0Sniklas #endif 515df930be7Sderaadt 516df930be7Sderaadt /* 517df930be7Sderaadt * Initialize the rest of proc 0's PCB, and cache its physical 518df930be7Sderaadt * address. 519df930be7Sderaadt */ 520df930be7Sderaadt proc0.p_md.md_pcbpaddr = 52150ce9ee0Sniklas (struct pcb *)ALPHA_K0SEG_TO_PHYS((vm_offset_t)&proc0paddr->u_pcb); 522df930be7Sderaadt 523df930be7Sderaadt /* 524df930be7Sderaadt * Set the kernel sp, reserving space for an (empty) trapframe, 525df930be7Sderaadt * and make proc0's trapframe pointer point to it for sanity. 526df930be7Sderaadt */ 52750ce9ee0Sniklas proc0paddr->u_pcb.pcb_hw.apcb_ksp = 528df930be7Sderaadt (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe); 52974652a67Sniklas proc0.p_md.md_tf = 53074652a67Sniklas (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp; 53150ce9ee0Sniklas 53250ce9ee0Sniklas #ifdef NEW_PMAP 53350ce9ee0Sniklas pmap_activate(kernel_pmap, &proc0paddr->u_pcb.pcb_hw, 0); 53450ce9ee0Sniklas #endif 535df930be7Sderaadt 536df930be7Sderaadt /* 537df930be7Sderaadt * Look at arguments passed to us and compute boothowto. 5383a630e3fSniklas * Also, get kernel name so it can be used in user-land. 539df930be7Sderaadt */ 540417eba8cSderaadt prom_getenv(PROM_E_BOOTED_OSFLAGS, boot_flags, sizeof(boot_flags)); 541417eba8cSderaadt #if 0 542417eba8cSderaadt printf("boot flags = \"%s\"\n", boot_flags); 543df930be7Sderaadt #endif 5443a630e3fSniklas prom_getenv(PROM_E_BOOTED_FILE, booted_kernel, 5453a630e3fSniklas sizeof(booted_kernel)); 5463a630e3fSniklas #if 0 5473a630e3fSniklas printf("booted kernel = \"%s\"\n", booted_kernel); 5483a630e3fSniklas #endif 549417eba8cSderaadt 550417eba8cSderaadt boothowto = RB_SINGLE; 551df930be7Sderaadt #ifdef KADB 552df930be7Sderaadt boothowto |= RB_KDB; 553df930be7Sderaadt #endif 554df930be7Sderaadt for (p = boot_flags; p && *p != '\0'; p++) { 555417eba8cSderaadt /* 556417eba8cSderaadt * Note that we'd really like to differentiate case here, 557417eba8cSderaadt * but the Alpha AXP Architecture Reference Manual 558417eba8cSderaadt * says that we shouldn't. 559417eba8cSderaadt */ 560df930be7Sderaadt switch (*p) { 561df930be7Sderaadt case 'a': /* autoboot */ 562417eba8cSderaadt case 'A': 563df930be7Sderaadt boothowto &= ~RB_SINGLE; 564df930be7Sderaadt break; 565df930be7Sderaadt 56612f8bbedSniklas case 'b': /* Enter DDB as soon as the console is initialised */ 56712f8bbedSniklas case 'B': 56812f8bbedSniklas boothowto |= RB_KDB; 56912f8bbedSniklas break; 57012f8bbedSniklas 57150ce9ee0Sniklas case 'c': /* enter user kernel configuration */ 57250ce9ee0Sniklas case 'C': 57350ce9ee0Sniklas boothowto |= RB_CONFIG; 57450ce9ee0Sniklas break; 57550ce9ee0Sniklas 57650ce9ee0Sniklas #ifdef DEBUG 57750ce9ee0Sniklas case 'd': /* crash dump immediately after autoconfig */ 57850ce9ee0Sniklas case 'D': 57950ce9ee0Sniklas boothowto |= RB_DUMP; 58050ce9ee0Sniklas break; 58150ce9ee0Sniklas #endif 58250ce9ee0Sniklas 58350ce9ee0Sniklas case 'h': /* always halt, never reboot */ 58450ce9ee0Sniklas case 'H': 58550ce9ee0Sniklas boothowto |= RB_HALT; 586df930be7Sderaadt break; 587df930be7Sderaadt 588417eba8cSderaadt #if 0 589417eba8cSderaadt case 'm': /* mini root present in memory */ 590417eba8cSderaadt case 'M': 591417eba8cSderaadt boothowto |= RB_MINIROOT; 592417eba8cSderaadt break; 593417eba8cSderaadt #endif 59450ce9ee0Sniklas 59550ce9ee0Sniklas case 'n': /* askname */ 59650ce9ee0Sniklas case 'N': 59750ce9ee0Sniklas boothowto |= RB_ASKNAME; 59850ce9ee0Sniklas break; 599df930be7Sderaadt } 600df930be7Sderaadt } 601df930be7Sderaadt 602df930be7Sderaadt /* 603df930be7Sderaadt * Figure out the number of cpus in the box, from RPB fields. 604df930be7Sderaadt * Really. We mean it. 605df930be7Sderaadt */ 606df930be7Sderaadt for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { 607df930be7Sderaadt struct pcs *pcsp; 608df930be7Sderaadt 609df930be7Sderaadt pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + 610df930be7Sderaadt (i * hwrpb->rpb_pcs_size)); 611df930be7Sderaadt if ((pcsp->pcs_flags & PCS_PP) != 0) 612df930be7Sderaadt ncpus++; 613df930be7Sderaadt } 614df930be7Sderaadt } 615df930be7Sderaadt 616417eba8cSderaadt void 617df930be7Sderaadt consinit() 618df930be7Sderaadt { 6193a630e3fSniklas (*cpu_fn_switch->cons_init)(); 620df930be7Sderaadt pmap_unmap_prom(); 62112f8bbedSniklas #ifdef DDB 62212f8bbedSniklas ddb_init(); 62312f8bbedSniklas if (boothowto & RB_KDB) 62412f8bbedSniklas Debugger(); 62512f8bbedSniklas #endif 626df930be7Sderaadt } 627df930be7Sderaadt 628417eba8cSderaadt void 629df930be7Sderaadt cpu_startup() 630df930be7Sderaadt { 631df930be7Sderaadt register unsigned i; 632df930be7Sderaadt int base, residual; 633df930be7Sderaadt vm_offset_t minaddr, maxaddr; 634df930be7Sderaadt vm_size_t size; 63550ce9ee0Sniklas #if defined(DEBUG) 636df930be7Sderaadt extern int pmapdebug; 637df930be7Sderaadt int opmapdebug = pmapdebug; 638df930be7Sderaadt 639df930be7Sderaadt pmapdebug = 0; 640df930be7Sderaadt #endif 641df930be7Sderaadt 642df930be7Sderaadt /* 643df930be7Sderaadt * Good {morning,afternoon,evening,night}. 644df930be7Sderaadt */ 645df930be7Sderaadt printf(version); 646df930be7Sderaadt identifycpu(); 64750ce9ee0Sniklas printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n", 648df930be7Sderaadt ctob(totalphysmem), ctob(resvmem), ctob(physmem)); 649df930be7Sderaadt if (unusedmem) 650df930be7Sderaadt printf("WARNING: unused memory = %d bytes\n", ctob(unusedmem)); 651df930be7Sderaadt if (unknownmem) 652df930be7Sderaadt printf("WARNING: %d bytes of memory with unknown purpose\n", 653df930be7Sderaadt ctob(unknownmem)); 654df930be7Sderaadt 655df930be7Sderaadt /* 656df930be7Sderaadt * Allocate virtual address space for file I/O buffers. 657df930be7Sderaadt * Note they are different than the array of headers, 'buf', 658df930be7Sderaadt * and usually occupy more virtual memory than physical. 659df930be7Sderaadt */ 660df930be7Sderaadt size = MAXBSIZE * nbuf; 661df930be7Sderaadt buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 662df930be7Sderaadt &maxaddr, size, TRUE); 663df930be7Sderaadt minaddr = (vm_offset_t)buffers; 664df930be7Sderaadt if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 665df930be7Sderaadt &minaddr, size, FALSE) != KERN_SUCCESS) 666df930be7Sderaadt panic("startup: cannot allocate buffers"); 667df930be7Sderaadt base = bufpages / nbuf; 668df930be7Sderaadt residual = bufpages % nbuf; 669df930be7Sderaadt for (i = 0; i < nbuf; i++) { 670df930be7Sderaadt vm_size_t curbufsize; 671df930be7Sderaadt vm_offset_t curbuf; 672df930be7Sderaadt 673df930be7Sderaadt /* 674df930be7Sderaadt * First <residual> buffers get (base+1) physical pages 675df930be7Sderaadt * allocated for them. The rest get (base) physical pages. 676df930be7Sderaadt * 677df930be7Sderaadt * The rest of each buffer occupies virtual space, 678df930be7Sderaadt * but has no physical memory allocated for it. 679df930be7Sderaadt */ 680df930be7Sderaadt curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 681df930be7Sderaadt curbufsize = CLBYTES * (i < residual ? base+1 : base); 682df930be7Sderaadt vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 683df930be7Sderaadt vm_map_simplify(buffer_map, curbuf); 684df930be7Sderaadt } 685df930be7Sderaadt /* 686df930be7Sderaadt * Allocate a submap for exec arguments. This map effectively 687df930be7Sderaadt * limits the number of processes exec'ing at any time. 688df930be7Sderaadt */ 689df930be7Sderaadt exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 690df930be7Sderaadt 16 * NCARGS, TRUE); 691df930be7Sderaadt 692df930be7Sderaadt /* 693df930be7Sderaadt * Allocate a submap for physio 694df930be7Sderaadt */ 695df930be7Sderaadt phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 696df930be7Sderaadt VM_PHYS_SIZE, TRUE); 697df930be7Sderaadt 698df930be7Sderaadt /* 699df930be7Sderaadt * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 700df930be7Sderaadt * we use the more space efficient malloc in place of kmem_alloc. 701df930be7Sderaadt */ 702df930be7Sderaadt mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 703df930be7Sderaadt M_MBUF, M_NOWAIT); 704df930be7Sderaadt bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 705df930be7Sderaadt mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 706df930be7Sderaadt VM_MBUF_SIZE, FALSE); 707df930be7Sderaadt /* 708df930be7Sderaadt * Initialize callouts 709df930be7Sderaadt */ 710df930be7Sderaadt callfree = callout; 711df930be7Sderaadt for (i = 1; i < ncallout; i++) 712df930be7Sderaadt callout[i-1].c_next = &callout[i]; 713df930be7Sderaadt callout[i-1].c_next = NULL; 714df930be7Sderaadt 71550ce9ee0Sniklas #if defined(DEBUG) 716df930be7Sderaadt pmapdebug = opmapdebug; 717df930be7Sderaadt #endif 718df930be7Sderaadt printf("avail mem = %ld\n", (long)ptoa(cnt.v_free_count)); 719df930be7Sderaadt printf("using %ld buffers containing %ld bytes of memory\n", 720df930be7Sderaadt (long)nbuf, (long)(bufpages * CLBYTES)); 721df930be7Sderaadt 722df930be7Sderaadt /* 723df930be7Sderaadt * Set up buffers, so they can be used to read disk labels. 724df930be7Sderaadt */ 725df930be7Sderaadt bufinit(); 726df930be7Sderaadt 727df930be7Sderaadt /* 728df930be7Sderaadt * Configure the system. 729df930be7Sderaadt */ 73041033391Sderaadt if (boothowto & RB_CONFIG) { 73141033391Sderaadt #ifdef BOOT_CONFIG 73241033391Sderaadt user_config(); 73341033391Sderaadt #else 73441033391Sderaadt printf("kernel does not support -c; continuing..\n"); 73541033391Sderaadt #endif 73641033391Sderaadt } 737df930be7Sderaadt configure(); 73850ce9ee0Sniklas 73950ce9ee0Sniklas /* 74050ce9ee0Sniklas * Note that bootstrapping is finished, and set the HWRPB up 74150ce9ee0Sniklas * to do restarts. 74250ce9ee0Sniklas */ 7433a630e3fSniklas hwrpb_restart_setup(); 744df930be7Sderaadt } 745df930be7Sderaadt 74650ce9ee0Sniklas void 747df930be7Sderaadt identifycpu() 748df930be7Sderaadt { 749df930be7Sderaadt 750df930be7Sderaadt /* 751df930be7Sderaadt * print out CPU identification information. 752df930be7Sderaadt */ 75350ce9ee0Sniklas printf("%s, %ldMHz\n", cpu_model, 754df930be7Sderaadt hwrpb->rpb_cc_freq / 1000000); /* XXX true for 21164? */ 75550ce9ee0Sniklas printf("%ld byte page size, %d processor%s.\n", 756df930be7Sderaadt hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s"); 757df930be7Sderaadt #if 0 758df930be7Sderaadt /* this isn't defined for any systems that we run on? */ 759df930be7Sderaadt printf("serial number 0x%lx 0x%lx\n", 760df930be7Sderaadt ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]); 761df930be7Sderaadt 762df930be7Sderaadt /* and these aren't particularly useful! */ 763df930be7Sderaadt printf("variation: 0x%lx, revision 0x%lx\n", 764df930be7Sderaadt hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision); 765df930be7Sderaadt #endif 766df930be7Sderaadt } 767df930be7Sderaadt 768df930be7Sderaadt int waittime = -1; 769df930be7Sderaadt struct pcb dumppcb; 770df930be7Sderaadt 771417eba8cSderaadt void 77250ce9ee0Sniklas boot(howto /* , bootstr */) 773df930be7Sderaadt int howto; 77450ce9ee0Sniklas /* char *bootstr; */ 775df930be7Sderaadt { 776df930be7Sderaadt extern int cold; 777df930be7Sderaadt 778df930be7Sderaadt /* If system is cold, just halt. */ 779df930be7Sderaadt if (cold) { 780df930be7Sderaadt howto |= RB_HALT; 781df930be7Sderaadt goto haltsys; 782df930be7Sderaadt } 783df930be7Sderaadt 78450ce9ee0Sniklas /* If "always halt" was specified as a boot flag, obey. */ 78550ce9ee0Sniklas if ((boothowto & RB_HALT) != 0) 78650ce9ee0Sniklas howto |= RB_HALT; 78750ce9ee0Sniklas 788df930be7Sderaadt boothowto = howto; 789df930be7Sderaadt if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 79050ce9ee0Sniklas extern struct proc proc0; 79150ce9ee0Sniklas 79250ce9ee0Sniklas /* protect against curproc->p_stats.foo refs in sync XXX */ 79350ce9ee0Sniklas if (curproc == NULL) 79450ce9ee0Sniklas curproc = &proc0; 79550ce9ee0Sniklas 796df930be7Sderaadt waittime = 0; 797df930be7Sderaadt vfs_shutdown(); 798df930be7Sderaadt /* 799df930be7Sderaadt * If we've been adjusting the clock, the todr 80067365115Skstailey * will be out of synch; adjust it now unless 80167365115Skstailey * the system was sitting in ddb. 802df930be7Sderaadt */ 80367365115Skstailey if ((howto & RB_TIMEBAD) == 0) { 804df930be7Sderaadt resettodr(); 80567365115Skstailey } else { 80667365115Skstailey printf("WARNING: not updating battery clock\n"); 80767365115Skstailey } 808df930be7Sderaadt } 809df930be7Sderaadt 810df930be7Sderaadt /* Disable interrupts. */ 811df930be7Sderaadt splhigh(); 812df930be7Sderaadt 813df930be7Sderaadt /* If rebooting and a dump is requested do it. */ 81450ce9ee0Sniklas #if 0 81550ce9ee0Sniklas if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 81650ce9ee0Sniklas #else 81750ce9ee0Sniklas if (howto & RB_DUMP) 81850ce9ee0Sniklas #endif 819df930be7Sderaadt dumpsys(); 820df930be7Sderaadt 82134fbf6deSderaadt haltsys: 82234fbf6deSderaadt 823df930be7Sderaadt /* run any shutdown hooks */ 824df930be7Sderaadt doshutdownhooks(); 825df930be7Sderaadt 826df930be7Sderaadt #ifdef BOOTKEY 827df930be7Sderaadt printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot"); 828df930be7Sderaadt cngetc(); 829df930be7Sderaadt printf("\n"); 830df930be7Sderaadt #endif 831df930be7Sderaadt 832df930be7Sderaadt /* Finally, halt/reboot the system. */ 833df930be7Sderaadt printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 834df930be7Sderaadt prom_halt(howto & RB_HALT); 835df930be7Sderaadt /*NOTREACHED*/ 836df930be7Sderaadt } 837df930be7Sderaadt 838df930be7Sderaadt /* 839df930be7Sderaadt * These variables are needed by /sbin/savecore 840df930be7Sderaadt */ 841df930be7Sderaadt u_long dumpmag = 0x8fca0101; /* magic number */ 842df930be7Sderaadt int dumpsize = 0; /* pages */ 843df930be7Sderaadt long dumplo = 0; /* blocks */ 844df930be7Sderaadt 845df930be7Sderaadt /* 84650ce9ee0Sniklas * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. 84750ce9ee0Sniklas */ 84850ce9ee0Sniklas int 84950ce9ee0Sniklas cpu_dumpsize() 85050ce9ee0Sniklas { 85150ce9ee0Sniklas int size; 85250ce9ee0Sniklas 85350ce9ee0Sniklas size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); 85450ce9ee0Sniklas if (roundup(size, dbtob(1)) != dbtob(1)) 85550ce9ee0Sniklas return -1; 85650ce9ee0Sniklas 85750ce9ee0Sniklas return (1); 85850ce9ee0Sniklas } 85950ce9ee0Sniklas 86050ce9ee0Sniklas /* 86150ce9ee0Sniklas * cpu_dump: dump machine-dependent kernel core dump headers. 86250ce9ee0Sniklas */ 86350ce9ee0Sniklas int 86450ce9ee0Sniklas cpu_dump() 86550ce9ee0Sniklas { 86650ce9ee0Sniklas int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 86750ce9ee0Sniklas long buf[dbtob(1) / sizeof (long)]; 86850ce9ee0Sniklas kcore_seg_t *segp; 86950ce9ee0Sniklas cpu_kcore_hdr_t *cpuhdrp; 87050ce9ee0Sniklas 87150ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 87250ce9ee0Sniklas 87350ce9ee0Sniklas segp = (kcore_seg_t *)buf; 87450ce9ee0Sniklas cpuhdrp = 87550ce9ee0Sniklas (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; 87650ce9ee0Sniklas 87750ce9ee0Sniklas /* 87850ce9ee0Sniklas * Generate a segment header. 87950ce9ee0Sniklas */ 88050ce9ee0Sniklas CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 88150ce9ee0Sniklas segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); 88250ce9ee0Sniklas 88350ce9ee0Sniklas /* 88450ce9ee0Sniklas * Add the machine-dependent header info 88550ce9ee0Sniklas */ 88650ce9ee0Sniklas cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map); 88750ce9ee0Sniklas cpuhdrp->page_size = PAGE_SIZE; 88850ce9ee0Sniklas cpuhdrp->core_seg.start = ctob(firstusablepage); 88950ce9ee0Sniklas cpuhdrp->core_seg.size = ctob(physmem); 89050ce9ee0Sniklas 89150ce9ee0Sniklas return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1))); 89250ce9ee0Sniklas } 89350ce9ee0Sniklas 89450ce9ee0Sniklas /* 895df930be7Sderaadt * This is called by configure to set dumplo and dumpsize. 896df930be7Sderaadt * Dumps always skip the first CLBYTES of disk space 897df930be7Sderaadt * in case there might be a disk label stored there. 898df930be7Sderaadt * If there is extra space, put dump at the end to 899df930be7Sderaadt * reduce the chance that swapping trashes it. 900df930be7Sderaadt */ 901df930be7Sderaadt void 902df930be7Sderaadt dumpconf() 903df930be7Sderaadt { 90450ce9ee0Sniklas int nblks, dumpblks; /* size of dump area */ 905df930be7Sderaadt int maj; 906df930be7Sderaadt 907df930be7Sderaadt if (dumpdev == NODEV) 90850ce9ee0Sniklas goto bad; 909df930be7Sderaadt maj = major(dumpdev); 910df930be7Sderaadt if (maj < 0 || maj >= nblkdev) 911df930be7Sderaadt panic("dumpconf: bad dumpdev=0x%x", dumpdev); 912df930be7Sderaadt if (bdevsw[maj].d_psize == NULL) 91350ce9ee0Sniklas goto bad; 914df930be7Sderaadt nblks = (*bdevsw[maj].d_psize)(dumpdev); 915df930be7Sderaadt if (nblks <= ctod(1)) 91650ce9ee0Sniklas goto bad; 91750ce9ee0Sniklas 91850ce9ee0Sniklas dumpblks = cpu_dumpsize(); 91950ce9ee0Sniklas if (dumpblks < 0) 92050ce9ee0Sniklas goto bad; 92150ce9ee0Sniklas dumpblks += ctod(physmem); 92250ce9ee0Sniklas 92350ce9ee0Sniklas /* If dump won't fit (incl. room for possible label), punt. */ 92450ce9ee0Sniklas if (dumpblks > (nblks - ctod(1))) 92550ce9ee0Sniklas goto bad; 92650ce9ee0Sniklas 92750ce9ee0Sniklas /* Put dump at end of partition */ 92850ce9ee0Sniklas dumplo = nblks - dumpblks; 92950ce9ee0Sniklas 93050ce9ee0Sniklas /* dumpsize is in page units, and doesn't include headers. */ 93150ce9ee0Sniklas dumpsize = physmem; 932df930be7Sderaadt return; 933df930be7Sderaadt 93450ce9ee0Sniklas bad: 93550ce9ee0Sniklas dumpsize = 0; 93650ce9ee0Sniklas return; 937df930be7Sderaadt } 938df930be7Sderaadt 939df930be7Sderaadt /* 94050ce9ee0Sniklas * Dump the kernel's image to the swap partition. 941df930be7Sderaadt */ 94250ce9ee0Sniklas #define BYTES_PER_DUMP NBPG 94350ce9ee0Sniklas 944df930be7Sderaadt void 945df930be7Sderaadt dumpsys() 946df930be7Sderaadt { 94750ce9ee0Sniklas unsigned bytes, i, n; 94850ce9ee0Sniklas int maddr, psize; 94950ce9ee0Sniklas daddr_t blkno; 95050ce9ee0Sniklas int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 95150ce9ee0Sniklas int error; 952df930be7Sderaadt 95350ce9ee0Sniklas /* Save registers. */ 95450ce9ee0Sniklas savectx(&dumppcb); 95550ce9ee0Sniklas 95650ce9ee0Sniklas msgbufmapped = 0; /* don't record dump msgs in msgbuf */ 957df930be7Sderaadt if (dumpdev == NODEV) 958df930be7Sderaadt return; 95950ce9ee0Sniklas 96050ce9ee0Sniklas /* 96150ce9ee0Sniklas * For dumps during autoconfiguration, 96250ce9ee0Sniklas * if dump device has already configured... 96350ce9ee0Sniklas */ 964df930be7Sderaadt if (dumpsize == 0) 96550ce9ee0Sniklas dumpconf(); 96650ce9ee0Sniklas if (dumplo <= 0) { 96750ce9ee0Sniklas printf("\ndump to dev %x not possible\n", dumpdev); 968df930be7Sderaadt return; 969df930be7Sderaadt } 97050ce9ee0Sniklas printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo); 971df930be7Sderaadt 97250ce9ee0Sniklas psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 973df930be7Sderaadt printf("dump "); 97450ce9ee0Sniklas if (psize == -1) { 97550ce9ee0Sniklas printf("area unavailable\n"); 97650ce9ee0Sniklas return; 97750ce9ee0Sniklas } 97850ce9ee0Sniklas 97950ce9ee0Sniklas /* XXX should purge all outstanding keystrokes. */ 98050ce9ee0Sniklas 98150ce9ee0Sniklas if ((error = cpu_dump()) != 0) 98250ce9ee0Sniklas goto err; 98350ce9ee0Sniklas 98450ce9ee0Sniklas bytes = ctob(physmem); 98550ce9ee0Sniklas maddr = ctob(firstusablepage); 98650ce9ee0Sniklas blkno = dumplo + cpu_dumpsize(); 98750ce9ee0Sniklas dump = bdevsw[major(dumpdev)].d_dump; 98850ce9ee0Sniklas error = 0; 98950ce9ee0Sniklas for (i = 0; i < bytes; i += n) { 99050ce9ee0Sniklas 99150ce9ee0Sniklas /* Print out how many MBs we to go. */ 99250ce9ee0Sniklas n = bytes - i; 99350ce9ee0Sniklas if (n && (n % (1024*1024)) == 0) 99450ce9ee0Sniklas printf("%d ", n / (1024 * 1024)); 99550ce9ee0Sniklas 99650ce9ee0Sniklas /* Limit size for next transfer. */ 99750ce9ee0Sniklas if (n > BYTES_PER_DUMP) 99850ce9ee0Sniklas n = BYTES_PER_DUMP; 99950ce9ee0Sniklas 100050ce9ee0Sniklas error = (*dump)(dumpdev, blkno, 100150ce9ee0Sniklas (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n); 100250ce9ee0Sniklas if (error) 100350ce9ee0Sniklas break; 100450ce9ee0Sniklas maddr += n; 100550ce9ee0Sniklas blkno += btodb(n); /* XXX? */ 100650ce9ee0Sniklas 100750ce9ee0Sniklas /* XXX should look for keystrokes, to cancel. */ 100850ce9ee0Sniklas } 100950ce9ee0Sniklas 101050ce9ee0Sniklas err: 101150ce9ee0Sniklas switch (error) { 1012df930be7Sderaadt 1013df930be7Sderaadt case ENXIO: 1014df930be7Sderaadt printf("device bad\n"); 1015df930be7Sderaadt break; 1016df930be7Sderaadt 1017df930be7Sderaadt case EFAULT: 1018df930be7Sderaadt printf("device not ready\n"); 1019df930be7Sderaadt break; 1020df930be7Sderaadt 1021df930be7Sderaadt case EINVAL: 1022df930be7Sderaadt printf("area improper\n"); 1023df930be7Sderaadt break; 1024df930be7Sderaadt 1025df930be7Sderaadt case EIO: 1026df930be7Sderaadt printf("i/o error\n"); 1027df930be7Sderaadt break; 1028df930be7Sderaadt 1029df930be7Sderaadt case EINTR: 1030df930be7Sderaadt printf("aborted from console\n"); 1031df930be7Sderaadt break; 1032df930be7Sderaadt 103350ce9ee0Sniklas case 0: 1034df930be7Sderaadt printf("succeeded\n"); 1035df930be7Sderaadt break; 103650ce9ee0Sniklas 103750ce9ee0Sniklas default: 103850ce9ee0Sniklas printf("error %d\n", error); 103950ce9ee0Sniklas break; 1040df930be7Sderaadt } 1041df930be7Sderaadt printf("\n\n"); 1042df930be7Sderaadt delay(1000); 1043df930be7Sderaadt } 1044df930be7Sderaadt 1045df930be7Sderaadt void 1046df930be7Sderaadt frametoreg(framep, regp) 1047df930be7Sderaadt struct trapframe *framep; 1048df930be7Sderaadt struct reg *regp; 1049df930be7Sderaadt { 1050df930be7Sderaadt 1051df930be7Sderaadt regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0]; 1052df930be7Sderaadt regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0]; 1053df930be7Sderaadt regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1]; 1054df930be7Sderaadt regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2]; 1055df930be7Sderaadt regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3]; 1056df930be7Sderaadt regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4]; 1057df930be7Sderaadt regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5]; 1058df930be7Sderaadt regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6]; 1059df930be7Sderaadt regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7]; 1060df930be7Sderaadt regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0]; 1061df930be7Sderaadt regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1]; 1062df930be7Sderaadt regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2]; 1063df930be7Sderaadt regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3]; 1064df930be7Sderaadt regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; 1065df930be7Sderaadt regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; 1066df930be7Sderaadt regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; 106750ce9ee0Sniklas regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; 106850ce9ee0Sniklas regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; 106950ce9ee0Sniklas regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; 1070df930be7Sderaadt regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; 1071df930be7Sderaadt regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; 1072df930be7Sderaadt regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; 1073df930be7Sderaadt regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8]; 1074df930be7Sderaadt regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9]; 1075df930be7Sderaadt regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10]; 1076df930be7Sderaadt regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11]; 1077df930be7Sderaadt regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; 1078df930be7Sderaadt regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; 1079df930be7Sderaadt regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; 108050ce9ee0Sniklas regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; 108150ce9ee0Sniklas /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ 1082df930be7Sderaadt regp->r_regs[R_ZERO] = 0; 1083df930be7Sderaadt } 1084df930be7Sderaadt 1085df930be7Sderaadt void 1086df930be7Sderaadt regtoframe(regp, framep) 1087df930be7Sderaadt struct reg *regp; 1088df930be7Sderaadt struct trapframe *framep; 1089df930be7Sderaadt { 1090df930be7Sderaadt 1091df930be7Sderaadt framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0]; 1092df930be7Sderaadt framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0]; 1093df930be7Sderaadt framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1]; 1094df930be7Sderaadt framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2]; 1095df930be7Sderaadt framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3]; 1096df930be7Sderaadt framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4]; 1097df930be7Sderaadt framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5]; 1098df930be7Sderaadt framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6]; 1099df930be7Sderaadt framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7]; 1100df930be7Sderaadt framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0]; 1101df930be7Sderaadt framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1]; 1102df930be7Sderaadt framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2]; 1103df930be7Sderaadt framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3]; 1104df930be7Sderaadt framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; 1105df930be7Sderaadt framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; 1106df930be7Sderaadt framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; 110750ce9ee0Sniklas framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; 110850ce9ee0Sniklas framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; 110950ce9ee0Sniklas framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; 1110df930be7Sderaadt framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; 1111df930be7Sderaadt framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; 1112df930be7Sderaadt framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; 1113df930be7Sderaadt framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8]; 1114df930be7Sderaadt framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9]; 1115df930be7Sderaadt framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10]; 1116df930be7Sderaadt framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11]; 1117df930be7Sderaadt framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; 1118df930be7Sderaadt framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; 1119df930be7Sderaadt framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; 112050ce9ee0Sniklas framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; 112150ce9ee0Sniklas /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ 1122df930be7Sderaadt /* ??? = regp->r_regs[R_ZERO]; */ 1123df930be7Sderaadt } 1124df930be7Sderaadt 1125df930be7Sderaadt void 1126df930be7Sderaadt printregs(regp) 1127df930be7Sderaadt struct reg *regp; 1128df930be7Sderaadt { 1129df930be7Sderaadt int i; 1130df930be7Sderaadt 1131df930be7Sderaadt for (i = 0; i < 32; i++) 1132df930be7Sderaadt printf("R%d:\t0x%016lx%s", i, regp->r_regs[i], 1133df930be7Sderaadt i & 1 ? "\n" : "\t"); 1134df930be7Sderaadt } 1135df930be7Sderaadt 1136df930be7Sderaadt void 1137df930be7Sderaadt regdump(framep) 1138df930be7Sderaadt struct trapframe *framep; 1139df930be7Sderaadt { 1140df930be7Sderaadt struct reg reg; 1141df930be7Sderaadt 1142df930be7Sderaadt frametoreg(framep, ®); 114350ce9ee0Sniklas reg.r_regs[R_SP] = alpha_pal_rdusp(); 114450ce9ee0Sniklas 1145df930be7Sderaadt printf("REGISTERS:\n"); 1146df930be7Sderaadt printregs(®); 1147df930be7Sderaadt } 1148df930be7Sderaadt 1149df930be7Sderaadt #ifdef DEBUG 1150df930be7Sderaadt int sigdebug = 0; 1151df930be7Sderaadt int sigpid = 0; 1152df930be7Sderaadt #define SDB_FOLLOW 0x01 1153df930be7Sderaadt #define SDB_KSTACK 0x02 1154df930be7Sderaadt #endif 1155df930be7Sderaadt 1156df930be7Sderaadt /* 1157df930be7Sderaadt * Send an interrupt to process. 1158df930be7Sderaadt */ 1159df930be7Sderaadt void 11605e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val) 1161df930be7Sderaadt sig_t catcher; 1162df930be7Sderaadt int sig, mask; 1163df930be7Sderaadt u_long code; 11645e1760a6Sderaadt int type; 11655e1760a6Sderaadt union sigval val; 1166df930be7Sderaadt { 1167df930be7Sderaadt struct proc *p = curproc; 1168df930be7Sderaadt struct sigcontext *scp, ksc; 1169df930be7Sderaadt struct trapframe *frame; 1170df930be7Sderaadt struct sigacts *psp = p->p_sigacts; 11712bf9c155Sderaadt int oonstack, fsize, rndfsize, kscsize; 1172df930be7Sderaadt extern char sigcode[], esigcode[]; 1173df930be7Sderaadt extern struct proc *fpcurproc; 11742bf9c155Sderaadt siginfo_t *sip, ksi; 1175df930be7Sderaadt 1176df930be7Sderaadt frame = p->p_md.md_tf; 1177df930be7Sderaadt oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 1178df930be7Sderaadt fsize = sizeof ksc; 1179df930be7Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 11802bf9c155Sderaadt kscsize = rndfsize; 11812bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 11822bf9c155Sderaadt fsize += sizeof ksi; 11832bf9c155Sderaadt rndfsize = ((fsize + 15) / 16) * 16; 11842bf9c155Sderaadt } 118574652a67Sniklas 1186df930be7Sderaadt /* 1187df930be7Sderaadt * Allocate and validate space for the signal handler 1188df930be7Sderaadt * context. Note that if the stack is in P0 space, the 1189df930be7Sderaadt * call to grow() is a nop, and the useracc() check 1190df930be7Sderaadt * will fail if the process has not already allocated 1191df930be7Sderaadt * the space with a `brk'. 1192df930be7Sderaadt */ 1193df930be7Sderaadt if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 1194df930be7Sderaadt (psp->ps_sigonstack & sigmask(sig))) { 11958bc2093aSderaadt scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp + 1196df930be7Sderaadt psp->ps_sigstk.ss_size - rndfsize); 1197df930be7Sderaadt psp->ps_sigstk.ss_flags |= SS_ONSTACK; 1198df930be7Sderaadt } else 119950ce9ee0Sniklas scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize); 1200df930be7Sderaadt if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 1201df930be7Sderaadt (void)grow(p, (u_long)scp); 1202df930be7Sderaadt #ifdef DEBUG 1203df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 120450ce9ee0Sniklas printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, 1205df930be7Sderaadt sig, &oonstack, scp); 1206df930be7Sderaadt #endif 1207df930be7Sderaadt if (useracc((caddr_t)scp, fsize, B_WRITE) == 0) { 1208df930be7Sderaadt #ifdef DEBUG 1209df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1210df930be7Sderaadt printf("sendsig(%d): useracc failed on sig %d\n", 1211df930be7Sderaadt p->p_pid, sig); 1212df930be7Sderaadt #endif 1213df930be7Sderaadt /* 1214df930be7Sderaadt * Process has trashed its stack; give it an illegal 1215df930be7Sderaadt * instruction to halt it in its tracks. 1216df930be7Sderaadt */ 1217df930be7Sderaadt SIGACTION(p, SIGILL) = SIG_DFL; 1218df930be7Sderaadt sig = sigmask(SIGILL); 1219df930be7Sderaadt p->p_sigignore &= ~sig; 1220df930be7Sderaadt p->p_sigcatch &= ~sig; 1221df930be7Sderaadt p->p_sigmask &= ~sig; 1222df930be7Sderaadt psignal(p, SIGILL); 1223df930be7Sderaadt return; 1224df930be7Sderaadt } 1225df930be7Sderaadt 1226df930be7Sderaadt /* 1227df930be7Sderaadt * Build the signal context to be used by sigreturn. 1228df930be7Sderaadt */ 1229df930be7Sderaadt ksc.sc_onstack = oonstack; 1230df930be7Sderaadt ksc.sc_mask = mask; 123150ce9ee0Sniklas ksc.sc_pc = frame->tf_regs[FRAME_PC]; 123250ce9ee0Sniklas ksc.sc_ps = frame->tf_regs[FRAME_PS]; 1233df930be7Sderaadt 1234df930be7Sderaadt /* copy the registers. */ 1235df930be7Sderaadt frametoreg(frame, (struct reg *)ksc.sc_regs); 1236df930be7Sderaadt ksc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ 123750ce9ee0Sniklas ksc.sc_regs[R_SP] = alpha_pal_rdusp(); 1238df930be7Sderaadt 1239df930be7Sderaadt /* save the floating-point state, if necessary, then copy it. */ 1240df930be7Sderaadt if (p == fpcurproc) { 124150ce9ee0Sniklas alpha_pal_wrfen(1); 1242df930be7Sderaadt savefpstate(&p->p_addr->u_pcb.pcb_fp); 124350ce9ee0Sniklas alpha_pal_wrfen(0); 1244df930be7Sderaadt fpcurproc = NULL; 1245df930be7Sderaadt } 1246df930be7Sderaadt ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED; 1247df930be7Sderaadt bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs, 1248df930be7Sderaadt sizeof(struct fpreg)); 1249df930be7Sderaadt ksc.sc_fp_control = 0; /* XXX ? */ 1250df930be7Sderaadt bzero(ksc.sc_reserved, sizeof ksc.sc_reserved); /* XXX */ 1251df930be7Sderaadt bzero(ksc.sc_xxx, sizeof ksc.sc_xxx); /* XXX */ 1252df930be7Sderaadt 1253df930be7Sderaadt 1254df930be7Sderaadt #ifdef COMPAT_OSF1 1255df930be7Sderaadt /* 1256df930be7Sderaadt * XXX Create an OSF/1-style sigcontext and associated goo. 1257df930be7Sderaadt */ 1258df930be7Sderaadt #endif 1259df930be7Sderaadt 12602bf9c155Sderaadt if (psp->ps_siginfo & sigmask(sig)) { 12612bf9c155Sderaadt initsiginfo(&ksi, sig, code, type, val); 12622bf9c155Sderaadt sip = (void *)scp + kscsize; 12632bf9c155Sderaadt (void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize); 12642bf9c155Sderaadt } 12652bf9c155Sderaadt 1266df930be7Sderaadt /* 1267df930be7Sderaadt * copy the frame out to userland. 1268df930be7Sderaadt */ 12692bf9c155Sderaadt (void) copyout((caddr_t)&ksc, (caddr_t)scp, kscsize); 1270df930be7Sderaadt #ifdef DEBUG 1271df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 127250ce9ee0Sniklas printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig, 1273df930be7Sderaadt scp, code); 1274df930be7Sderaadt #endif 1275df930be7Sderaadt 1276df930be7Sderaadt /* 1277df930be7Sderaadt * Set up the registers to return to sigcode. 1278df930be7Sderaadt */ 127950ce9ee0Sniklas frame->tf_regs[FRAME_PC] = 128050ce9ee0Sniklas (u_int64_t)PS_STRINGS - (esigcode - sigcode); 128150ce9ee0Sniklas frame->tf_regs[FRAME_A0] = sig; 12822bf9c155Sderaadt frame->tf_regs[FRAME_A1] = (psp->ps_siginfo & sigmask(sig)) ? 12832bf9c155Sderaadt (u_int64_t)sip : NULL; 128450ce9ee0Sniklas frame->tf_regs[FRAME_A2] = (u_int64_t)scp; 1285df930be7Sderaadt frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */ 128650ce9ee0Sniklas alpha_pal_wrusp((unsigned long)scp); 1287df930be7Sderaadt 1288df930be7Sderaadt #ifdef DEBUG 1289df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1290df930be7Sderaadt printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, 129150ce9ee0Sniklas frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]); 1292df930be7Sderaadt if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1293df930be7Sderaadt printf("sendsig(%d): sig %d returns\n", 1294df930be7Sderaadt p->p_pid, sig); 1295df930be7Sderaadt #endif 1296df930be7Sderaadt } 1297df930be7Sderaadt 1298df930be7Sderaadt /* 1299df930be7Sderaadt * System call to cleanup state after a signal 1300df930be7Sderaadt * has been taken. Reset signal mask and 1301df930be7Sderaadt * stack state from context left by sendsig (above). 1302df930be7Sderaadt * Return to previous pc and psl as specified by 1303df930be7Sderaadt * context left by sendsig. Check carefully to 1304df930be7Sderaadt * make sure that the user has not modified the 1305df930be7Sderaadt * psl to gain improper priviledges or to cause 1306df930be7Sderaadt * a machine fault. 1307df930be7Sderaadt */ 1308df930be7Sderaadt /* ARGSUSED */ 1309df930be7Sderaadt int 1310df930be7Sderaadt sys_sigreturn(p, v, retval) 1311df930be7Sderaadt struct proc *p; 1312df930be7Sderaadt void *v; 1313df930be7Sderaadt register_t *retval; 1314df930be7Sderaadt { 1315df930be7Sderaadt struct sys_sigreturn_args /* { 1316df930be7Sderaadt syscallarg(struct sigcontext *) sigcntxp; 1317df930be7Sderaadt } */ *uap = v; 1318df930be7Sderaadt struct sigcontext *scp, ksc; 1319df930be7Sderaadt extern struct proc *fpcurproc; 1320df930be7Sderaadt 1321df930be7Sderaadt scp = SCARG(uap, sigcntxp); 1322df930be7Sderaadt #ifdef DEBUG 1323df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 132450ce9ee0Sniklas printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 1325df930be7Sderaadt #endif 1326df930be7Sderaadt 1327df930be7Sderaadt if (ALIGN(scp) != (u_int64_t)scp) 1328df930be7Sderaadt return (EINVAL); 1329df930be7Sderaadt 1330df930be7Sderaadt /* 1331df930be7Sderaadt * Test and fetch the context structure. 1332df930be7Sderaadt * We grab it all at once for speed. 1333df930be7Sderaadt */ 1334df930be7Sderaadt if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 || 1335df930be7Sderaadt copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)) 1336df930be7Sderaadt return (EINVAL); 1337df930be7Sderaadt 1338df930be7Sderaadt if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */ 1339df930be7Sderaadt return (EINVAL); 1340df930be7Sderaadt /* 1341df930be7Sderaadt * Restore the user-supplied information 1342df930be7Sderaadt */ 1343df930be7Sderaadt if (ksc.sc_onstack) 1344df930be7Sderaadt p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; 1345df930be7Sderaadt else 1346df930be7Sderaadt p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 1347df930be7Sderaadt p->p_sigmask = ksc.sc_mask &~ sigcantmask; 1348df930be7Sderaadt 134950ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc; 135050ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_PS] = 135150ce9ee0Sniklas (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; 1352df930be7Sderaadt 1353df930be7Sderaadt regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf); 135450ce9ee0Sniklas alpha_pal_wrusp(ksc.sc_regs[R_SP]); 1355df930be7Sderaadt 1356df930be7Sderaadt /* XXX ksc.sc_ownedfp ? */ 1357df930be7Sderaadt if (p == fpcurproc) 1358df930be7Sderaadt fpcurproc = NULL; 1359df930be7Sderaadt bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp, 1360df930be7Sderaadt sizeof(struct fpreg)); 1361df930be7Sderaadt /* XXX ksc.sc_fp_control ? */ 1362df930be7Sderaadt 1363df930be7Sderaadt #ifdef DEBUG 1364df930be7Sderaadt if (sigdebug & SDB_FOLLOW) 1365df930be7Sderaadt printf("sigreturn(%d): returns\n", p->p_pid); 1366df930be7Sderaadt #endif 1367df930be7Sderaadt return (EJUSTRETURN); 1368df930be7Sderaadt } 1369df930be7Sderaadt 1370df930be7Sderaadt /* 1371df930be7Sderaadt * machine dependent system variables. 1372df930be7Sderaadt */ 137350ce9ee0Sniklas int 1374df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 1375df930be7Sderaadt int *name; 1376df930be7Sderaadt u_int namelen; 1377df930be7Sderaadt void *oldp; 1378df930be7Sderaadt size_t *oldlenp; 1379df930be7Sderaadt void *newp; 1380df930be7Sderaadt size_t newlen; 1381df930be7Sderaadt struct proc *p; 1382df930be7Sderaadt { 1383df930be7Sderaadt dev_t consdev; 1384df930be7Sderaadt 1385df930be7Sderaadt /* all sysctl names at this level are terminal */ 1386df930be7Sderaadt if (namelen != 1) 1387df930be7Sderaadt return (ENOTDIR); /* overloaded */ 1388df930be7Sderaadt 1389df930be7Sderaadt switch (name[0]) { 1390df930be7Sderaadt case CPU_CONSDEV: 1391df930be7Sderaadt if (cn_tab != NULL) 1392df930be7Sderaadt consdev = cn_tab->cn_dev; 1393df930be7Sderaadt else 1394df930be7Sderaadt consdev = NODEV; 1395df930be7Sderaadt return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 1396df930be7Sderaadt sizeof consdev)); 1397417eba8cSderaadt 1398417eba8cSderaadt case CPU_ROOT_DEVICE: 1399417eba8cSderaadt return (sysctl_rdstring(oldp, oldlenp, newp, root_device)); 1400417eba8cSderaadt 140150ce9ee0Sniklas case CPU_UNALIGNED_PRINT: 140250ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 140350ce9ee0Sniklas &alpha_unaligned_print)); 140450ce9ee0Sniklas 140550ce9ee0Sniklas case CPU_UNALIGNED_FIX: 140650ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 140750ce9ee0Sniklas &alpha_unaligned_fix)); 140850ce9ee0Sniklas 140950ce9ee0Sniklas case CPU_UNALIGNED_SIGBUS: 141050ce9ee0Sniklas return (sysctl_int(oldp, oldlenp, newp, newlen, 141150ce9ee0Sniklas &alpha_unaligned_sigbus)); 141250ce9ee0Sniklas 14133a630e3fSniklas case CPU_BOOTED_KERNEL: 14143a630e3fSniklas return (sysctl_rdstring(oldp, oldlenp, newp, booted_kernel)); 14153a630e3fSniklas 1416df930be7Sderaadt default: 1417df930be7Sderaadt return (EOPNOTSUPP); 1418df930be7Sderaadt } 1419df930be7Sderaadt /* NOTREACHED */ 1420df930be7Sderaadt } 1421df930be7Sderaadt 1422df930be7Sderaadt /* 1423df930be7Sderaadt * Set registers on exec. 1424df930be7Sderaadt */ 1425df930be7Sderaadt void 1426df930be7Sderaadt setregs(p, pack, stack, retval) 1427df930be7Sderaadt register struct proc *p; 1428df930be7Sderaadt struct exec_package *pack; 1429df930be7Sderaadt u_long stack; 1430df930be7Sderaadt register_t *retval; 1431df930be7Sderaadt { 1432df930be7Sderaadt struct trapframe *tfp = p->p_md.md_tf; 1433df930be7Sderaadt extern struct proc *fpcurproc; 14343a630e3fSniklas #ifdef DEBUG 14353a630e3fSniklas int i; 14363a630e3fSniklas #endif 1437df930be7Sderaadt 1438df930be7Sderaadt #ifdef DEBUG 143950ce9ee0Sniklas /* 144050ce9ee0Sniklas * Crash and dump, if the user requested it. 144150ce9ee0Sniklas */ 144250ce9ee0Sniklas if (boothowto & RB_DUMP) 144350ce9ee0Sniklas panic("crash requested by boot flags"); 144450ce9ee0Sniklas #endif 144550ce9ee0Sniklas 144650ce9ee0Sniklas #ifdef DEBUG 144750ce9ee0Sniklas for (i = 0; i < FRAME_SIZE; i++) 1448df930be7Sderaadt tfp->tf_regs[i] = 0xbabefacedeadbeef; 1449df930be7Sderaadt #else 145050ce9ee0Sniklas bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]); 1451df930be7Sderaadt #endif 1452df930be7Sderaadt bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp); 1453df930be7Sderaadt #define FP_RN 2 /* XXX */ 1454df930be7Sderaadt p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58; 145550ce9ee0Sniklas alpha_pal_wrusp(stack); 145650ce9ee0Sniklas tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; 145750ce9ee0Sniklas tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; 1458df930be7Sderaadt 145950ce9ee0Sniklas tfp->tf_regs[FRAME_A0] = stack; 146050ce9ee0Sniklas /* a1 and a2 already zeroed */ 146150ce9ee0Sniklas tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ 146250ce9ee0Sniklas 146350ce9ee0Sniklas p->p_md.md_flags &= ~MDP_FPUSED; 1464df930be7Sderaadt if (fpcurproc == p) 1465df930be7Sderaadt fpcurproc = NULL; 1466df930be7Sderaadt 1467df930be7Sderaadt retval[0] = retval[1] = 0; 1468df930be7Sderaadt } 1469df930be7Sderaadt 1470df930be7Sderaadt void 1471df930be7Sderaadt netintr() 1472df930be7Sderaadt { 147350ce9ee0Sniklas int n, s; 147450ce9ee0Sniklas 147550ce9ee0Sniklas s = splhigh(); 147650ce9ee0Sniklas n = netisr; 147750ce9ee0Sniklas netisr = 0; 147850ce9ee0Sniklas splx(s); 147950ce9ee0Sniklas 148050ce9ee0Sniklas #define DONETISR(bit, fn) \ 148150ce9ee0Sniklas do { \ 148250ce9ee0Sniklas if (n & (1 << (bit))) \ 148350ce9ee0Sniklas fn; \ 148450ce9ee0Sniklas } while (0) 148550ce9ee0Sniklas 1486df930be7Sderaadt #ifdef INET 148750ce9ee0Sniklas DONETISR(NETISR_ARP, arpintr()); 148850ce9ee0Sniklas DONETISR(NETISR_IP, ipintr()); 1489df930be7Sderaadt #endif 1490df930be7Sderaadt #ifdef NS 149150ce9ee0Sniklas DONETISR(NETISR_NS, nsintr()); 1492df930be7Sderaadt #endif 1493df930be7Sderaadt #ifdef ISO 149450ce9ee0Sniklas DONETISR(NETISR_ISO, clnlintr()); 1495df930be7Sderaadt #endif 1496df930be7Sderaadt #ifdef CCITT 149750ce9ee0Sniklas DONETISR(NETISR_CCITT, ccittintr()); 1498df930be7Sderaadt #endif 149950ce9ee0Sniklas #ifdef NATM 150050ce9ee0Sniklas DONETISR(NETISR_NATM, natmintr()); 1501df930be7Sderaadt #endif 150250ce9ee0Sniklas #if NPPP > 1 150350ce9ee0Sniklas DONETISR(NETISR_PPP, pppintr()); 150450ce9ee0Sniklas #endif 150550ce9ee0Sniklas 150650ce9ee0Sniklas #undef DONETISR 1507df930be7Sderaadt } 1508df930be7Sderaadt 1509df930be7Sderaadt void 1510df930be7Sderaadt do_sir() 1511df930be7Sderaadt { 15123a630e3fSniklas u_int64_t n; 1513df930be7Sderaadt 15143a630e3fSniklas do { 15153a630e3fSniklas (void)splhigh(); 15163a630e3fSniklas n = ssir; 15173a630e3fSniklas ssir = 0; 15183a630e3fSniklas splsoft(); /* don't recurse through spl0() */ 15193a630e3fSniklas 15203a630e3fSniklas #define DO_SIR(bit, fn) \ 15213a630e3fSniklas do { \ 15223a630e3fSniklas if (n & (bit)) { \ 15233a630e3fSniklas cnt.v_soft++; \ 15243a630e3fSniklas fn; \ 15253a630e3fSniklas } \ 15263a630e3fSniklas } while (0) 15273a630e3fSniklas 15283a630e3fSniklas DO_SIR(SIR_NET, netintr()); 15293a630e3fSniklas DO_SIR(SIR_CLOCK, softclock()); 15303a630e3fSniklas 15313a630e3fSniklas #undef DO_SIR 15323a630e3fSniklas } while (ssir != 0); 1533df930be7Sderaadt } 1534df930be7Sderaadt 1535df930be7Sderaadt int 1536df930be7Sderaadt spl0() 1537df930be7Sderaadt { 1538df930be7Sderaadt 15393a630e3fSniklas if (ssir) 15403a630e3fSniklas do_sir(); /* it lowers the IPL itself */ 1541df930be7Sderaadt 154250ce9ee0Sniklas return (alpha_pal_swpipl(ALPHA_PSL_IPL_0)); 1543df930be7Sderaadt } 1544df930be7Sderaadt 1545df930be7Sderaadt /* 1546df930be7Sderaadt * The following primitives manipulate the run queues. _whichqs tells which 1547df930be7Sderaadt * of the 32 queues _qs have processes in them. Setrunqueue puts processes 1548e464495eSniklas * into queues, Remrunqueue removes them from queues. The running process is 1549e464495eSniklas * on no queue, other processes are on a queue related to p->p_priority, 1550e464495eSniklas * divided by 4 actually to shrink the 0-127 range of priorities into the 32 1551e464495eSniklas * available queues. 1552df930be7Sderaadt */ 1553df930be7Sderaadt /* 1554df930be7Sderaadt * setrunqueue(p) 1555df930be7Sderaadt * proc *p; 1556df930be7Sderaadt * 1557df930be7Sderaadt * Call should be made at splclock(), and p->p_stat should be SRUN. 1558df930be7Sderaadt */ 1559df930be7Sderaadt 1560df930be7Sderaadt void 1561df930be7Sderaadt setrunqueue(p) 1562df930be7Sderaadt struct proc *p; 1563df930be7Sderaadt { 1564df930be7Sderaadt int bit; 1565df930be7Sderaadt 1566df930be7Sderaadt /* firewall: p->p_back must be NULL */ 1567df930be7Sderaadt if (p->p_back != NULL) 1568df930be7Sderaadt panic("setrunqueue"); 1569df930be7Sderaadt 1570df930be7Sderaadt bit = p->p_priority >> 2; 1571df930be7Sderaadt whichqs |= (1 << bit); 1572df930be7Sderaadt p->p_forw = (struct proc *)&qs[bit]; 1573df930be7Sderaadt p->p_back = qs[bit].ph_rlink; 1574df930be7Sderaadt p->p_back->p_forw = p; 1575df930be7Sderaadt qs[bit].ph_rlink = p; 1576df930be7Sderaadt } 1577df930be7Sderaadt 1578df930be7Sderaadt /* 1579e464495eSniklas * remrunqueue(p) 1580df930be7Sderaadt * 1581df930be7Sderaadt * Call should be made at splclock(). 1582df930be7Sderaadt */ 1583df930be7Sderaadt void 1584d3cbbad5Skstailey remrunqueue(p) 1585df930be7Sderaadt struct proc *p; 1586df930be7Sderaadt { 1587df930be7Sderaadt int bit; 1588df930be7Sderaadt 1589df930be7Sderaadt bit = p->p_priority >> 2; 1590df930be7Sderaadt if ((whichqs & (1 << bit)) == 0) 1591d3cbbad5Skstailey panic("remrunqueue"); 1592df930be7Sderaadt 1593df930be7Sderaadt p->p_back->p_forw = p->p_forw; 1594df930be7Sderaadt p->p_forw->p_back = p->p_back; 1595df930be7Sderaadt p->p_back = NULL; /* for firewall checking. */ 1596df930be7Sderaadt 1597df930be7Sderaadt if ((struct proc *)&qs[bit] == qs[bit].ph_link) 1598df930be7Sderaadt whichqs &= ~(1 << bit); 1599df930be7Sderaadt } 1600df930be7Sderaadt 1601df930be7Sderaadt /* 1602df930be7Sderaadt * Return the best possible estimate of the time in the timeval 1603df930be7Sderaadt * to which tvp points. Unfortunately, we can't read the hardware registers. 1604df930be7Sderaadt * We guarantee that the time will be greater than the value obtained by a 1605df930be7Sderaadt * previous call. 1606df930be7Sderaadt */ 1607df930be7Sderaadt void 1608df930be7Sderaadt microtime(tvp) 1609df930be7Sderaadt register struct timeval *tvp; 1610df930be7Sderaadt { 1611df930be7Sderaadt int s = splclock(); 1612df930be7Sderaadt static struct timeval lasttime; 1613df930be7Sderaadt 1614df930be7Sderaadt *tvp = time; 1615df930be7Sderaadt #ifdef notdef 1616df930be7Sderaadt tvp->tv_usec += clkread(); 1617df930be7Sderaadt while (tvp->tv_usec > 1000000) { 1618df930be7Sderaadt tvp->tv_sec++; 1619df930be7Sderaadt tvp->tv_usec -= 1000000; 1620df930be7Sderaadt } 1621df930be7Sderaadt #endif 1622df930be7Sderaadt if (tvp->tv_sec == lasttime.tv_sec && 1623df930be7Sderaadt tvp->tv_usec <= lasttime.tv_usec && 1624df930be7Sderaadt (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 1625df930be7Sderaadt tvp->tv_sec++; 1626df930be7Sderaadt tvp->tv_usec -= 1000000; 1627df930be7Sderaadt } 1628df930be7Sderaadt lasttime = *tvp; 1629df930be7Sderaadt splx(s); 1630df930be7Sderaadt } 1631df930be7Sderaadt 1632417eba8cSderaadt /* 1633417eba8cSderaadt * Wait "n" microseconds. 1634417eba8cSderaadt */ 163550ce9ee0Sniklas void 1636417eba8cSderaadt delay(n) 163750ce9ee0Sniklas unsigned long n; 1638417eba8cSderaadt { 1639417eba8cSderaadt long N = cycles_per_usec * (n); 1640417eba8cSderaadt 1641417eba8cSderaadt while (N > 0) /* XXX */ 1642417eba8cSderaadt N -= 3; /* XXX */ 1643417eba8cSderaadt } 1644417eba8cSderaadt 1645df930be7Sderaadt #if defined(COMPAT_OSF1) || 1 /* XXX */ 16463a630e3fSniklas void cpu_exec_ecoff_setregs __P((struct proc *, struct exec_package *, 16473a630e3fSniklas u_long, register_t *)); 16483a630e3fSniklas 1649df930be7Sderaadt void 1650417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval) 1651df930be7Sderaadt struct proc *p; 1652417eba8cSderaadt struct exec_package *epp; 1653df930be7Sderaadt u_long stack; 1654df930be7Sderaadt register_t *retval; 1655df930be7Sderaadt { 1656417eba8cSderaadt struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; 1657df930be7Sderaadt 1658417eba8cSderaadt setregs(p, epp, stack, retval); 165950ce9ee0Sniklas p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value; 1660df930be7Sderaadt } 1661df930be7Sderaadt 1662df930be7Sderaadt /* 1663df930be7Sderaadt * cpu_exec_ecoff_hook(): 1664df930be7Sderaadt * cpu-dependent ECOFF format hook for execve(). 1665df930be7Sderaadt * 1666df930be7Sderaadt * Do any machine-dependent diddling of the exec package when doing ECOFF. 1667df930be7Sderaadt * 1668df930be7Sderaadt */ 1669df930be7Sderaadt int 1670417eba8cSderaadt cpu_exec_ecoff_hook(p, epp) 1671df930be7Sderaadt struct proc *p; 1672df930be7Sderaadt struct exec_package *epp; 1673df930be7Sderaadt { 1674417eba8cSderaadt struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; 1675a2f8ce8dSderaadt extern struct emul emul_native; 1676df930be7Sderaadt #ifdef COMPAT_OSF1 1677df930be7Sderaadt extern struct emul emul_osf1; 1678df930be7Sderaadt #endif 1679df930be7Sderaadt 1680417eba8cSderaadt switch (execp->f.f_magic) { 1681df930be7Sderaadt #ifdef COMPAT_OSF1 1682df930be7Sderaadt case ECOFF_MAGIC_ALPHA: 1683df930be7Sderaadt epp->ep_emul = &emul_osf1; 1684df930be7Sderaadt break; 1685df930be7Sderaadt #endif 1686df930be7Sderaadt 168750ce9ee0Sniklas case ECOFF_MAGIC_NATIVE_ALPHA: 1688a2f8ce8dSderaadt epp->ep_emul = &emul_native; 1689df930be7Sderaadt break; 1690df930be7Sderaadt 1691df930be7Sderaadt default: 169234fbf6deSderaadt return ENOEXEC; 1693df930be7Sderaadt } 1694df930be7Sderaadt return 0; 1695df930be7Sderaadt } 1696df930be7Sderaadt #endif 1697e464495eSniklas 1698e464495eSniklas /* XXX XXX BEGIN XXX XXX */ 1699e464495eSniklas vm_offset_t alpha_XXX_dmamap_or; /* XXX */ 1700e464495eSniklas /* XXX */ 1701e464495eSniklas vm_offset_t /* XXX */ 1702e464495eSniklas alpha_XXX_dmamap(v) /* XXX */ 1703e464495eSniklas vm_offset_t v; /* XXX */ 1704e464495eSniklas { /* XXX */ 1705e464495eSniklas /* XXX */ 1706e464495eSniklas return (vtophys(v) | alpha_XXX_dmamap_or); /* XXX */ 1707e464495eSniklas } /* XXX */ 1708e464495eSniklas /* XXX XXX END XXX XXX */ 1709