machdep.c revision 1.22 1 /* $NetBSD: machdep.c,v 1.22 1998/07/05 00:51:12 jonathan Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "opt_ddb.h"
35 #include "opt_inet.h"
36 #include "opt_uvm.h"
37 #include "ipkdb.h"
38
39 #include <sys/param.h>
40 #include <sys/buf.h>
41 #include <sys/callout.h>
42 #include <sys/exec.h>
43 #include <sys/malloc.h>
44 #include <sys/map.h>
45 #include <sys/mbuf.h>
46 #include <sys/mount.h>
47 #include <sys/msgbuf.h>
48 #include <sys/proc.h>
49 #include <sys/reboot.h>
50 #include <sys/syscallargs.h>
51 #include <sys/syslog.h>
52 #include <sys/systm.h>
53 #include <sys/user.h>
54
55 #include <vm/vm.h>
56 #include <vm/vm_kern.h>
57
58 #if defined(UVM)
59 #include <uvm/uvm_extern.h>
60 #endif
61
62 #include <net/netisr.h>
63
64 #include <machine/bat.h>
65 #include <machine/pmap.h>
66 #include <machine/powerpc.h>
67 #include <machine/trap.h>
68
69 /*
70 * Global variables used here and there
71 */
72 #if defined(UVM)
73 vm_map_t exec_map = NULL;
74 vm_map_t mb_map = NULL;
75 vm_map_t phys_map = NULL;
76 #endif
77
78 struct pcb *curpcb;
79 struct pmap *curpm;
80 struct proc *fpuproc;
81
82 extern struct user *proc0paddr;
83
84 struct bat battable[16];
85
86 int astpending;
87
88 char *bootpath;
89
90 #define MSGBUFADDR 0x3000
91
92 caddr_t allocsys __P((caddr_t));
93
94 static int fake_spl __P((void));
95 static int fake_splx __P((int));
96 static void fake_setsoft __P((void));
97 static void fake_clock_return __P((struct clockframe *, int));
98 static void fake_irq_establish __P((int, int, void (*)(void *), void *));
99
100 struct machvec machine_interface = {
101 fake_spl,
102 fake_spl,
103 fake_spl,
104 fake_spl,
105 fake_spl,
106 fake_spl,
107 fake_spl,
108 fake_spl,
109 fake_spl,
110 fake_splx,
111 fake_setsoft,
112 fake_setsoft,
113 fake_clock_return,
114 fake_irq_establish,
115 };
116
117 int cold = 1;
118
119 void
120 initppc(startkernel, endkernel, args)
121 u_int startkernel, endkernel;
122 char *args;
123 {
124 int phandle, qhandle;
125 char name[32];
126 struct machvec *mp;
127 extern trapcode, trapsize;
128 extern dsitrap, dsisize;
129 extern isitrap, isisize;
130 extern decrint, decrsize;
131 extern tlbimiss, tlbimsize;
132 extern tlbdlmiss, tlbdlmsize;
133 extern tlbdsmiss, tlbdsmsize;
134 #ifdef DDB
135 extern ddblow, ddbsize;
136 extern void *startsym, *endsym;
137 #endif
138 #if NIPKDB > 0
139 extern ipkdblow, ipkdbsize;
140 #endif
141 extern void consinit __P((void));
142 extern void callback __P((void *));
143 int exc, scratch;
144
145 proc0.p_addr = proc0paddr;
146 bzero(proc0.p_addr, sizeof *proc0.p_addr);
147
148 curpcb = &proc0paddr->u_pcb;
149
150 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
151
152 /*
153 * i386 port says, that this shouldn't be here,
154 * but I really think the console should be initialized
155 * as early as possible.
156 */
157 consinit();
158
159 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */
160 OF_set_callback(callback);
161 #endif
162 /*
163 * Initialize BAT registers to unmapped to not generate
164 * overlapping mappings below.
165 */
166 asm volatile ("mtibatu 0,%0" :: "r"(0));
167 asm volatile ("mtibatu 1,%0" :: "r"(0));
168 asm volatile ("mtibatu 2,%0" :: "r"(0));
169 asm volatile ("mtibatu 3,%0" :: "r"(0));
170 asm volatile ("mtdbatu 0,%0" :: "r"(0));
171 asm volatile ("mtdbatu 1,%0" :: "r"(0));
172 asm volatile ("mtdbatu 2,%0" :: "r"(0));
173 asm volatile ("mtdbatu 3,%0" :: "r"(0));
174
175 /*
176 * Set up initial BAT table to only map the lowest 256 MB area
177 */
178 battable[0].batl = BATL(0x00000000, BAT_M);
179 battable[0].batu = BATU(0x00000000);
180
181 /*
182 * Now setup fixed bat registers
183 *
184 * Note that we still run in real mode, and the BAT
185 * registers were cleared above.
186 */
187 /* IBAT0 used for initial 256 MB segment */
188 asm volatile ("mtibatl 0,%0; mtibatu 0,%1"
189 :: "r"(battable[0].batl), "r"(battable[0].batu));
190 /* DBAT0 used similar */
191 asm volatile ("mtdbatl 0,%0; mtdbatu 0,%1"
192 :: "r"(battable[0].batl), "r"(battable[0].batu));
193
194 /*
195 * Set up trap vectors
196 */
197 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100)
198 switch (exc) {
199 default:
200 bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
201 break;
202 case EXC_EXI:
203 /*
204 * This one is (potentially) installed during autoconf
205 */
206 break;
207 case EXC_DSI:
208 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
209 break;
210 case EXC_ISI:
211 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
212 break;
213 case EXC_DECR:
214 bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
215 break;
216 case EXC_IMISS:
217 bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
218 break;
219 case EXC_DLMISS:
220 bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
221 break;
222 case EXC_DSMISS:
223 bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
224 break;
225 #if defined(DDB) || NIPKDB > 0
226 case EXC_PGM:
227 case EXC_TRC:
228 case EXC_BPT:
229 #if defined(DDB)
230 bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
231 #else
232 bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize);
233 #endif
234 break;
235 #endif /* DDB || NIPKDB > 0 */
236 }
237
238 syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
239
240 /*
241 * Now enable translation (and machine checks/recoverable interrupts).
242 */
243 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
244 : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
245
246 /*
247 * Parse arg string.
248 */
249 bootpath = args;
250 while (*++args && *args != ' ');
251 if (*args) {
252 *args++ = 0;
253 while (*args) {
254 switch (*args++) {
255 case 'a':
256 boothowto |= RB_ASKNAME;
257 break;
258 case 's':
259 boothowto |= RB_SINGLE;
260 break;
261 case 'd':
262 boothowto |= RB_KDB;
263 break;
264 }
265 }
266 }
267
268 #ifdef DDB
269 /* ddb_init(startsym, endsym); */
270 #endif
271 #if NIPKDB > 0
272 /*
273 * Now trap to IPKDB
274 */
275 ipkdb_init();
276 if (boothowto & RB_KDB)
277 ipkdb_connect(0);
278 #endif
279
280 /*
281 * Set the page size.
282 */
283 #if defined(UVM)
284 uvm_setpagesize();
285 #else
286 vm_set_page_size();
287 #endif
288
289 /*
290 * Initialize pmap module.
291 */
292 pmap_bootstrap(startkernel, endkernel);
293 }
294
295 /*
296 * This should probably be in autoconf! XXX
297 */
298 int cpu;
299 char cpu_model[80];
300 char machine[] = MACHINE; /* from <machine/param.h> */
301 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */
302
303 void
304 identifycpu()
305 {
306 int phandle, pvr;
307 char name[32];
308
309 /*
310 * Find cpu type (Do it by OpenFirmware?)
311 */
312 asm ("mfpvr %0" : "=r"(pvr));
313 cpu = pvr >> 16;
314 switch (cpu) {
315 case 1:
316 sprintf(cpu_model, "601");
317 break;
318 case 3:
319 sprintf(cpu_model, "603");
320 break;
321 case 4:
322 sprintf(cpu_model, "604");
323 break;
324 case 5:
325 sprintf(cpu_model, "602");
326 break;
327 case 6:
328 sprintf(cpu_model, "603e");
329 break;
330 case 7:
331 sprintf(cpu_model, "603ev");
332 break;
333 case 9:
334 sprintf(cpu_model, "604ev");
335 break;
336 case 20:
337 sprintf(cpu_model, "620");
338 break;
339 default:
340 sprintf(cpu_model, "Version %x", cpu);
341 break;
342 }
343 sprintf(cpu_model + strlen(cpu_model), " (Revision %x)", pvr & 0xffff);
344 printf("CPU: %s\n", cpu_model);
345 }
346
347 void
348 install_extint(handler)
349 void (*handler) __P((void));
350 {
351 extern extint, extsize;
352 extern u_long extint_call;
353 u_long offset = (u_long)handler - (u_long)&extint_call;
354 int omsr, msr;
355
356 #ifdef DIAGNOSTIC
357 if (offset > 0x1ffffff)
358 panic("install_extint: too far away");
359 #endif
360 asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
361 : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE));
362 extint_call = (extint_call & 0xfc000003) | offset;
363 bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
364 syncicache((void *)&extint_call, sizeof extint_call);
365 syncicache((void *)EXC_EXI, (int)&extsize);
366 asm volatile ("mtmsr %0" :: "r"(omsr));
367 }
368
369 /*
370 * Machine dependent startup code.
371 */
372 void
373 cpu_startup()
374 {
375 int sz, i;
376 caddr_t v;
377 vm_offset_t minaddr, maxaddr;
378 int base, residual;
379
380 /*
381 * Initialize error message buffer (at end of core).
382 */
383 initmsgbuf((caddr_t)MSGBUFADDR, round_page(MSGBUFSIZE));
384
385 proc0.p_addr = proc0paddr;
386 v = (caddr_t)proc0paddr + USPACE;
387
388 printf("%s", version);
389 identifycpu();
390
391 printf("real mem = %d\n", ctob(physmem));
392
393 /*
394 * Find out how much space we need, allocate it,
395 * and then give everything true virtual addresses.
396 */
397 sz = (int)allocsys((caddr_t)0);
398 #if defined(UVM)
399 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
400 panic("startup: no room for tables");
401 #else
402 if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
403 panic("startup: no room for tables");
404 #endif
405 if (allocsys(v) - v != sz)
406 panic("startup: table size inconsistency");
407
408 /*
409 * Now allocate buffers proper. They are different than the above
410 * in that they usually occupy more virtual memory than physical.
411 */
412 sz = MAXBSIZE * nbuf;
413 #if defined(UVM)
414 if (uvm_map(kernel_map, (vm_offset_t *)&buffers, round_page(sz),
415 NULL, UVM_UNKNOWN_OFFSET,
416 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
417 UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
418 panic("startup: cannot allocate VM for buffers");
419 #else
420 buffer_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, sz, TRUE);
421 buffers = (char *)minaddr;
422 if (vm_map_find(buffer_map, vm_object_allocate(sz), (vm_offset_t)0,
423 &minaddr, sz, FALSE) != KERN_SUCCESS)
424 panic("startup: cannot allocate buffers");
425 #endif
426 base = bufpages / nbuf;
427 residual = bufpages % nbuf;
428 if (base >= MAXBSIZE) {
429 /* Don't want to alloc more physical mem than ever needed */
430 base = MAXBSIZE;
431 residual = 0;
432 }
433 for (i = 0; i < nbuf; i++) {
434 #if defined(UVM)
435 vm_size_t curbufsize;
436 vm_offset_t curbuf;
437 struct vm_page *pg;
438
439 /*
440 * Each buffer has MAXBSIZE bytes of VM space allocated. Of
441 * that MAXBSIZE space, we allocate and map (base+1) pages
442 * for the first "residual" buffers, and then we allocate
443 * "base" pages for the rest.
444 */
445 curbuf = (vm_offset_t) buffers + (i * MAXBSIZE);
446 curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
447
448 while (curbufsize) {
449 pg = uvm_pagealloc(NULL, 0, NULL);
450 if (pg == NULL)
451 panic("startup: not enough memory for "
452 "buffer cache");
453 pmap_enter(kernel_map->pmap, curbuf,
454 VM_PAGE_TO_PHYS(pg), VM_PROT_ALL, TRUE);
455 curbuf += PAGE_SIZE;
456 curbufsize -= PAGE_SIZE;
457 }
458 #else
459 vm_size_t curbufsize;
460 vm_offset_t curbuf;
461
462 curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
463 curbufsize = CLBYTES * (i < residual ? base + 1 : base);
464 vm_map_pageable(buffer_map, curbuf, curbuf + curbufsize, FALSE);
465 vm_map_simplify(buffer_map, curbuf);
466 #endif
467 }
468
469 /*
470 * Allocate a submap for exec arguments. This map effectively
471 * limits the number of processes exec'ing at any time.
472 */
473 #if defined(UVM)
474 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
475 16*NCARGS, TRUE, FALSE, NULL);
476 #else
477 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
478 16*NCARGS, TRUE);
479 #endif
480
481 /*
482 * Allocate a submap for physio
483 */
484 #if defined(UVM)
485 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
486 VM_PHYS_SIZE, TRUE, FALSE, NULL);
487 #else
488 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
489 VM_PHYS_SIZE, TRUE);
490 #endif
491
492 /*
493 * Finally, allocate mbuf cluster submap.
494 */
495 #if defined(UVM)
496 mb_map = uvm_km_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
497 VM_MBUF_SIZE, FALSE, FALSE, NULL);
498 #else
499 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
500 VM_MBUF_SIZE, FALSE);
501 #endif
502
503 /*
504 * Initialize callouts.
505 */
506 callfree = callout;
507 for (i = 1; i < ncallout; i++)
508 callout[i - 1].c_next = &callout[i];
509
510 #if defined(UVM)
511 printf("avail memory = %d\n", ptoa(uvmexp.free));
512 #else
513 printf("avail memory = %d\n", ptoa(cnt.v_free_count));
514 #endif
515 printf("using %d buffers containing %d bytes of memory\n",
516 nbuf, bufpages * CLBYTES);
517
518 /*
519 * Set up the buffers.
520 */
521 bufinit();
522
523 /*
524 * For now, use soft spl handling.
525 */
526 {
527 extern struct machvec soft_machvec;
528
529 machine_interface = soft_machvec;
530 }
531
532 /*
533 * Now allow hardware interrupts.
534 */
535 {
536 int msr;
537
538 splhigh();
539 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
540 : "=r"(msr) : "K"((u_short)(PSL_EE|PSL_RI)));
541 }
542
543 /*
544 * Configure devices.
545 */
546 configure();
547 }
548
549 /*
550 * Allocate space for system data structures.
551 */
552 caddr_t
553 allocsys(v)
554 caddr_t v;
555 {
556 #define valloc(name, type, num) \
557 v = (caddr_t)(((name) = (type *)v) + (num))
558
559 valloc(callout, struct callout, ncallout);
560 #ifdef SYSVSHM
561 valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
562 #endif
563 #ifdef SYSVSEM
564 valloc(sema, struct semid_ds, seminfo.semmni);
565 valloc(sem, struct sem, seminfo.semmns);
566 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
567 #endif
568 #ifdef SYSVMSG
569 valloc(msgpool, char, msginfo.msgmax);
570 valloc(msgmaps, struct msgmap, msginfo.msgseg);
571 valloc(msghdrs, struct msg, msginfo.msgtql);
572 valloc(msqids, struct msqid_ds, msginfo.msgmni);
573 #endif
574
575 /*
576 * Decide on buffer space to use.
577 */
578 if (bufpages == 0)
579 bufpages = (physmem / 20) / CLSIZE;
580 if (nbuf == 0) {
581 nbuf = bufpages;
582 if (nbuf < 16)
583 nbuf = 16;
584 }
585 if (nswbuf == 0) {
586 nswbuf = (nbuf / 2) & ~1;
587 if (nswbuf > 256)
588 nswbuf = 256;
589 }
590 #if !defined(UVM)
591 valloc(swbuf, struct buf, nswbuf);
592 #endif
593 valloc(buf, struct buf, nbuf);
594
595 return v;
596 }
597
598 /*
599 * consinit
600 * Initialize system console.
601 */
602 void
603 consinit()
604 {
605 static int initted;
606
607 if (initted)
608 return;
609 initted = 1;
610 cninit();
611 }
612
613 /*
614 * Set set up registers on exec.
615 */
616 void
617 setregs(p, pack, stack)
618 struct proc *p;
619 struct exec_package *pack;
620 u_long stack;
621 {
622 struct trapframe *tf = trapframe(p);
623 struct ps_strings arginfo;
624
625 bzero(tf, sizeof *tf);
626 tf->fixreg[1] = -roundup(-stack + 8, 16);
627
628 /*
629 * XXX Machine-independent code has already copied arguments and
630 * XXX environment to userland. Get them back here.
631 */
632 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
633
634 /*
635 * Set up arguments for _start():
636 * _start(argc, argv, envp, obj, cleanup, ps_strings);
637 *
638 * Notes:
639 * - obj and cleanup are the auxilliary and termination
640 * vectors. They are fixed up by ld.elf_so.
641 * - ps_strings is a NetBSD extention, and will be
642 * ignored by executables which are strictly
643 * compliant with the SVR4 ABI.
644 *
645 * XXX We have to set both regs and retval here due to different
646 * XXX calling convention in trap.c and init_main.c.
647 */
648 tf->fixreg[3] = arginfo.ps_nargvstr;
649 tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
650 tf->fixreg[5] = (register_t)arginfo.ps_envstr;
651 tf->fixreg[6] = 0; /* auxillary vector */
652 tf->fixreg[7] = 0; /* termination vector */
653 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */
654
655 tf->srr0 = pack->ep_entry;
656 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
657 p->p_addr->u_pcb.pcb_flags = 0;
658 }
659
660 /*
661 * Send a signal to process.
662 */
663 void
664 sendsig(catcher, sig, mask, code)
665 sig_t catcher;
666 int sig, mask;
667 u_long code;
668 {
669 struct proc *p = curproc;
670 struct trapframe *tf;
671 struct sigframe *fp, frame;
672 struct sigacts *psp = p->p_sigacts;
673 int oldonstack;
674
675 frame.sf_signum = sig;
676
677 tf = trapframe(p);
678 oldonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
679
680 /*
681 * Allocate stack space for signal handler.
682 */
683 if ((psp->ps_flags & SAS_ALTSTACK)
684 && !oldonstack
685 && (psp->ps_sigonstack & sigmask(sig))) {
686 fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp
687 + psp->ps_sigstk.ss_size);
688 psp->ps_sigstk.ss_flags |= SS_ONSTACK;
689 } else
690 fp = (struct sigframe *)tf->fixreg[1];
691 fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
692
693 frame.sf_code = code;
694
695 /*
696 * Generate signal context for SYS_sigreturn.
697 */
698 frame.sf_sc.sc_onstack = oldonstack;
699 frame.sf_sc.sc_mask = mask;
700 bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf);
701 if (copyout(&frame, fp, sizeof frame) != 0)
702 sigexit(p, SIGILL);
703
704 tf->fixreg[1] = (int)fp;
705 tf->lr = (int)catcher;
706 tf->fixreg[3] = (int)sig;
707 tf->fixreg[4] = (int)code;
708 tf->fixreg[5] = (int)&frame.sf_sc;
709 tf->srr0 = (int)(((char *)PS_STRINGS)
710 - (p->p_emul->e_esigcode - p->p_emul->e_sigcode));
711 }
712
713 /*
714 * System call to cleanup state after a signal handler returns.
715 */
716 int
717 sys_sigreturn(p, v, retval)
718 struct proc *p;
719 void *v;
720 register_t *retval;
721 {
722 struct sys_sigreturn_args /* {
723 syscallarg(struct sigcontext *) sigcntxp;
724 } */ *uap = v;
725 struct sigcontext sc;
726 struct trapframe *tf;
727 int error;
728
729 if (error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc))
730 return error;
731 tf = trapframe(p);
732 if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
733 return EINVAL;
734 bcopy(&sc.sc_frame, tf, sizeof *tf);
735 if (sc.sc_onstack & 1)
736 p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
737 else
738 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
739 p->p_sigmask = sc.sc_mask & ~sigcantmask;
740 return EJUSTRETURN;
741 }
742
743 /*
744 * Machine dependent system variables.
745 * None for now.
746 */
747 int
748 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
749 int *name;
750 u_int namelen;
751 void *oldp;
752 size_t *oldlenp;
753 void *newp;
754 size_t newlen;
755 struct proc *p;
756 {
757 /* all sysctl names at this level are terminal */
758 if (namelen != 1)
759 return ENOTDIR;
760 switch (name[0]) {
761 default:
762 return EOPNOTSUPP;
763 }
764 }
765
766 /*
767 * Crash dump handling.
768 */
769 u_long dumpmag = 0x8fca0101; /* magic number */
770 int dumpsize = 0; /* size of dump in pages */
771 long dumplo = -1; /* blocks */
772
773 void
774 dumpsys()
775 {
776 printf("dumpsys: TBD\n");
777 }
778
779 /*
780 * Soft networking interrupts.
781 */
782 void
783 softnet()
784 {
785 int isr = netisr;
786
787 netisr = 0;
788 #ifdef INET
789 #include "arp.h"
790 #if NARP > 0
791 if (isr & (1 << NETISR_ARP))
792 arpintr();
793 #endif
794 if (isr & (1 << NETISR_IP))
795 ipintr();
796 #endif
797 #ifdef IMP
798 if (isr & (1 << NETISR_IMP))
799 impintr();
800 #endif
801 #ifdef NS
802 if (isr & (1 << NETISR_NS))
803 nsintr();
804 #endif
805 #ifdef ISO
806 if (isr & (1 << NETISR_ISO))
807 clnlintr();
808 #endif
809 #ifdef CCITT
810 if (isr & (1 << NETISR_CCITT))
811 ccittintr();
812 #endif
813 #include "ppp.h"
814 #if NPPP > 0
815 if (isr & (1 << NETISR_PPP))
816 pppintr();
817 #endif
818 }
819
820 /*
821 * Stray interrupts.
822 */
823 void
824 strayintr(irq)
825 int irq;
826 {
827 log(LOG_ERR, "stray interrupt %d\n", irq);
828 }
829
830 /*
831 * Halt or reboot the machine after syncing/dumping according to howto.
832 */
833 void
834 cpu_reboot(howto, what)
835 int howto;
836 char *what;
837 {
838 static int syncing;
839 static char str[256];
840 char *ap = str, *ap1 = ap;
841
842 boothowto = howto;
843 if (!cold && !(howto & RB_NOSYNC) && !syncing) {
844 syncing = 1;
845 vfs_shutdown(); /* sync */
846 resettodr(); /* set wall clock */
847 }
848 splhigh();
849 if (howto & RB_HALT) {
850 doshutdownhooks();
851 printf("halted\n\n");
852 ppc_exit();
853 }
854 if (!cold && (howto & RB_DUMP))
855 dumpsys();
856 doshutdownhooks();
857 printf("rebooting\n\n");
858 if (what && *what) {
859 if (strlen(what) > sizeof str - 5)
860 printf("boot string too large, ignored\n");
861 else {
862 strcpy(str, what);
863 ap1 = ap = str + strlen(str);
864 *ap++ = ' ';
865 }
866 }
867 *ap++ = '-';
868 if (howto & RB_SINGLE)
869 *ap++ = 's';
870 if (howto & RB_KDB)
871 *ap++ = 'd';
872 *ap++ = 0;
873 if (ap[-2] == '-')
874 *ap1 = 0;
875 ppc_boot(str);
876 }
877
878 /*
879 * OpenFirmware callback routine
880 */
881 void
882 callback(p)
883 void *p;
884 {
885 panic("callback"); /* for now XXX */
886 }
887
888 /*
889 * Initial Machine Interface.
890 */
891 static int
892 fake_spl()
893 {
894 int scratch;
895
896 asm volatile ("mfmsr %0; andi. %0,%0,%1; mtmsr %0; isync"
897 : "=r"(scratch) : "K"((u_short)~(PSL_EE|PSL_ME)));
898 return -1;
899 }
900
901 static void
902 fake_setsoft()
903 {
904 /* Do nothing */
905 }
906
907 static int
908 fake_splx(new)
909 int new;
910 {
911 return fake_spl();
912 }
913
914 static void
915 fake_clock_return(frame, nticks)
916 struct clockframe *frame;
917 int nticks;
918 {
919 /* Do nothing */
920 }
921
922 static void
923 fake_irq_establish(irq, level, handler, arg)
924 int irq, level;
925 void (*handler) __P((void *));
926 void *arg;
927 {
928 panic("fake_irq_establish");
929 }
930