Annotation of sys/arch/hppa64/hppa64/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.7 2007/06/06 17:15:12 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Michael Shalayeff
5: * All rights reserved.
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/param.h>
21: #include <sys/systm.h>
22: #include <sys/signalvar.h>
23: #include <sys/kernel.h>
24: #include <sys/proc.h>
25: #include <sys/buf.h>
26: #include <sys/reboot.h>
27: #include <sys/device.h>
28: #include <sys/conf.h>
29: #include <sys/file.h>
30: #include <sys/timeout.h>
31: #include <sys/malloc.h>
32: #include <sys/mbuf.h>
33: #include <sys/msgbuf.h>
34: #include <sys/ioctl.h>
35: #include <sys/tty.h>
36: #include <sys/user.h>
37: #include <sys/exec.h>
38: #include <sys/sysctl.h>
39: #include <sys/core.h>
40: #include <sys/kcore.h>
41: #include <sys/extent.h>
42: #ifdef SYSVMSG
43: #include <sys/msg.h>
44: #endif
45:
46: #include <sys/mount.h>
47: #include <sys/syscallargs.h>
48:
49: #include <uvm/uvm.h>
50: #include <uvm/uvm_page.h>
51:
52: #include <dev/cons.h>
53: #include <dev/clock_subr.h>
54:
55: #include <machine/pdc.h>
56: #include <machine/iomod.h>
57: #include <machine/psl.h>
58: #include <machine/reg.h>
59: #include <machine/autoconf.h>
60: #include <machine/kcore.h>
61:
62: #ifdef COMPAT_HPUX
63: #include <compat/hpux/hpux.h>
64: #endif
65:
66: #ifdef DDB
67: #include <machine/db_machdep.h>
68: #include <ddb/db_access.h>
69: #include <ddb/db_sym.h>
70: #include <ddb/db_extern.h>
71: #endif
72:
73: #include <hppa/dev/cpudevs.h>
74:
75: /*
76: * Patchable buffer cache parameters
77: */
78: #ifndef BUFCACHEPERCENT
79: #define BUFCACHEPERCENT 10
80: #endif /* BUFCACHEPERCENT */
81:
82: #ifdef BUFPAGES
83: int bufpages = BUFPAGES;
84: #else
85: int bufpages = 0;
86: #endif
87: int bufcachepercent = BUFCACHEPERCENT;
88:
89: /*
90: * Different kinds of flags used throughout the kernel.
91: */
92: int cold = 1; /* unset when engine is up to go */
93: extern int msgbufmapped; /* set when safe to use msgbuf */
94:
95: /*
96: * cache configuration, for most machines is the same
97: * numbers, so it makes sense to do defines w/ numbers depending
98: * on configured cpu types in the kernel
99: */
100: int icache_stride, icache_line_mask;
101: int dcache_stride, dcache_line_mask;
102:
103: /*
104: * things to not kill
105: */
106: volatile u_int8_t *machine_ledaddr;
107: int machine_ledword, machine_leds;
108: struct cpu_info cpu0_info;
109:
110: /*
111: * CPU params (should be the same for all cpus in the system)
112: */
113: struct pdc_cache pdc_cache PDC_ALIGNMENT;
114: struct pdc_model pdc_model PDC_ALIGNMENT;
115:
116: /* w/ a little deviation should be the same for all installed cpus */
117: u_int cpu_ticksnum, cpu_ticksdenom;
118:
119: /* exported info */
120: char machine[] = MACHINE;
121: char cpu_model[128];
122: int cpu_hvers;
123: enum hppa_cpu_type cpu_type;
124: const char *cpu_typename;
125: u_int fpu_version;
126: #ifdef COMPAT_HPUX
127: int cpu_model_hpux; /* contains HPUX_SYSCONF_CPU* kind of value */
128: #endif
129:
130: dev_t bootdev;
131: int physmem, resvmem, resvphysmem, esym;
132: paddr_t avail_end;
133:
134: /*
135: * Things for MI glue to stick on.
136: */
137: struct user *proc0paddr;
138: long mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(32) / sizeof(long)];
139: struct extent *hppa_ex;
140:
141: struct vm_map *exec_map = NULL;
142: struct vm_map *phys_map = NULL;
143: /* Virtual page frame for /dev/mem (see mem.c) */
144: vaddr_t vmmap;
145:
146: void delay_init(void);
147: static __inline void fall(int, int, int, int, int);
148: void dumpsys(void);
149: void hpmc_dump(void);
150: void cpuid(void);
151:
152: /*
153: * wide used hardware params
154: */
155: struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT;
156: struct pdc_coproc pdc_coproc PDC_ALIGNMENT;
157: struct pdc_coherence pdc_coherence PDC_ALIGNMENT;
158: struct pdc_spidb pdc_spidbits PDC_ALIGNMENT;
159: struct pdc_model pdc_model PDC_ALIGNMENT;
160:
161: #ifdef DEBUG
162: int sigdebug = 0;
163: pid_t sigpid = 0;
164: #define SDB_FOLLOW 0x01
165: #endif
166:
167: int
168: hppa_cpuspeed(int *mhz)
169: {
170: *mhz = PAGE0->mem_10msec / 10000;
171:
172: return (0);
173: }
174:
175: void
176: hppa_init(start)
177: paddr_t start;
178: {
179: extern int kernel_text;
180: int error;
181:
182: mtctl((long)&cpu0_info, 24);
183:
184: pdc_init(); /* init PDC iface, so we can call em easy */
185:
186: delay_init(); /* calculate cpu clock ratio */
187:
188: cpuid();
189:
190: /* cache parameters */
191: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT,
192: &pdc_cache)) < 0) {
193: #ifdef DEBUG
194: printf("WARNING: PDC_CACHE error %d\n", error);
195: #endif
196: }
197:
198: dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1;
199: dcache_stride = pdc_cache.dc_stride;
200: icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1;
201: icache_stride = pdc_cache.ic_stride;
202:
203: /* cache coherence params (pbably available for 8k only) */
204: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS,
205: &pdc_coherence, 1, 1, 1, 1);
206: #ifdef DEBUG
207: printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n",
208: pdc_coherence.ia_cst, pdc_coherence.da_cst,
209: pdc_coherence.ita_cst, pdc_coherence.dta_cst, error);
210: #endif
211: error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB,
212: &pdc_spidbits, 0, 0, 0, 0);
213: printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error);
214:
215: #if 0
216: TODO hpmc/toc/pfr
217: /* setup hpmc handler */
218: {
219: extern u_int hpmc_v[]; /* from locore.s */
220: register u_int *p = hpmc_v;
221:
222: if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p))
223: *p = 0x08000240;
224:
225: p[6] = (u_int)&hpmc_dump;
226: p[7] = 32;
227: p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]);
228: }
229:
230: {
231: extern u_int hppa_toc[], hppa_toc_end[];
232: register u_int cksum, *p;
233:
234: for (cksum = 0, p = hppa_toc; p < hppa_toc_end; p++)
235: cksum += *p;
236:
237: *p = cksum;
238: PAGE0->ivec_toc = (u_int)&hppa_toc[0];
239: PAGE0->ivec_toclen = (hppa_toc_end - hppa_toc + 1) * 4;
240: }
241:
242: {
243: extern u_int hppa_pfr[], hppa_pfr_end[];
244: register u_int cksum, *p;
245:
246: for (cksum = 0, p = hppa_pfr; p < hppa_pfr_end; p++)
247: cksum += *p;
248:
249: *p = cksum;
250: PAGE0->ivec_mempf = (u_int)&hppa_pfr[0];
251: PAGE0->ivec_mempflen = (hppa_pfr_end - hppa_pfr + 1) * 4;
252: }
253: #endif
254: avail_end = trunc_page(PAGE0->imm_max_mem);
255: if (avail_end > 0x4000000)
256: avail_end = 0x4000000;
257: physmem = btoc(avail_end);
258: resvmem = btoc(((vaddr_t)&kernel_text));
259:
260: /* we hope this won't fail */
261: hppa_ex = extent_create("mem", 0, HPPA_PHYSMAP, M_DEVBUF,
262: (caddr_t)mem_ex_storage, sizeof(mem_ex_storage),
263: EX_NOCOALESCE|EX_NOWAIT);
264: if (extent_alloc_region(hppa_ex, 0, (vaddr_t)PAGE0->imm_max_mem,
265: EX_NOWAIT))
266: panic("cannot reserve main memory");
267:
268: #ifdef SYSVMSG
269: {
270: vaddr_t v;
271:
272: v = round_page(start);
273: #define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num))
274: valloc(msgpool, char, msginfo.msgmax);
275: valloc(msgmaps, struct msgmap, msginfo.msgseg);
276: valloc(msghdrs, struct msg, msginfo.msgtql);
277: valloc(msqids, struct msqid_ds, msginfo.msgmni);
278: #undef valloc
279: v = round_page(v);
280: bzero ((void *)start, (v - start));
281: start = v;
282: }
283: #endif
284: /* sets resvphysmem */
285: pmap_bootstrap(start);
286:
287: /* space has been reserved in pmap_bootstrap() */
288: msgbufp = (struct msgbuf *)((vaddr_t)ptoa(physmem) -
289: round_page(MSGBUFSIZE));
290: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
291: msgbufmapped = 1;
292:
293: /* they say PDC_COPROC might turn fault light on */
294: pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP,
295: PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0);
296:
297: cpu_cpuspeed = &hppa_cpuspeed;
298:
299: #ifdef DDB
300: ddb_init();
301: if (boothowto & RB_KDB)
302: Debugger();
303: #endif
304: ptlball();
305: ficacheall();
306: fdcacheall();
307: printf("out\n");
308: }
309:
310: void
311: cpuid()
312: {
313: extern u_int fpu_enable;
314: struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT;
315: int error;
316:
317: /* identify system type */
318: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO,
319: &pdc_model)) < 0) {
320: #ifdef DEBUG
321: printf("WARNING: PDC_MODEL error %d\n", error);
322: #endif
323: pdc_model.hvers = 0;
324: }
325:
326: bzero(&pdc_cpuid, sizeof(pdc_cpuid));
327: if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID,
328: &pdc_cpuid, 0, 0, 0, 0) >= 0) {
329:
330: /* patch for old 8200 */
331: if (pdc_cpuid.version == HPPA_CPU_PCXU &&
332: pdc_cpuid.revision > 0x0d)
333: pdc_cpuid.version = HPPA_CPU_PCXUP;
334:
335: cpu_type = pdc_cpuid.version;
336: }
337:
338: /* locate coprocessors and SFUs */
339: bzero(&pdc_coproc, sizeof(pdc_coproc));
340: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT,
341: &pdc_coproc, 0, 0, 0, 0)) < 0)
342: printf("WARNING: PDC_COPROC error %d\n", error);
343: else {
344: printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n",
345: pdc_coproc.ccr_enable, pdc_coproc.ccr_present,
346: pdc_coproc.fpu_model, pdc_coproc.fpu_revision);
347: fpu_enable = pdc_coproc.ccr_enable & 0xc0;
348:
349: /* a kludge to detect PCXW */
350: if (pdc_coproc.fpu_model == HPPA_FPU_PCXW)
351: cpu_type = HPPA_CPU_PCXW;
352: }
353:
354: if (!cpu_type)
355: printf("WARNING: UNKNOWN CPU TYPE; GOOD LUCK\n");
356: cpu_typename = hppa_mod_info(HPPA_TYPE_CPU, cpu_type);
357:
358: if (pdc_model.arch_rev != 8)
359: panic("CANNOT RUN 64BIT KERNEL on 32BIT CPU");
360:
361: {
362: const char *p;
363: char buf[32];
364:
365: cpu_hvers = pdc_model.hvers >> 4;
366: if (!cpu_hvers) {
367: p = "(UNKNOWN)";
368: } else {
369: p = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers);
370: if (!p) {
371: snprintf(buf, sizeof buf, "(UNKNOWN 0x%x)",
372: cpu_hvers);
373: p = buf;
374: }
375: }
376:
377: snprintf(cpu_model, sizeof cpu_model,
378: "HP 9000/%s PA-RISC 2.0", p);
379: }
380: #ifdef DEBUG
381: printf("%s\n", cpu_model);
382: #endif
383: }
384:
385: void
386: cpu_startup(void)
387: {
388: vaddr_t minaddr, maxaddr;
389:
390: /*
391: * psychodelic kingdom come
392: * ... run, run, run
393: * psychodelic kings and queens
394: * join me in this one love dream
395: */
396: printf("%s%s\n", version, cpu_model);
397: printf("real mem = %u (%u reserved for PROM, %u used by OpenBSD)\n",
398: ctob(physmem), ctob(resvmem), ctob(resvphysmem - resvmem));
399:
400: /*
401: * Determine how many buffers to allocate.
402: * We allocate bufcachepercent% of memory for buffer space.
403: */
404: if (bufpages == 0)
405: bufpages = physmem * bufcachepercent / 100;
406:
407: /* Restrict to at most 25% filled kvm */
408: if (bufpages >
409: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
410: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
411: PAGE_SIZE / 4;
412:
413: printf("here3\n");
414: /*
415: * Allocate a submap for exec arguments. This map effectively
416: * limits the number of processes exec'ing at any time.
417: */
418: minaddr = vm_map_min(kernel_map);
419: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
420: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
421:
422: printf("here4\n");
423: /*
424: * Allocate a submap for physio
425: */
426: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
427: VM_PHYS_SIZE, 0, FALSE, NULL);
428:
429: printf("here5\n");
430: printf("avail mem = %lu\n", ptoa(uvmexp.free));
431:
432: /*
433: * Set up buffers, so they can be used to read disk labels.
434: */
435: bufinit();
436: vmmap = uvm_km_valloc_wait(kernel_map, NBPG);
437:
438: printf("here6\n");
439: /*
440: * Configure the system.
441: */
442: if (boothowto & RB_CONFIG) {
443: #ifdef BOOT_CONFIG
444: user_config();
445: #else
446: printf("kernel does not support -c; continuing..\n");
447: #endif
448: }
449: printf("here7\n");
450: }
451:
452: /*
453: * initialize the system time from the time of day clock
454: */
455: void
456: inittodr(t)
457: time_t t;
458: {
459: struct pdc_tod tod PDC_ALIGNMENT;
460: int error, tbad = 0;
461:
462: if (t < 12*SECYR) {
463: printf ("WARNING: preposterous time in file system");
464: t = 6*SECYR + 186*SECDAY + SECDAY/2;
465: tbad = 1;
466: }
467:
468: if ((error = pdc_call((iodcio_t)pdc,
469: 1, PDC_TOD, PDC_TOD_READ, &tod, 0, 0, 0, 0, 0)))
470: printf("clock: failed to fetch (%d)\n", error);
471:
472: time.tv_sec = tod.sec;
473: time.tv_usec = tod.usec;
474:
475: if (!tbad) {
476: u_long dt;
477:
478: dt = (time.tv_sec < t)? t - time.tv_sec : time.tv_sec - t;
479:
480: if (dt < 2 * SECDAY)
481: return;
482: printf("WARNING: clock %s %ld days",
483: time.tv_sec < t? "lost" : "gained", dt / SECDAY);
484: }
485:
486: printf (" -- CHECK AND RESET THE DATE!\n");
487: }
488:
489: /*
490: * reset the time of day clock to the value in time
491: */
492: void
493: resettodr()
494: {
495: int error;
496:
497: if ((error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_WRITE,
498: time.tv_sec, time.tv_usec)))
499: printf("clock: failed to save (%d)\n", error);
500: }
501:
502: /*
503: * compute cpu clock ratio such as:
504: * cpu_ticksnum / cpu_ticksdenom = t + delta
505: * delta -> 0
506: */
507: void
508: delay_init(void)
509: {
510: u_long num, denom, delta, mdelta;
511:
512: mdelta = ULONG_MAX;
513: for (denom = 1; denom < 1000; denom++) {
514: num = (PAGE0->mem_10msec * denom) / 10000;
515: delta = num * 10000 / denom - PAGE0->mem_10msec;
516: if (!delta) {
517: cpu_ticksdenom = denom;
518: cpu_ticksnum = num;
519: break;
520: } else if (delta < mdelta) {
521: cpu_ticksdenom = denom;
522: cpu_ticksnum = num;
523: mdelta = delta;
524: }
525: }
526: printf("nom=%lu denom=%lu\n", cpu_ticksnum, cpu_ticksdenom);
527: }
528:
529: void
530: delay(us)
531: u_int us;
532: {
533: u_long start, end, n;
534:
535: start = mfctl(CR_ITMR);
536: while (us) {
537: n = min(1000, us);
538: end = start + n * cpu_ticksnum / cpu_ticksdenom;
539:
540: /* N.B. Interval Timer may wrap around */
541: if (end < start)
542: do
543: start = mfctl(CR_ITMR);
544: while (start > end);
545:
546: do
547: start = mfctl(CR_ITMR);
548: while (start < end);
549:
550: us -= n;
551: }
552: }
553:
554: static __inline void
555: fall(c_base, c_count, c_loop, c_stride, data)
556: int c_base, c_count, c_loop, c_stride, data;
557: {
558: int loop;
559:
560: for (; c_count--; c_base += c_stride)
561: for (loop = c_loop; loop--; )
562: if (data)
563: __asm __volatile("fdce 0(%%sr0,%0)"
564: :: "r" (c_base));
565: else
566: __asm __volatile("fice 0(%%sr0,%0)"
567: :: "r" (c_base));
568: }
569:
570: void
571: ficacheall(void)
572: {
573: /*
574: * Flush the instruction, then data cache.
575: */
576: fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop,
577: pdc_cache.ic_stride, 0);
578: sync_caches();
579: }
580:
581: void
582: fdcacheall(void)
583: {
584: fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop,
585: pdc_cache.dc_stride, 1);
586: sync_caches();
587: }
588:
589: void
590: ptlball(void)
591: {
592: register pa_space_t sp;
593: register int i, j, k;
594:
595: /* instruction TLB */
596: sp = pdc_cache.it_sp_base;
597: for (i = 0; i < pdc_cache.it_sp_count; i++) {
598: register vaddr_t off = pdc_cache.it_off_base;
599: for (j = 0; j < pdc_cache.it_off_count; j++) {
600: for (k = 0; k < pdc_cache.it_loop; k++)
601: pitlb(sp, off);
602: off += pdc_cache.it_off_stride;
603: }
604: sp += pdc_cache.it_sp_stride;
605: }
606:
607: /* data TLB */
608: sp = pdc_cache.dt_sp_base;
609: for (i = 0; i < pdc_cache.dt_sp_count; i++) {
610: register vaddr_t off = pdc_cache.dt_off_base;
611: for (j = 0; j < pdc_cache.dt_off_count; j++) {
612: for (k = 0; k < pdc_cache.dt_loop; k++)
613: pdtlb(sp, off);
614: off += pdc_cache.dt_off_stride;
615: }
616: sp += pdc_cache.dt_sp_stride;
617: }
618: }
619:
620: void
621: boot(howto)
622: int howto;
623: {
624: /* If system is cold, just halt. */
625: if (cold) {
626: /* (Unless the user explicitly asked for reboot.) */
627: if ((howto & RB_USERREQ) == 0)
628: howto |= RB_HALT;
629: } else {
630:
631: boothowto = howto | (boothowto & RB_HALT);
632:
633: if (!(howto & RB_NOSYNC)) {
634: vfs_shutdown();
635: /*
636: * If we've been adjusting the clock, the todr
637: * will be out of synch; adjust it now unless
638: * the system was sitting in ddb.
639: */
640: if ((howto & RB_TIMEBAD) == 0)
641: resettodr();
642: else
643: printf("WARNING: not updating battery clock\n");
644: }
645:
646: /* XXX probably save howto into stable storage */
647:
648: splhigh();
649:
650: if (howto & RB_DUMP)
651: dumpsys();
652:
653: doshutdownhooks();
654: }
655:
656: /* in case we came on powerfail interrupt */
657: if (cold_hook)
658: (*cold_hook)(HPPA_COLD_COLD);
659:
660: if (howto & RB_HALT) {
661: if (howto & RB_POWERDOWN && cold_hook) {
662: printf("Powering off...");
663: DELAY(2000000);
664: (*cold_hook)(HPPA_COLD_OFF);
665: DELAY(1000000);
666: }
667:
668: printf("System halted!\n");
669: DELAY(2000000);
670: __asm __volatile("stwas %0, 0(%1)"
671: :: "r" (CMD_STOP), "r" (HPPA_LBCAST + iomod_command));
672: } else {
673: printf("rebooting...");
674: DELAY(2000000);
675: __asm __volatile(".export hppa_reset, entry\n\t"
676: ".label hppa_reset");
677: __asm __volatile("stwas %0, 0(%1)"
678: :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command));
679: }
680:
681: for(;;); /* loop while bus reset is comming up */
682: /* NOTREACHED */
683: }
684:
685: u_long dumpmag = 0x8fca0101; /* magic number */
686: int dumpsize = 0; /* pages */
687: long dumplo = 0; /* blocks */
688:
689: /*
690: * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
691: */
692: int
693: cpu_dumpsize(void)
694: {
695: int size;
696:
697: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
698: if (roundup(size, dbtob(1)) != dbtob(1))
699: return -1;
700:
701: return 1;
702: }
703:
704: /*
705: * Called from HPMC handler in locore
706: */
707: void
708: hpmc_dump(void)
709: {
710: printf("HPMC\n");
711:
712: cold = 0;
713: boot(RB_NOSYNC);
714: }
715:
716: int
717: cpu_dump(void)
718: {
719: long buf[dbtob(1) / sizeof (long)];
720: kcore_seg_t *segp;
721: cpu_kcore_hdr_t *cpuhdrp;
722:
723: segp = (kcore_seg_t *)buf;
724: cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)];
725:
726: /*
727: * Generate a segment header.
728: */
729: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
730: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
731:
732: /*
733: * Add the machine-dependent header info
734: */
735: /* nothing for now */
736:
737: return (bdevsw[major(dumpdev)].d_dump)
738: (dumpdev, dumplo, (caddr_t)buf, dbtob(1));
739: }
740:
741: /*
742: * Dump the kernel's image to the swap partition.
743: */
744: #define BYTES_PER_DUMP NBPG
745:
746: void
747: dumpsys(void)
748: {
749: int psize, bytes, i, n;
750: caddr_t maddr;
751: daddr64_t blkno;
752: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
753: int error;
754:
755: /* Save registers
756: savectx(&dumppcb); */
757:
758: if (dumpsize == 0)
759: dumpconf();
760: if (dumplo <= 0) {
761: printf("\ndump to dev %x not possible\n", dumpdev);
762: return;
763: }
764: printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
765:
766: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
767: printf("dump ");
768: if (psize == -1) {
769: printf("area unavailable\n");
770: return;
771: }
772:
773: if (!(error = cpu_dump())) {
774:
775: bytes = ctob(physmem);
776: maddr = NULL;
777: blkno = dumplo + cpu_dumpsize();
778: dump = bdevsw[major(dumpdev)].d_dump;
779: for (i = 0; i < bytes; i += n) {
780:
781: /* Print out how many MBs we are to go. */
782: n = bytes - i;
783: if (n && (n % (1024*1024)) == 0)
784: printf("%d ", n / (1024 * 1024));
785:
786: /* Limit size for next transfer. */
787: if (n > BYTES_PER_DUMP)
788: n = BYTES_PER_DUMP;
789:
790: if ((error = (*dump)(dumpdev, blkno, maddr, n)))
791: break;
792: maddr += n;
793: blkno += btodb(n);
794: }
795: }
796:
797: switch (error) {
798: case ENXIO: printf("device bad\n"); break;
799: case EFAULT: printf("device not ready\n"); break;
800: case EINVAL: printf("area improper\n"); break;
801: case EIO: printf("i/o error\n"); break;
802: case EINTR: printf("aborted from console\n"); break;
803: case 0: printf("succeeded\n"); break;
804: default: printf("error %d\n", error); break;
805: }
806: }
807:
808: /* bcopy(), error on fault */
809: int
810: kcopy(from, to, size)
811: const void *from;
812: void *to;
813: size_t size;
814: {
815: return spcopy(HPPA_SID_KERNEL, from, HPPA_SID_KERNEL, to, size);
816: }
817:
818: int
819: copystr(src, dst, size, lenp)
820: const void *src;
821: void *dst;
822: size_t size;
823: size_t *lenp;
824: {
825: return spstrcpy(HPPA_SID_KERNEL, src, HPPA_SID_KERNEL, dst, size, lenp);
826: }
827:
828: int
829: copyinstr(src, dst, size, lenp)
830: const void *src;
831: void *dst;
832: size_t size;
833: size_t *lenp;
834: {
835: return spstrcpy(curproc->p_addr->u_pcb.pcb_space, src,
836: HPPA_SID_KERNEL, dst, size, lenp);
837: }
838:
839:
840: int
841: copyoutstr(src, dst, size, lenp)
842: const void *src;
843: void *dst;
844: size_t size;
845: size_t *lenp;
846: {
847: return spstrcpy(HPPA_SID_KERNEL, src,
848: curproc->p_addr->u_pcb.pcb_space, dst, size, lenp);
849: }
850:
851:
852: int
853: copyin(src, dst, size)
854: const void *src;
855: void *dst;
856: size_t size;
857: {
858: return spcopy(curproc->p_addr->u_pcb.pcb_space, src,
859: HPPA_SID_KERNEL, dst, size);
860: }
861:
862: int
863: copyout(src, dst, size)
864: const void *src;
865: void *dst;
866: size_t size;
867: {
868: return spcopy(HPPA_SID_KERNEL, src,
869: curproc->p_addr->u_pcb.pcb_space, dst, size);
870: }
871:
872: /*
873: * Set registers on exec.
874: */
875: void
876: setregs(p, pack, stack, retval)
877: struct proc *p;
878: struct exec_package *pack;
879: u_long stack;
880: register_t *retval;
881: {
882: extern paddr_t fpu_curpcb; /* from locore.S */
883: struct trapframe *tf = p->p_md.md_regs;
884: struct pcb *pcb = &p->p_addr->u_pcb;
885: register_t zero;
886:
887: tf->tf_flags = TFF_SYS|TFF_LAST;
888: tf->tf_iioq[1] = 4 +
889: (tf->tf_iioq[0] = pack->ep_entry | HPPA_PC_PRIV_USER);
890: tf->tf_rp = 0;
891: tf->tf_args[0] = (u_long)PS_STRINGS;
892: tf->tf_args[1] = tf->tf_args[2] = 0; /* XXX dynload stuff */
893:
894: /* setup terminal stack frame */
895: stack = (stack + 0x1f) & ~0x1f;
896: tf->tf_r3 = stack;
897: tf->tf_sp = stack += HPPA_FRAME_SIZE;
898: tf->tf_ret1 = stack - 16; /* ap */
899: zero = 0;
900: copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t));
901: copyout(&zero, (caddr_t)(stack + HPPA_FRAME_RP), sizeof(register_t));
902:
903: /* reset any of the pending FPU exceptions */
904: if (tf->tf_cr30 == fpu_curpcb) {
905: fpu_exit();
906: fpu_curpcb = 0;
907: }
908: pcb->pcb_fpregs[0] = ((u_int64_t)HPPA_FPU_INIT) << 32;
909: pcb->pcb_fpregs[1] = 0;
910: pcb->pcb_fpregs[2] = 0;
911: pcb->pcb_fpregs[3] = 0;
912: fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4);
913:
914: retval[1] = 0;
915: }
916:
917: /*
918: * Send an interrupt to process.
919: */
920: void
921: sendsig(catcher, sig, mask, code, type, val)
922: sig_t catcher;
923: int sig, mask;
924: u_long code;
925: int type;
926: union sigval val;
927: {
928: extern paddr_t fpu_curpcb; /* from locore.S */
929: extern u_int fpu_enable;
930: struct proc *p = curproc;
931: struct trapframe *tf = p->p_md.md_regs;
932: struct sigacts *psp = p->p_sigacts;
933: struct sigcontext ksc;
934: siginfo_t ksi;
935: register_t scp, sip, zero;
936: int sss;
937:
938: /* TODO sendsig */
939:
940: #ifdef DEBUG
941: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
942: printf("sendsig: %s[%d] sig %d catcher %p\n",
943: p->p_comm, p->p_pid, sig, catcher);
944: #endif
945:
946: /* flush the FPU ctx first */
947: if (tf->tf_cr30 == fpu_curpcb) {
948: mtctl(fpu_enable, CR_CCR);
949: fpu_save(fpu_curpcb);
950: /* fpu_curpcb = 0; only needed if fpregs are preset */
951: mtctl(0, CR_CCR);
952: }
953:
954: ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
955:
956: /*
957: * Allocate space for the signal handler context.
958: */
959: if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
960: (psp->ps_sigonstack & sigmask(sig))) {
961: scp = (register_t)psp->ps_sigstk.ss_sp;
962: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
963: } else
964: scp = (tf->tf_sp + 63) & ~63;
965:
966: sss = (sizeof(ksc) + 63) & ~63;
967: sip = 0;
968: if (psp->ps_siginfo & sigmask(sig)) {
969: sip = scp + sizeof(ksc);
970: sss += (sizeof(ksi) + 63) & ~63;
971: }
972:
973: #ifdef DEBUG
974: if ((tf->tf_iioq[0] & ~PAGE_MASK) == SYSCALLGATE)
975: printf("sendsig: interrupted syscall at 0x%x:0x%x, flags %b\n",
976: tf->tf_iioq[0], tf->tf_iioq[1], tf->tf_ipsw, PSL_BITS);
977: #endif
978:
979: ksc.sc_mask = mask;
980: ksc.sc_fp = scp + sss;
981: ksc.sc_ps = tf->tf_ipsw;
982: ksc.sc_pcoqh = tf->tf_iioq[0];
983: ksc.sc_pcoqt = tf->tf_iioq[1];
984: bcopy(tf, &ksc.sc_regs[0], 32*8);
985: ksc.sc_regs[0] = tf->tf_sar;
986: bcopy(p->p_addr->u_pcb.pcb_fpregs, ksc.sc_fpregs,
987: sizeof(ksc.sc_fpregs));
988:
989: sss += HPPA_FRAME_SIZE;
990: tf->tf_args[0] = sig;
991: tf->tf_args[1] = sip;
992: tf->tf_args[2] = tf->tf_r4 = scp;
993: tf->tf_args[3] = (register_t)catcher;
994: tf->tf_sp = scp + sss;
995: tf->tf_ipsw &= ~(PSL_N|PSL_B);
996: tf->tf_iioq[0] = HPPA_PC_PRIV_USER | p->p_sigcode;
997: tf->tf_iioq[1] = tf->tf_iioq[0] + 4;
998: /* disable tracing in the trapframe */
999:
1000: #ifdef DEBUG
1001: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
1002: printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n",
1003: p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss);
1004: #endif
1005:
1006: if (copyout(&ksc, (void *)scp, sizeof(ksc)))
1007: sigexit(p, SIGILL);
1008:
1009: if (sip) {
1010: initsiginfo(&ksi, sig, code, type, val);
1011: if (copyout(&ksi, (void *)sip, sizeof(ksi)))
1012: sigexit(p, SIGILL);
1013: }
1014:
1015: zero = 0;
1016: if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE,
1017: sizeof(register_t)))
1018: sigexit(p, SIGILL);
1019:
1020: #ifdef DEBUG
1021: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
1022: printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
1023: tf->tf_iioq[0], tf->tf_args[3]);
1024: #endif
1025: }
1026:
1027: int
1028: sys_sigreturn(p, v, retval)
1029: struct proc *p;
1030: void *v;
1031: register_t *retval;
1032: {
1033: extern paddr_t fpu_curpcb; /* from locore.S */
1034: struct sys_sigreturn_args /* {
1035: syscallarg(struct sigcontext *) sigcntxp;
1036: } */ *uap = v;
1037: struct sigcontext *scp, ksc;
1038: struct trapframe *tf = p->p_md.md_regs;
1039: int error;
1040:
1041: /* TODO sigreturn */
1042:
1043: scp = SCARG(uap, sigcntxp);
1044: #ifdef DEBUG
1045: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
1046: printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
1047: #endif
1048:
1049: /* flush the FPU ctx first */
1050: if (tf->tf_cr30 == fpu_curpcb) {
1051: fpu_exit();
1052: fpu_curpcb = 0;
1053: }
1054:
1055: if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)))
1056: return (error);
1057:
1058: #define PSL_MBS (PSL_C|PSL_Q|PSL_P|PSL_D|PSL_I)
1059: #define PSL_MBZ (PSL_Y|PSL_Z|PSL_S|PSL_X|PSL_M|PSL_R)
1060: if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS)
1061: return (EINVAL);
1062:
1063: if (ksc.sc_onstack)
1064: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
1065: else
1066: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1067: p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1068:
1069: tf->tf_sar = ksc.sc_regs[0];
1070: ksc.sc_regs[0] = tf->tf_flags;
1071: bcopy(&ksc.sc_regs[0], tf, 32*8);
1072: bcopy(ksc.sc_fpregs, p->p_addr->u_pcb.pcb_fpregs,
1073: sizeof(ksc.sc_fpregs));
1074: fdcache(HPPA_SID_KERNEL, (vaddr_t)p->p_addr->u_pcb.pcb_fpregs,
1075: sizeof(ksc.sc_fpregs));
1076:
1077: tf->tf_iioq[0] = ksc.sc_pcoqh;
1078: tf->tf_iioq[1] = ksc.sc_pcoqt;
1079: tf->tf_ipsw = ksc.sc_ps;
1080:
1081: #ifdef DEBUG
1082: if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
1083: printf("sigreturn(%d): returns\n", p->p_pid);
1084: #endif
1085: return (EJUSTRETURN);
1086: }
1087:
1088: /*
1089: * machine dependent system variables.
1090: */
1091: int
1092: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1093: int *name;
1094: u_int namelen;
1095: void *oldp;
1096: size_t *oldlenp;
1097: void *newp;
1098: size_t newlen;
1099: struct proc *p;
1100: {
1101: dev_t consdev;
1102:
1103: /* all sysctl names at this level are terminal */
1104: if (namelen != 1)
1105: return (ENOTDIR); /* overloaded */
1106: switch (name[0]) {
1107: case CPU_CONSDEV:
1108: if (cn_tab != NULL)
1109: consdev = cn_tab->cn_dev;
1110: else
1111: consdev = NODEV;
1112: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1113: sizeof consdev));
1114: default:
1115: return (EOPNOTSUPP);
1116: }
1117: /* NOTREACHED */
1118: }
1119:
1120:
1121: /*
1122: * consinit:
1123: * initialize the system console.
1124: */
1125: void
1126: consinit(void)
1127: {
1128: static int initted;
1129:
1130: if (!initted) {
1131: initted++;
1132: cninit();
1133: }
1134: }
1135:
1136: #ifdef DIAGNOSTIC
1137: void
1138: splassert_check(int wantipl, const char *func)
1139: {
1140: extern int cpl; /* from locoore.s */
1141:
1142: if (cpl < wantipl) {
1143: splassert_fail(wantipl, cpl, func);
1144: }
1145: }
1146: #endif
CVSweb