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