Annotation of sys/arch/hp300/hp300/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.115 2007/06/06 17:15:11 deraadt Exp $ */
2: /* $NetBSD: machdep.c,v 1.121 1999/03/26 23:41:29 mycroft Exp $ */
3:
4: /*
5: * Copyright (c) 1988 University of Utah.
6: * Copyright (c) 1982, 1986, 1990, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * the Systems Programming Group of the University of Utah Computer
11: * Science Department.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * from: Utah $Hdr: machdep.c 1.74 92/12/20$
38: *
39: * @(#)machdep.c 8.10 (Berkeley) 4/20/94
40: */
41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/buf.h>
45: #include <sys/timeout.h>
46: #include <sys/conf.h>
47: #include <sys/exec.h>
48: #include <sys/file.h>
49: #include <sys/ioctl.h>
50: #include <sys/kernel.h>
51: #include <sys/device.h>
52: #include <sys/malloc.h>
53: #include <sys/extent.h>
54: #include <sys/mbuf.h>
55: #include <sys/mount.h>
56: #include <sys/msgbuf.h>
57: #include <sys/proc.h>
58: #include <sys/reboot.h>
59: #include <sys/signalvar.h>
60: #include <sys/tty.h>
61: #include <sys/user.h>
62: #include <sys/exec.h>
63: #include <sys/core.h>
64: #include <sys/kcore.h>
65: #include <sys/vnode.h>
66: #include <sys/sysctl.h>
67: #include <sys/syscallargs.h>
68: #include <sys/syslog.h>
69: #ifdef SYSVMSG
70: #include <sys/msg.h>
71: #endif
72:
73: #include <machine/db_machdep.h>
74: #ifdef DDB
75: #include <ddb/db_var.h>
76: #endif
77: #include <ddb/db_sym.h>
78: #include <ddb/db_extern.h>
79:
80: #include <machine/autoconf.h>
81: #include <machine/cpu.h>
82: #include <machine/hp300spu.h>
83: #include <machine/kcore.h>
84: #include <machine/reg.h>
85: #include <machine/psl.h>
86: #include <machine/pte.h>
87:
88: #include <dev/cons.h>
89:
90: #include <uvm/uvm_extern.h>
91:
92: #ifdef USELEDS
93: #include <hp300/hp300/leds.h>
94: #endif
95:
96: /* the following is used externally (sysctl_hw) */
97: char machine[] = MACHINE; /* from <machine/param.h> */
98:
99: struct vm_map *exec_map = NULL;
100: struct vm_map *phys_map = NULL;
101:
102: extern paddr_t avail_start, avail_end;
103:
104: /*
105: * Declare these as initialized data so we can patch them.
106: */
107: #ifndef BUFCACHEPERCENT
108: #define BUFCACHEPERCENT 5
109: #endif
110:
111: #ifdef BUFPAGES
112: int bufpages = BUFPAGES;
113: #else
114: int bufpages = 0;
115: #endif
116: int bufcachepercent = BUFCACHEPERCENT;
117:
118: int physmem; /* size of physical memory, in pages */
119: /*
120: * safepri is a safe priority for sleep to set for a spin-wait
121: * during autoconfiguration or after a panic.
122: */
123: int safepri = PSL_LOWIPL;
124:
125: extern u_int lowram;
126: extern short exframesize[];
127:
128: #ifdef COMPAT_HPUX
129: extern struct emul emul_hpux;
130: #endif
131: #ifdef COMPAT_SUNOS
132: extern struct emul emul_sunos;
133: #endif
134:
135: /*
136: * Some storage space must be allocated statically because of the
137: * early console initialization.
138: */
139: char extiospace[EXTENT_FIXED_STORAGE_SIZE(8)];
140: extern int eiomapsize;
141:
142: /* prototypes for local functions */
143: caddr_t allocsys(caddr_t);
144: void parityenable(void);
145: int parityerror(struct frame *);
146: int parityerrorfind(void);
147: void identifycpu(void);
148: void initcpu(void);
149: void dumpmem(int *, int, int);
150: char *hexstr(int, int);
151:
152: /* functions called from locore.s */
153: void dumpsys(void);
154: void hp300_init(void);
155: void straytrap(int, u_short);
156: void nmihand(struct frame);
157:
158: /*
159: * Select code of console. Set to CONSCODE_INTERNAL if console is on
160: * "internal" framebuffer.
161: */
162: int conscode;
163: caddr_t conaddr; /* for drivers in cn_init() */
164: int convasize; /* size of mapped console device */
165:
166: /*
167: * Note that the value of delay_divisor is roughly
168: * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
169: * and 68030 systems. See clock.c for the delay
170: * calibration algorithm.
171: */
172: int cpuspeed; /* relative cpu speed */
173: int delay_divisor; /* delay constant */
174:
175: /*
176: * Early initialization, before main() is called.
177: */
178: void
179: hp300_init()
180: {
181: /*
182: * Tell the VM system about available physical memory. The
183: * hp300 only has one segment.
184: */
185: uvm_page_physload(atop(avail_start), atop(avail_end),
186: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
187:
188: /* Initialize the interrupt handlers. */
189: intr_init();
190:
191: /* Calibrate the delay loop. */
192: hp300_calibrate_delay();
193: }
194:
195: /*
196: * Console initialization: called early on from main,
197: * before vm init or startup. Do enough configuration
198: * to choose and initialize a console.
199: */
200: void
201: consinit()
202: {
203: extern struct extent *extio;
204: extern char *extiobase;
205:
206: /*
207: * Initialize some variables for sanity.
208: */
209: convasize = 0;
210: conscode = CONSCODE_INVALID;
211:
212: /*
213: * Initialize the bus resource map.
214: */
215: extio = extent_create("extio",
216: (u_long)extiobase, (u_long)extiobase + ctob(eiomapsize),
217: M_DEVBUF, extiospace, sizeof(extiospace), EX_NOWAIT);
218:
219: /*
220: * Initialize the console before we print anything out.
221: */
222: hp300_cninit();
223:
224: #ifdef DDB
225: ddb_init();
226: if (boothowto & RB_KDB)
227: Debugger();
228: #endif
229: }
230:
231: /*
232: * cpu_startup: allocate memory for variable-sized tables,
233: * initialize cpu, and do autoconfiguration.
234: */
235: void
236: cpu_startup()
237: {
238: extern char *etext;
239: unsigned i;
240: caddr_t v;
241: vaddr_t minaddr, maxaddr;
242: vsize_t size;
243: #ifdef DEBUG
244: extern int pmapdebug;
245: int opmapdebug = pmapdebug;
246:
247: pmapdebug = 0;
248: #endif
249:
250: /*
251: * Now that VM services are available, give another chance at
252: * console devices to initialize, if they could not before.
253: */
254: hp300_cninit();
255:
256: /*
257: * Initialize error message buffer (at end of core).
258: * avail_end was pre-decremented in pmap_bootstrap to compensate.
259: */
260: for (i = 0; i < btoc(MSGBUFSIZE); i++)
261: pmap_enter(pmap_kernel(), (vaddr_t)msgbufp + i * NBPG,
262: avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE,
263: VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
264: pmap_update(pmap_kernel());
265: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
266:
267: /*
268: * Good {morning,afternoon,evening,night}.
269: */
270: printf(version);
271: identifycpu();
272: printf("real mem = %u (%uMB)\n", ctob(physmem),
273: ctob(physmem)/1024/1024);
274:
275: /*
276: * Find out how much space we need, allocate it,
277: * and then give everything true virtual addresses.
278: */
279: size = (vsize_t)allocsys((caddr_t)0);
280: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0)
281: panic("startup: no room for tables");
282: if ((allocsys(v) - v) != size)
283: panic("startup: table size inconsistency");
284:
285: /*
286: * Determine how many buffers to allocate.
287: * We allocate bufcachepercent% of memory for buffer space.
288: */
289: if (bufpages == 0)
290: bufpages = physmem * bufcachepercent / 100;
291:
292: /* Restrict to at most 25% filled kvm */
293: if (bufpages >
294: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
295: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
296: PAGE_SIZE / 4;
297:
298: /*
299: * Allocate a submap for exec arguments. This map effectively
300: * limits the number of processes exec'ing at any time.
301: */
302: minaddr = vm_map_min(kernel_map);
303: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
304: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
305:
306: /*
307: * Allocate a submap for physio
308: */
309: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
310: VM_PHYS_SIZE, 0, FALSE, NULL);
311:
312: #ifdef DEBUG
313: pmapdebug = opmapdebug;
314: #endif
315: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
316: ptoa(uvmexp.free)/1024/1024);
317:
318: /*
319: * Tell the VM system that page 0 isn't mapped.
320: *
321: * XXX This is bogus; should just fix KERNBASE and
322: * XXX VM_MIN_KERNEL_ADDRESS, but not right now.
323: */
324: if (uvm_map_protect(kernel_map, 0, NBPG, UVM_PROT_NONE, TRUE))
325: panic("can't mark page 0 off-limits");
326:
327: /*
328: * Tell the VM system that writing to kernel text isn't allowed.
329: * If we don't, we might end up COW'ing the text segment!
330: *
331: * XXX Should be trunc_page(&kernel_text) instead
332: * XXX of NBPG.
333: */
334: if (uvm_map_protect(kernel_map, NBPG, round_page((vaddr_t)&etext),
335: UVM_PROT_READ|UVM_PROT_EXEC, TRUE))
336: panic("can't protect kernel text");
337:
338: /*
339: * Set up CPU-specific registers, cache, etc.
340: */
341: initcpu();
342:
343: /*
344: * Set up buffers, so they can be used to read disk labels.
345: */
346: bufinit();
347:
348: /*
349: * Configure the system.
350: */
351: if (boothowto & RB_CONFIG) {
352: #ifdef BOOT_CONFIG
353: user_config();
354: #else
355: printf("kernel does not support -c; continuing..\n");
356: #endif
357: }
358: }
359:
360: /*
361: * Allocate space for system data structures. We are given
362: * a starting virtual address and we return a final virtual
363: * address; along the way we set each data structure pointer.
364: *
365: * We call allocsys() with 0 to find out how much space we want,
366: * allocate that much and fill it with zeroes, and then call
367: * allocsys() again with the correct base virtual address.
368: */
369: caddr_t
370: allocsys(v)
371: caddr_t v;
372: {
373:
374: #define valloc(name, type, num) \
375: (name) = (type *)v; v = (caddr_t)((name)+(num))
376: #define valloclim(name, type, num, lim) \
377: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
378:
379: #ifdef SYSVMSG
380: valloc(msgpool, char, msginfo.msgmax);
381: valloc(msgmaps, struct msgmap, msginfo.msgseg);
382: valloc(msghdrs, struct msg, msginfo.msgtql);
383: valloc(msqids, struct msqid_ds, msginfo.msgmni);
384: #endif
385:
386: return (v);
387: }
388:
389: /*
390: * Info for CTL_HW
391: */
392: char cpu_model[120];
393:
394: /*
395: * Text description of models we support, indexed by machineid.
396: */
397: const char *hp300_models[] = {
398: "320", /* HP_320 */
399: "318/319/330", /* HP_330 */
400: "350", /* HP_350 */
401: "360", /* HP_360 */
402: "370", /* HP_370 */
403: "340", /* HP_340 */
404: "345", /* HP_345 */
405: "375", /* HP_375 */
406: "400", /* HP_400 */
407: "380", /* HP_380 */
408: "425", /* HP_425 */
409: "433", /* HP_433 */
410: "385", /* HP_385 */
411: "362", /* HP_362 */
412: "382", /* HP_382 */
413: };
414:
415: /* Map mmuid to single letter designation in 4xx models (e.g. 425s, 425t) */
416: char hp300_designations[] = " ttss e";
417:
418: void
419: identifycpu()
420: {
421: const char *t;
422: char mc, *td;
423: int len;
424: #ifdef FPSP
425: extern u_long fpvect_tab, fpvect_end, fpsp_tab;
426: #endif
427:
428: /*
429: * Map machineid to model name.
430: */
431: if (machineid >= sizeof(hp300_models) / sizeof(char *)) {
432: printf("\nunknown machineid %d\n", machineid);
433: goto lose;
434: }
435: t = hp300_models[machineid];
436:
437: /*
438: * Look up special designation (425s, 425t, etc) by mmuid.
439: */
440: if (mmuid < strlen(hp300_designations) &&
441: hp300_designations[mmuid] != ' ') {
442: td = &hp300_designations[mmuid];
443: td[1] = '\0';
444: } else
445: td = "";
446:
447: /*
448: * ...and the CPU type
449: */
450: switch (cputype) {
451: case CPU_68040:
452: mc = '4';
453: /* adjust cpuspeed by 3/8 on '040 boxes */
454: cpuspeed *= 3;
455: cpuspeed /= 8;
456: break;
457: case CPU_68030:
458: mc = '3';
459: break;
460: case CPU_68020:
461: mc = '2';
462: break;
463: default:
464: printf("\nunknown cputype %d\n", cputype);
465: goto lose;
466: }
467: snprintf(cpu_model, sizeof cpu_model,
468: "HP 9000/%s%s (%dMHz MC680%c0 CPU", t, td, cpuspeed, mc);
469:
470: /*
471: * ...and the MMU type.
472: */
473: switch (mmutype) {
474: case MMU_68040:
475: case MMU_68030:
476: strlcat(cpu_model, "+MMU", sizeof cpu_model);
477: break;
478: case MMU_68851:
479: strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
480: break;
481: case MMU_HP:
482: strlcat(cpu_model, ", HP MMU", sizeof cpu_model);
483: break;
484: default:
485: printf("%s\nunknown MMU type %d\n", cpu_model, mmutype);
486: panic("startup");
487: }
488:
489: /*
490: * ...and the FPU type.
491: */
492: switch (fputype) {
493: case FPU_68040:
494: strlcat(cpu_model, "+FPU", sizeof cpu_model);
495: break;
496: case FPU_68882:
497: len = strlen(cpu_model);
498: snprintf(cpu_model + len, sizeof cpu_model - len,
499: ", %dMHz MC68882 FPU", cpuspeed);
500: break;
501: case FPU_68881:
502: len = strlen(cpu_model);
503: snprintf(cpu_model + len, sizeof cpu_model - len,
504: ", %dMHz MC68881 FPU", machineid == HP_350 ? 20 : 16);
505: break;
506: default:
507: strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
508: }
509:
510: /*
511: * ...and finally, the cache type.
512: */
513: if (cputype == CPU_68040)
514: strlcat(cpu_model, ", 4k on-chip physical I/D caches",
515: sizeof cpu_model);
516: else {
517: len = strlen(cpu_model);
518: switch (ectype) {
519: case EC_VIRT:
520: snprintf(cpu_model + len, sizeof cpu_model - len,
521: ", %dK virtual-address cache",
522: machineid == HP_320 ? 16 : 32);
523: break;
524: case EC_PHYS:
525: snprintf(cpu_model + len, sizeof cpu_model - len,
526: ", %dK physical-address cache",
527: machineid == HP_370 ? 64 : 32);
528: break;
529: }
530: }
531:
532: printf("%s)\n", cpu_model);
533: #ifdef DEBUG
534: printf("cpu: delay divisor %d", delay_divisor);
535: if (mmuid)
536: printf(", mmuid %d", mmuid);
537: printf("\n");
538: #endif
539:
540: /*
541: * Now that we have told the user what they have,
542: * let them know if that machine type isn't configured.
543: */
544: switch (machineid) {
545: case -1: /* keep compilers happy */
546: #if !defined(HP320)
547: case HP_320:
548: #endif
549: #if !defined(HP330)
550: case HP_330:
551: #endif
552: #if !defined(HP340)
553: case HP_340:
554: #endif
555: #if !defined(HP345)
556: case HP_345:
557: #endif
558: #if !defined(HP350)
559: case HP_350:
560: #endif
561: #if !defined(HP360)
562: case HP_360:
563: #endif
564: #if !defined(HP362)
565: case HP_362:
566: #endif
567: #if !defined(HP370)
568: case HP_370:
569: #endif
570: #if !defined(HP375)
571: case HP_375:
572: #endif
573: #if !defined(HP380)
574: case HP_380:
575: #endif
576: #if !defined(HP382)
577: case HP_382:
578: #endif
579: #if !defined(HP385)
580: case HP_385:
581: #endif
582: #if !defined(HP400)
583: case HP_400:
584: #endif
585: #if !defined(HP425)
586: case HP_425:
587: #endif
588: #if !defined(HP433)
589: case HP_433:
590: #endif
591: panic("SPU type not configured for machineid %d", machineid);
592: default:
593: break;
594: }
595:
596: #ifdef FPSP
597: if (cputype == CPU_68040) {
598: bcopy(&fpsp_tab, &fpvect_tab,
599: (&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
600: }
601: #endif
602:
603: return;
604: lose:
605: panic("startup");
606: }
607:
608: /*
609: * machine dependent system variables.
610: */
611: int
612: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
613: int *name;
614: u_int namelen;
615: void *oldp;
616: size_t *oldlenp;
617: void *newp;
618: size_t newlen;
619: struct proc *p;
620: {
621: dev_t consdev;
622:
623: /* all sysctl names at this level are terminal */
624: if (namelen != 1)
625: return (ENOTDIR); /* overloaded */
626:
627: switch (name[0]) {
628: case CPU_CONSDEV:
629: if (cn_tab != NULL)
630: consdev = cn_tab->cn_dev;
631: else
632: consdev = NODEV;
633: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
634: sizeof consdev));
635: case CPU_CPUSPEED:
636: return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
637: case CPU_MACHINEID:
638: return (sysctl_rdint(oldp, oldlenp, newp, machineid));
639: case CPU_MMUID:
640: return (sysctl_rdint(oldp, oldlenp, newp, mmuid));
641: default:
642: return (EOPNOTSUPP);
643: }
644: /* NOTREACHED */
645: }
646:
647: int waittime = -1;
648:
649: void
650: boot(howto)
651: int howto;
652: {
653: /* take a snap shot before clobbering any registers */
654: if (curproc && curproc->p_addr)
655: savectx(&curproc->p_addr->u_pcb);
656:
657: /* If system is cold, just halt. */
658: if (cold) {
659: /* (Unless the user explicitly asked for reboot.) */
660: if ((howto & RB_USERREQ) == 0)
661: howto |= RB_HALT;
662: goto haltsys;
663: }
664:
665: boothowto = howto;
666: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
667: waittime = 0;
668: vfs_shutdown();
669: /*
670: * If we've been adjusting the clock, the todr
671: * will be out of synch; adjust it now unless
672: * the system was sitting in ddb.
673: */
674: if ((howto & RB_TIMEBAD) == 0) {
675: resettodr();
676: } else {
677: printf("WARNING: not updating battery clock\n");
678: }
679: }
680:
681: /* Disable interrupts. */
682: splhigh();
683:
684: /* If rebooting and a dump is requested do it. */
685: if (howto & RB_DUMP)
686: dumpsys();
687:
688: haltsys:
689: /* Run any shutdown hooks. */
690: doshutdownhooks();
691:
692: /* Finally, halt/reboot the system. */
693: if (howto & RB_HALT) {
694: printf("System halted. Hit any key to reboot.\n\n");
695: while (cngetc() == 0);
696: }
697:
698: printf("rebooting...\n");
699: DELAY(1000000);
700: doboot();
701: /*NOTREACHED*/
702: }
703:
704: /*
705: * These variables are needed by /sbin/savecore
706: */
707: u_long dumpmag = 0x8fca0101; /* magic number */
708: int dumpsize = 0; /* pages */
709: long dumplo = 0; /* blocks */
710: cpu_kcore_hdr_t cpu_kcore_hdr;
711:
712: /*
713: * This is called by configure to set dumplo and dumpsize.
714: * Dumps always skip the first PAGE_SIZE of disk space
715: * in case there might be a disk label stored there.
716: * If there is extra space, put dump at the end to
717: * reduce the chance that swapping trashes it.
718: */
719: void
720: dumpconf(void)
721: {
722: int nblks; /* size of dump area */
723:
724: if (dumpdev == NODEV ||
725: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
726: return;
727: if (nblks <= ctod(1))
728: return;
729:
730: /*
731: * XXX include the final RAM page which is not included in physmem.
732: */
733: dumpsize = physmem;
734:
735: /* hp300 only uses a single segment. */
736: cpu_kcore_hdr.ram_segs[0].start = lowram;
737: cpu_kcore_hdr.ram_segs[0].size = ctob(dumpsize);
738: cpu_kcore_hdr.mmutype = mmutype;
739: cpu_kcore_hdr.kernel_pa = lowram;
740: cpu_kcore_hdr.sysseg_pa = pmap_kernel()->pm_stpa;
741:
742: /* Always skip the first block, in case there is a label there. */
743: if (dumplo < ctod(1))
744: dumplo = ctod(1);
745:
746: /* Put dump at end of partition, and make it fit. */
747: if (dumpsize > dtoc(nblks - dumplo))
748: dumpsize = dtoc(nblks - dumplo);
749: if (dumplo < nblks - ctod(dumpsize))
750: dumplo = nblks - ctod(dumpsize);
751: }
752:
753: /*
754: * Dump physical memory onto the dump device. Called by doadump()
755: * in locore.s or by boot() here in machdep.c
756: */
757: void
758: dumpsys()
759: {
760: daddr64_t blkno; /* current block to write */
761: /* dump routine */
762: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
763: int pg; /* page being dumped */
764: paddr_t maddr; /* PA being dumped */
765: int error; /* error code from (*dump)() */
766: kcore_seg_t *kseg_p;
767: cpu_kcore_hdr_t *chdr_p;
768: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
769: extern int msgbufmapped;
770:
771: /* XXX initialized here because of gcc lossage */
772: maddr = lowram;
773: pg = 0;
774:
775: /* Don't put dump messages in msgbuf. */
776: msgbufmapped = 0;
777:
778: /* Make sure dump device is valid. */
779: if (dumpdev == NODEV)
780: return;
781: if (dumpsize == 0) {
782: dumpconf();
783: if (dumpsize == 0)
784: return;
785: }
786: if (dumplo <= 0) {
787: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
788: minor(dumpdev));
789: return;
790: }
791: dump = bdevsw[major(dumpdev)].d_dump;
792: blkno = dumplo;
793:
794: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
795: minor(dumpdev), dumplo);
796:
797: kseg_p = (kcore_seg_t *)dump_hdr;
798: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
799: bzero(dump_hdr, sizeof(dump_hdr));
800:
801: /*
802: * Generate a segment header
803: */
804: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
805: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
806:
807: /*
808: * Add the md header
809: */
810:
811: *chdr_p = cpu_kcore_hdr;
812:
813: printf("dump ");
814: maddr = cpu_kcore_hdr.ram_segs[0].start;
815: /* Dump the header. */
816: error = (*dump) (dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
817: switch (error) {
818: case 0:
819: break;
820:
821: case ENXIO:
822: printf("device bad\n");
823: return;
824:
825: case EFAULT:
826: printf("device not ready\n");
827: return;
828:
829: case EINVAL:
830: printf("area improper\n");
831: return;
832:
833: case EIO:
834: printf("i/o error\n");
835: return;
836:
837: case EINTR:
838: printf("aborted from console\n");
839: return;
840:
841: default:
842: printf("error %d\n", error);
843: return;
844: }
845: for (pg = 0; pg < dumpsize; pg++) {
846: #define NPGMB (1024*1024/NBPG)
847: /* print out how many MBs we have dumped */
848: if (pg && (pg % NPGMB) == 0)
849: printf("%d ", pg / NPGMB);
850: #undef NPGMB
851: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
852: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
853:
854: pmap_update(pmap_kernel());
855: error = (*dump)(dumpdev, blkno, vmmap, NBPG);
856: switch (error) {
857: case 0:
858: maddr += NBPG;
859: blkno += btodb(NBPG);
860: break;
861:
862: case ENXIO:
863: printf("device bad\n");
864: return;
865:
866: case EFAULT:
867: printf("device not ready\n");
868: return;
869:
870: case EINVAL:
871: printf("area improper\n");
872: return;
873:
874: case EIO:
875: printf("i/o error\n");
876: return;
877:
878: case EINTR:
879: printf("aborted from console\n");
880: return;
881:
882: default:
883: printf("error %d\n", error);
884: return;
885: }
886: }
887: printf("succeeded\n");
888: }
889:
890: void
891: initcpu()
892: {
893:
894: parityenable();
895: #ifdef USELEDS
896: ledinit();
897: #endif
898: }
899:
900: void
901: straytrap(pc, evec)
902: int pc;
903: u_short evec;
904: {
905: printf("unexpected trap (vector offset %x) from %x\n",
906: evec & 0xFFF, pc);
907: }
908:
909: /* XXX should change the interface, and make one badaddr() function */
910:
911: int *nofault;
912:
913: int
914: badaddr(addr)
915: caddr_t addr;
916: {
917: int i;
918: label_t faultbuf;
919:
920: nofault = (int *) &faultbuf;
921: if (setjmp((label_t *)nofault)) {
922: nofault = (int *) 0;
923: return(1);
924: }
925: i = *(volatile short *)addr;
926: nofault = (int *) 0;
927: return(0);
928: }
929:
930: int
931: badbaddr(addr)
932: caddr_t addr;
933: {
934: int i;
935: label_t faultbuf;
936:
937: nofault = (int *) &faultbuf;
938: if (setjmp((label_t *)nofault)) {
939: nofault = (int *) 0;
940: return(1);
941: }
942: i = *(volatile char *)addr;
943: nofault = (int *) 0;
944: return(0);
945: }
946:
947: static int innmihand; /* simple mutex */
948:
949: /*
950: * Level 7 interrupts can be caused by HIL keyboards (in cooked mode only,
951: * but we run them in raw mode) or parity errors.
952: */
953: void
954: nmihand(frame)
955: struct frame frame;
956: {
957:
958: /* Prevent unwanted recursion. */
959: if (innmihand)
960: return;
961: innmihand = 1;
962:
963: if (parityerror(&frame)) {
964: innmihand = 0;
965: return;
966: }
967:
968: /* panic?? */
969: printf("unexpected level 7 interrupt ignored\n");
970:
971: innmihand = 0;
972: }
973:
974: /*
975: * Parity error section. Contains magic.
976: */
977: #define PARREG ((volatile short *)IIOV(0x5B0000))
978: static int gotparmem = 0;
979: #ifdef DEBUG
980: int ignorekperr = 0; /* ignore kernel parity errors */
981: #endif
982:
983: /*
984: * Enable parity detection
985: */
986: void
987: parityenable()
988: {
989: label_t faultbuf;
990:
991: nofault = (int *) &faultbuf;
992: if (setjmp((label_t *)nofault)) {
993: nofault = (int *) 0;
994: printf("No parity memory\n");
995: return;
996: }
997: *PARREG = 1;
998: nofault = (int *) 0;
999: gotparmem = 1;
1000: printf("Parity detection enabled\n");
1001: }
1002:
1003: /*
1004: * Determine if level 7 interrupt was caused by a parity error
1005: * and deal with it if it was. Returns 1 if it was a parity error.
1006: */
1007: int
1008: parityerror(fp)
1009: struct frame *fp;
1010: {
1011: if (!gotparmem)
1012: return(0);
1013: *PARREG = 0;
1014: DELAY(10);
1015: *PARREG = 1;
1016: if (panicstr) {
1017: printf("parity error after panic ignored\n");
1018: return (1);
1019: }
1020: if (!parityerrorfind())
1021: printf("WARNING: transient parity error ignored\n");
1022: else if (USERMODE(fp->f_sr)) {
1023: log(LOG_ERR, "pid %d was killed: memory parity error\n",
1024: curproc->p_pid);
1025: uprintf("sorry, pid %d killed: memory parity error\n",
1026: curproc->p_pid);
1027: psignal(curproc, SIGKILL);
1028: #ifdef DEBUG
1029: } else if (ignorekperr) {
1030: printf("WARNING: kernel parity error ignored\n");
1031: #endif
1032: } else {
1033: regdump(&(fp->F_t), 128);
1034: panic("kernel parity error");
1035: }
1036: return (1);
1037: }
1038:
1039: /*
1040: * Yuck! There has got to be a better way to do this!
1041: * Searching all of memory with interrupts blocked can lead to disaster.
1042: */
1043: int
1044: parityerrorfind()
1045: {
1046: static label_t parcatch;
1047: static int looking = 0;
1048: volatile int pg, o, s;
1049: volatile int *ip;
1050: int i;
1051: int found;
1052:
1053: #ifdef lint
1054: i = o = pg = 0; if (i) return(0);
1055: #endif
1056: /*
1057: * If looking is true we are searching for a known parity error
1058: * and it has just occurred. All we do is return to the higher
1059: * level invocation.
1060: */
1061: if (looking)
1062: longjmp(&parcatch);
1063: s = splhigh();
1064: /*
1065: * If setjmp returns true, the parity error we were searching
1066: * for has just occurred (longjmp above) at the current pg+o
1067: */
1068: if (setjmp(&parcatch)) {
1069: printf("Parity error at 0x%x\n", ctob(pg)|o);
1070: found = 1;
1071: goto done;
1072: }
1073: /*
1074: * If we get here, a parity error has occurred for the first time
1075: * and we need to find it. We turn off any external caches and
1076: * loop thru memory, testing every longword til a fault occurs and
1077: * we regain control at setjmp above. Note that because of the
1078: * setjmp, pg and o need to be volatile or their values will be lost.
1079: */
1080: looking = 1;
1081: ecacheoff();
1082: for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) {
1083: pmap_kenter_pa((vaddr_t)vmmap, ptoa(pg), VM_PROT_READ);
1084: pmap_update(pmap_kernel());
1085: ip = (int *)vmmap;
1086: for (o = 0; o < PAGE_SIZE; o += sizeof(int))
1087: i = *ip++;
1088: }
1089: /*
1090: * Getting here implies no fault was found. Should never happen.
1091: */
1092: printf("Couldn't locate parity error\n");
1093: found = 0;
1094: done:
1095: looking = 0;
1096: ecacheon(); /* pmap_kremove() may cause a cache flush */
1097: pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
1098: pmap_update(pmap_kernel());
1099: splx(s);
1100: return(found);
1101: }
1102:
1103: /*
1104: * cpu_exec_aout_makecmds():
1105: * cpu-dependent a.out format hook for execve().
1106: *
1107: * Determine of the given exec package refers to something which we
1108: * understand and, if so, set up the vmcmds for it.
1109: */
1110: int
1111: cpu_exec_aout_makecmds(p, epp)
1112: struct proc *p;
1113: struct exec_package *epp;
1114: {
1115: #if defined(COMPAT_44) || defined(COMPAT_SUNOS)
1116: u_long midmag, magic;
1117: u_short mid;
1118: int error;
1119: struct exec *execp = epp->ep_hdr;
1120: #ifdef COMPAT_SUNOS
1121: extern int sunos_exec_aout_makecmds(struct proc *, struct exec_package *);
1122: #endif
1123:
1124: midmag = ntohl(execp->a_midmag);
1125: mid = (midmag >> 16) & 0xffff;
1126: magic = midmag & 0xffff;
1127:
1128: midmag = mid << 16 | magic;
1129:
1130: switch (midmag) {
1131: #ifdef COMPAT_44
1132: case (MID_HP300 << 16) | ZMAGIC:
1133: error = exec_aout_prep_oldzmagic(p, epp);
1134: break;
1135: #endif
1136: default:
1137: #ifdef COMPAT_SUNOS
1138: /* Hand it over to the SunOS emulation package. */
1139: error = sunos_exec_aout_makecmds(p, epp);
1140: #else
1141: error = ENOEXEC;
1142: #endif
1143: }
1144:
1145: return error;
1146: #else /* !(defined(COMPAT_44) || defined(COMPAT_SUNOS)) */
1147: return ENOEXEC;
1148: #endif
1149: }
CVSweb