summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/mvme88k/machdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k/mvme88k/machdep.c')
-rw-r--r--sys/arch/mvme88k/mvme88k/machdep.c1360
1 files changed, 1360 insertions, 0 deletions
diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c
new file mode 100644
index 00000000000..fb3002a426f
--- /dev/null
+++ b/sys/arch/mvme88k/mvme88k/machdep.c
@@ -0,0 +1,1360 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1991 Carnegie Mellon University
+ * Copyright (c) 1991 OMRON Corporation
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/clist.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/mount.h>
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/psl.h>
+#include <machine/locore.h>
+#include <machine/board.h>
+#include <machine/trap.h>
+#include <machine/bug.h>
+
+#include <dev/cons.h>
+
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#define __IS_MACHDEP_C__
+#include <assym.s> /* EF_EPSR, etc. */
+#include <machine/m88100.h> /* DMT_VALID */
+#include <machine/m882xx.h> /* CMMU stuff */
+#if DDB
+# include <machine/db_machdep.h>
+#endif /* DDB */
+
+#if 0
+#include <machine/m88100.h> /* DMT_VALID */
+#include <machine/m882xx.h> /* CMMU stuff */
+#include <vm/vm.h>
+#include <vm/vm_kern.h> /* kernel_map */
+#include <sys/param.h>
+#include <sys/msgbuf.h>
+#include <sys/buf.h>
+#include <machine/locore.h> /* USERMODE */
+/*
+#include <machine/nvram.h>
+*/
+#include <sys/types.h>
+#endif /* 0 */
+
+static int waittime = -1;
+
+static void level0_intr(int, unsigned *);
+static void level1_intr(int, unsigned *);
+static void level2_intr(int, unsigned *);
+static void level3_intr(int, unsigned *);
+static void level4_intr(int, unsigned *);
+static void level5_intr(int, unsigned *);
+static void level6_intr(int, unsigned *);
+static void level7_intr(int, unsigned *);
+
+unsigned char *ivec[] = {
+ (unsigned char *)0xFFFE007,
+ (unsigned char *)0xFFFE00B,
+ (unsigned char *)0xFFFE00F,
+ (unsigned char *)0xFFFE013,
+ (unsigned char *)0xFFFE017,
+ (unsigned char *)0xFFFE01B,
+ (unsigned char *)0xFFFE01F,
+};
+
+static void (*int_handler[8])() =
+{
+ level0_intr,
+ level1_intr,
+ level2_intr,
+ level3_intr,
+ level4_intr,
+ level5_intr,
+ level6_intr,
+ level7_intr,
+};
+
+unsigned char *int_mask_level = (unsigned char *)INT_MASK_LEVEL;
+unsigned char *int_pri_level = (unsigned char *)INT_PRI_LEVEL;
+unsigned char *iackaddr;
+
+int physmem; /* available physical memory, in pages */
+int cold;
+vm_offset_t avail_end, avail_start, avail_next;
+int msgbufmapped = 0;
+int foodebug = 0;
+int longformat = 0;
+
+extern char kstack[]; /* kernel stack - actually this is == UADDR */
+extern char *cpu_string;
+extern short exframesize[];
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+int nswbuf = 0;
+#ifdef NBUF
+int nbuf = NBUF;
+#else
+int nbuf = 0;
+#endif
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int *nofault;
+
+caddr_t allocsys __P((caddr_t));
+
+/*
+ * Info for CTL_HW
+ */
+char machine[] = "MVME187"; /* cpu "architecture" */
+char cpu_model[120];
+extern char version[];
+
+ /*
+ * Console initialization: called early on from main,
+ * before vm init or startup. Do enough configuration
+ * to choose and initialize a console.
+ */
+void
+consinit()
+{
+
+ /*
+ * Initialize the console before we print anything out.
+ */
+ cninit();
+
+#if defined (DDB)
+ kdb_init();
+ if (boothowto & RB_KDB)
+ Debugger();
+#endif
+}
+
+/*
+ * Figure out how much real memory is available.
+ * Start looking from the megabyte after the end of the kernel data,
+ * until we find non-memory.
+ */
+vm_offset_t
+size_memory(void)
+{
+ volatile unsigned int *look;
+ unsigned int *max;
+ extern char end[];
+ #define PATTERN 0x5a5a5a5a
+ #define STRIDE (4*1024) /* 4k at a time */
+ #define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
+
+ /*
+ * count it up.
+ */
+ max = (void*)MAXPHYSMEM;
+ for (look = (void*)Roundup(end, STRIDE); look < max;
+ look = (int*)((unsigned)look + STRIDE)) {
+ unsigned save;
+
+ /* if can't access, we've reached the end */
+ if (foodebug)
+ printf("%x\n", look);
+ if (badwordaddr((vm_offset_t)look)) {
+ printf("%x\n", look);
+ look = (int *)((int)look - STRIDE);
+ break;
+ }
+
+#if 1
+ /*
+ * If we write a value, we expect to read the same value back.
+ * We'll do this twice, the 2nd time with the opposite bit
+ * pattern from the first, to make sure we check all bits.
+ */
+ save = *look;
+ if (*look = PATTERN, *look != PATTERN)
+ break;
+ if (*look = ~PATTERN, *look != ~PATTERN)
+ break;
+ *look = save;
+#endif
+ }
+
+ physmem = btoc(trunc_page((unsigned)look)); /* in pages */
+ return(trunc_page((unsigned)look));
+}
+
+void
+identifycpu()
+{
+ /* XXX -take this one out. It can be done in m187_bootstrap() */
+ strcpy(cpu_model, "Motorola M88K");
+ printf("Model: %s\n", cpu_model);
+}
+
+/* The following two functions assume UPAGES == 3 */
+#if UPAGES != 3
+#error "UPAGES changed?"
+#endif
+
+void
+save_u_area(struct proc *p, vm_offset_t va)
+{
+ p->p_md.md_upte[0] = kvtopte(va)->bits;
+ p->p_md.md_upte[1] = kvtopte(va + NBPG)->bits;
+ p->p_md.md_upte[2] = kvtopte(va + NBPG + NBPG)->bits;
+}
+
+void
+load_u_area(struct proc *p)
+{
+ pte_template_t *t;
+
+ t = kvtopte(UADDR);
+ t->bits = p->p_md.md_upte[0];
+ t = kvtopte(UADDR + NBPG);
+ t->bits = p->p_md.md_upte[1];
+ t = kvtopte(UADDR + NBPG + NBPG);
+ t->bits = p->p_md.md_upte[2];
+ cmmu_flush_tlb(1, UADDR, 3 * NBPG);
+}
+
+
+void
+cpu_startup()
+{
+ caddr_t v;
+ int sz, i;
+ vm_size_t size;
+ int base, residual;
+ vm_offset_t minaddr, maxaddr, uarea_pages;
+ extern vm_offset_t miniroot;
+
+ /*
+ * Initialize error message buffer (at end of core).
+ * avail_end was pre-decremented in m1x7_init.
+ */
+ for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
+ pmap_enter(kernel_pmap, (vm_offset_t)msgbufp,
+ avail_end + i * NBPG, VM_PROT_ALL, TRUE);
+ msgbufmapped = 1;
+
+ printf(version);
+ identifycpu();
+ printf("real mem = %d\n", ctob(physmem));
+
+ /*
+ * Find out how much space we need, allocate it,
+ * and then give everything true virtual addresses.
+ */
+ sz = (int)allocsys((caddr_t)0);
+ if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
+ panic("startup: no room for tables");
+ if (allocsys(v) - v != sz)
+ panic("startup: table size inconsistency");
+
+ /*
+ * Grab UADDR virtual address
+ */
+
+ uarea_pages = UADDR;
+
+ vm_map_find(kernel_map, vm_object_allocate(PAGE_SIZE * UPAGES), 0,
+ (vm_offset_t *)&uarea_pages, PAGE_SIZE * UPAGES, TRUE);
+
+ if (uarea_pages != UADDR) {
+ printf("uarea_pages %x: UADDR not free\n", uarea_pages);
+ panic("bad UADDR");
+ }
+ /*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, size, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+ (vm_offset_t *)&minaddr, size, FALSE) != KERN_SUCCESS)
+ panic("startup: cannot allocate buffers");
+ if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
+ /* don't want to alloc more physical mem than needed */
+ bufpages = btoc(MAXBSIZE) * nbuf;
+ }
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ for (i = 0; i < nbuf; i++) {
+ vm_size_t curbufsize;
+ vm_offset_t curbuf;
+
+ /*
+ * First <residual> buffers get (base+1) physical pages
+ * allocated for them. The rest get (base) physical pages.
+ *
+ * The rest of each buffer occupies virtual space,
+ * but has no physical memory allocated for it.
+ */
+ curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
+ curbufsize = CLBYTES * (i < residual ? base+1 : base);
+ vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+ vm_map_simplify(buffer_map, curbuf);
+ }
+
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ 16*NCARGS, TRUE);
+
+ /*
+ * Allocate a map for IO.
+ */
+ phys_map = vm_map_create(kernel_pmap, IO_SPACE_START,
+ IO_SPACE_END, TRUE);
+ if (phys_map == NULL)
+ panic("cpu_startup: unable to create physmap");
+
+ /*
+ * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
+ * we use the more space efficient malloc in place of kmem_alloc.
+ */
+ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
+ M_MBUF, M_NOWAIT);
+ bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
+ mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
+ VM_MBUF_SIZE, FALSE);
+
+ /*
+ * Initialize callouts
+ */
+ callfree = callout;
+ for (i = 1; i < ncallout; i++)
+ callout[i-1].c_next = &callout[i];
+ callout[i-1].c_next = NULL;
+
+ printf("avail mem = %d\n", ptoa(cnt.v_free_count));
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+
+ mfs_initminiroot(miniroot);
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+ /*
+ * Configure the system.
+ */
+ nofault = NULL;
+ configure();
+
+ dumpconf();
+}
+
+/*
+ * Allocate space for system data structures. We are given
+ * a starting virtual address and we return a final virtual
+ * address; along the way we set each data structure pointer.
+ *
+ * We call allocsys() with 0 to find out how much space we want,
+ * allocate that much and fill it with zeroes, and then call
+ * allocsys() again with the correct base virtual address.
+ */
+caddr_t
+allocsys(v)
+ register caddr_t v;
+{
+
+#define valloc(name, type, num) \
+ v = (caddr_t)(((name) = (type *)v) + (num))
+
+#ifdef REAL_CLISTS
+ valloc(cfree, struct cblock, nclist);
+#endif
+ valloc(callout, struct callout, ncallout);
+ valloc(swapmap, struct map, nswapmap = maxproc * 2);
+#ifdef SYSVSHM
+ valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+ valloc(sema, struct semid_ds, seminfo.semmni);
+ valloc(sem, struct sem, seminfo.semmns);
+ /* This is pretty disgusting! */
+ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+ /*
+ * Determine how many buffers to allocate (enough to
+ * hold 5% of total physical memory, but at least 16).
+ * Allocate 1/2 as many swap buffer headers as file i/o buffers.
+ */
+ if (bufpages == 0)
+ if (physmem < btoc(2 * 1024 * 1024))
+ bufpages = (physmem / 10) / CLSIZE;
+ else
+ bufpages = (physmem / 20) / CLSIZE;
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+ if (nswbuf == 0) {
+ nswbuf = (nbuf / 2) &~ 1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+ return v;
+}
+
+/*
+ * Set registers on exec.
+ * Clear all except sp and pc.
+ */
+/* ARGSUSED */
+void
+setregs(p, pack, stack, retval)
+ struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ int retval[2];
+{
+ register struct trapframe *tf = p->p_md.md_tf;
+ register int psr;
+
+ /*
+ * The syscall will ``return'' to snip; set it.
+ * Set the rest of the registers to 0 except for r31 (stack pointer,
+ * built in exec()) and psr (supervisor bit).
+ */
+ psr = tf->epsr & PSR_SUPERVISOR_MODE_BIT;
+#if 0
+ /*
+ I don't think I need to mess with fpstate on 88k because
+ we make sure the floating point pipeline is drained in
+ locore.s. Should check on this later. Nivas.
+ */
+
+ if ((fs = p->p_md.md_fpstate) != NULL) {
+ /*
+ * We hold an FPU state. If we own *the* FPU chip state
+ * we must get rid of it, and the only way to do that is
+ * to save it. In any case, get rid of our FPU state.
+ */
+ if (p == fpproc) {
+ savefpstate(fs);
+ fpproc = NULL;
+ }
+ free((void *)fs, M_SUBPROC);
+ p->p_md.md_fpstate = NULL;
+ }
+#endif /* 0 */
+ bzero((caddr_t)tf, sizeof *tf);
+ tf->epsr = psr;
+ tf->snip = pack->ep_entry & ~3;
+ tf->sfip = tf->snip + 4;
+ tf->r[31] = stack;
+ retval[1] = 0;
+}
+
+/*
+ * WARNING: code in locore.s assumes the layout shown for sf_signum
+ * thru sf_handler so... don't screw with them!
+ */
+struct sigframe {
+ int sf_signo; /* signo for handler */
+ int sf_code; /* additional info for handler */
+ struct sigcontext *sf_scp; /* context ptr for handler */
+ sig_t sf_handler; /* handler addr for u_sigc */
+ struct sigcontext sf_sc; /* actual context */
+};
+
+#ifdef DEBUG
+int sigdebug = 0;
+int sigpid = 0;
+#define SDB_FOLLOW 0x01
+#define SDB_KSTACK 0x02
+#define SDB_FPSTATE 0x04
+#endif
+
+/*
+ * Send an interrupt to process.
+ */
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ unsigned long code;
+{
+ register struct proc *p = curproc;
+ register struct trapframe *tf;
+ register struct sigacts *psp = p->p_sigacts;
+ struct sigframe *fp;
+ int oonstack, fsize;
+ struct sigframe sf;
+ int addr;
+ extern char sigcode[], esigcode[];
+
+#define szsigcode (esigcode - sigcode)
+
+ tf = p->p_md.md_tf;
+ oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in data space, the
+ * call to grow() is a nop, and the copyout()
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+ fsize = sizeof(struct sigframe);
+ if ((psp->ps_flags & SAS_ALTSTACK) &&
+ (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
+ psp->ps_sigstk.ss_size - fsize);
+ psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+ } else
+ fp = (struct sigframe *)(tf->r[31] - fsize);
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
+ p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
+#endif
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ sf.sf_signo = sig;
+ sf.sf_code = code;
+ sf.sf_scp = &fp->sf_sc;
+ sf.sf_sc.sc_onstack = oonstack;
+ sf.sf_sc.sc_mask = mask;
+ /*
+ * Copy the whole user context into signal context that we
+ * are building.
+ */
+
+ bcopy((caddr_t)tf->r, (caddr_t)sf.sf_sc.sc_regs,
+ sizeof(sf.sf_sc.sc_regs));
+ sf.sf_sc.sc_xip = tf->sxip;
+ sf.sf_sc.sc_nip = tf->snip;
+ sf.sf_sc.sc_fip = tf->sfip;
+ sf.sf_sc.sc_ps = tf->epsr;
+ sf.sf_sc.sc_sp = tf->r[31];
+ sf.sf_sc.sc_fpsr = tf->fpsr;
+ sf.sf_sc.sc_fpcr = tf->fpcr;
+ sf.sf_sc.sc_ssbr = tf->ssbr;
+ sf.sf_sc.sc_dmt0 = tf->dmt0;
+ sf.sf_sc.sc_dmd0 = tf->dmd0;
+ sf.sf_sc.sc_dma0 = tf->dma0;
+ sf.sf_sc.sc_dmt1 = tf->dmt1;
+ sf.sf_sc.sc_dmd1 = tf->dmd1;
+ sf.sf_sc.sc_dma1 = tf->dma1;
+ sf.sf_sc.sc_dmt2 = tf->dmt2;
+ sf.sf_sc.sc_dmd2 = tf->dmd2;
+ sf.sf_sc.sc_dma2 = tf->dma2;
+ sf.sf_sc.sc_fpecr = tf->fpecr;
+ sf.sf_sc.sc_fphs1 = tf->fphs1;
+ sf.sf_sc.sc_fpls1 = tf->fpls1;
+ sf.sf_sc.sc_fphs2 = tf->fphs2;
+ sf.sf_sc.sc_fpls2 = tf->fpls2;
+ sf.sf_sc.sc_fppt = tf->fppt;
+ sf.sf_sc.sc_fprh = tf->fprh;
+ sf.sf_sc.sc_fprl = tf->fprl;
+ sf.sf_sc.sc_fpit = tf->fpit;
+ if (copyout((caddr_t)&sf, (caddr_t)&fp, sizeof sf)) {
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ /*
+ * Build the argument list for the signal handler.
+ * Signal trampoline code is at base of user stack.
+ */
+ addr = (int)PS_STRINGS - szsigcode;
+ tf->snip = addr & ~3;
+ tf->sfip = tf->snip + 4;
+ tf->r[31] = (unsigned)fp;
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+#endif
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+/* ARGSUSED */
+sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ int *retval;
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ register struct sigcontext *scp;
+ register struct trapframe *tf;
+ struct sigcontext ksc;
+ int error;
+
+ scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+ if ((int)scp & 3 || useracc((caddr_t)scp, sizeof *scp, B_WRITE) == 0)
+ return (EINVAL);
+ tf = p->p_md.md_tf;
+ /*
+ * xip, nip and fip must be multiples of 4. This is all
+ * that is required; if it holds, just do it.
+ */
+ if (((scp->sc_xip | scp->sc_nip | scp->sc_fip) & 3) != 0)
+ return (EINVAL);
+ bcopy((caddr_t)scp->sc_regs, (caddr_t)tf->r,
+ sizeof(scp->sc_regs));
+ tf->sxip = scp->sc_xip;
+ tf->snip = scp->sc_nip;
+ tf->sfip = scp->sc_fip;
+ tf->epsr = scp->sc_ps;
+ tf->r[31] = scp->sc_sp;
+ tf->fpsr = scp->sc_fpsr;
+ tf->fpcr = scp->sc_fpcr;
+ tf->ssbr = scp->sc_ssbr;
+ tf->dmt0 = scp->sc_dmt0;
+ tf->dmd0 = scp->sc_dmd0;
+ tf->dma0 = scp->sc_dma0;
+ tf->dmt1 = scp->sc_dmt1;
+ tf->dmd1 = scp->sc_dmd1;
+ tf->dma1 = scp->sc_dma1;
+ tf->dmt2 = scp->sc_dmt2;
+ tf->dmd2 = scp->sc_dmd2;
+ tf->dma2 = scp->sc_dma2;
+ tf->fpecr = scp->sc_fpecr;
+ tf->fphs1 = scp->sc_fphs1;
+ tf->fpls1 = scp->sc_fpls1;
+ tf->fphs2 = scp->sc_fphs2;
+ tf->fpls2 = scp->sc_fpls2;
+ tf->fppt = scp->sc_fppt;
+ tf->fprh = scp->sc_fprh;
+ tf->fprl = scp->sc_fprl;
+ tf->fpit = scp->sc_fpit;
+
+ tf->epsr = scp->sc_ps;
+
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->sc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~ sigcantmask;
+ return (EJUSTRETURN);
+}
+
+void
+bootsync(void)
+{
+ if (waittime < 0) {
+ register struct buf *bp;
+ int iter, nbusy;
+
+ waittime = 0;
+ (void) spl0();
+ printf("syncing disks... ");
+ /*
+ * Release vnodes held by texts before sync.
+ */
+ if (panicstr == 0)
+ vnode_pager_umount(NULL);
+ sync(&proc0, (void *)NULL, (int *)NULL);
+
+ for (iter = 0; iter < 20; iter++) {
+ nbusy = 0;
+ for (bp = &buf[nbuf]; --bp >= buf; )
+ if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
+ nbusy++;
+ if (nbusy == 0)
+ break;
+ printf("%d ", nbusy);
+ delay(40000 * iter);
+ }
+ if (nbusy)
+ printf("giving up\n");
+ else
+ printf("done\n");
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now.
+ */
+ resettodr();
+ }
+}
+
+doboot()
+{
+ bugreturn();
+}
+
+void
+boot(howto)
+ register int howto;
+{
+ /* take a snap shot before clobbering any registers */
+ if (curproc)
+ savectx(curproc->p_addr, 0);
+
+ boothowto = howto;
+ if ((howto&RB_NOSYNC) == 0)
+ bootsync();
+ splhigh(); /* extreme priority */
+ if (howto&RB_HALT) {
+ printf("halted\n\n");
+ bugreturn();
+ } else {
+ if (howto & RB_DUMP)
+ dumpsys();
+ doboot();
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
+int dumpsize = 0; /* also for savecore */
+long dumplo = 0;
+
+dumpconf()
+{
+ int nblks;
+
+ dumpsize = physmem;
+ if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
+ nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ if (dumpsize > btoc(dbtob(nblks - dumplo)))
+ dumpsize = btoc(dbtob(nblks - dumplo));
+ else if (dumplo == 0)
+ dumplo = nblks - btodb(ctob(physmem));
+ }
+ /*
+ * Don't dump on the first CLBYTES (why CLBYTES?)
+ * in case the dump device includes a disk label.
+ */
+ if (dumplo < btodb(CLBYTES))
+ dumplo = btodb(CLBYTES);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+dumpsys()
+{
+
+ msgbufmapped = 0;
+ if (dumpdev == NODEV)
+ return;
+ /*
+ * For dumps during autoconfiguration,
+ * if dump device has already configured...
+ */
+ if (dumpsize == 0)
+ dumpconf();
+ if (dumplo < 0)
+ return;
+ printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+ printf("dump ");
+ switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
+
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ default:
+ printf("succeeded\n");
+ break;
+ }
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points. We do this by returning the current time
+ * plus the amount of time since the last clock interrupt (clock.c:clkread).
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment. Just for fun,
+ * we guarantee that the time will be greater than the value obtained by a
+ * previous call.
+ */
+void
+microtime(tvp)
+ register struct timeval *tvp;
+{
+ int s = splhigh();
+ static struct timeval lasttime;
+
+ *tvp = time;
+ tvp->tv_usec += clkread();
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ if (tvp->tv_sec == lasttime.tv_sec &&
+ tvp->tv_usec <= lasttime.tv_usec &&
+ (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ lasttime = *tvp;
+ splx(s);
+}
+
+#ifdef PGINPROF
+/*
+ * Return the difference (in microseconds)
+ * between the current time and a previous
+ * time as represented by the arguments.
+ * If there is a pending clock interrupt
+ * which has not been serviced due to high
+ * ipl, return error code.
+ */
+unsigned vmtime(int otime, int olbolt, int oicr)
+{
+ return ((time.tv_sec-otime)*60 + lbolt-olbolt)*16667;
+}
+#endif /* PGINPROF */
+
+badwordaddr(void *addr)
+{
+ return badaddr((vm_offset_t)addr, 4);
+}
+
+/* returns positive if memory is not there; */
+unsigned check_memory(void *addr, unsigned flag)
+{
+ return badaddr((vm_offset_t)addr, 1);
+}
+
+void start_clock(void)
+{
+ printf("Start clock\n");
+}
+
+static void
+level0_intr(int level, unsigned *frame)
+{
+ printf("Spurious interrupt\n");
+}
+
+static void
+level1_intr(int level, unsigned *frame)
+{
+ register char vec;
+ iackaddr = ivec[level];
+
+ /* generate IACK and get the vector */
+ asm volatile ("ld.b %0,%1" : "=r" (vec) : "" (iackaddr));
+}
+#if 0
+static void
+level1_intr(int level, unsigned *frame)
+{
+ register char vec;
+ iackaddr = ivec[level];
+
+ /* generate IACK and get the vector */
+ asm volatile ("ld.b %0,%1" : "=r" (vec) : "" (iackaddr));
+}
+#endif
+
+static void
+level2_intr(int level, unsigned *frame)
+{
+ iackaddr = ivec[level];
+}
+
+static void
+level3_intr(int level, unsigned *frame)
+{
+ iackaddr = ivec[level];
+}
+
+static void
+level4_intr(int level, unsigned *frame)
+{
+ iackaddr = ivec[level];
+}
+
+static void
+level5_intr(int level, unsigned *frame)
+{
+ iackaddr = ivec[level];
+}
+
+static void
+level6_intr(int level, unsigned *frame)
+{
+ register char vec;
+ struct clockframe clkframe;
+ iackaddr = ivec[level];
+
+ /* generate IACK and get the vector */
+ asm volatile("ld.b %0,%1" : "=r" (vec) : "" (iackaddr));
+ switch (vec){
+ case TIMER1IRQ:
+ break;
+ case TIMER2IRQ:
+ /*
+ * build clockframe and pass to the clock
+ * interrupt handler
+ */
+ clkframe.pc = frame[EF_SXIP] & ~3;
+ clkframe.sr = frame[EF_EPSR];
+ clkframe.ipl = frame[EF_MASK];
+ clockintr(&clkframe);
+ break;
+ }
+}
+
+static void
+level7_intr(int level, unsigned *frame)
+{
+ iackaddr = ivec[level];
+}
+
+/*
+ * Device interrupt handler
+ *
+ * when we enter, interrupts are disabled;
+ * when we leave, they should be disabled,
+ * but they need not be enabled throughout
+ * the routine.
+ */
+
+void
+ext_int(unsigned vec, unsigned *eframe)
+{
+ register unsigned char mask, level;
+ register int s; /* XXX */
+
+ asm volatile ("ld.b %0,%1" : "=r" (mask) : "" (int_mask_level));
+ asm volatile ("ld.b %0,%1" : "=r" (level) : "" (int_pri_level));
+
+ /* get the mask and stash it away in the trap frame */
+ eframe[EF_MASK] = mask;
+ /* and block ints level or lower */
+ spln((char)mask);
+ enable_interrupt();
+ (*int_handler[level])(level,eframe);
+ /*
+ * process any remaining data access exceptions before
+ * returning to assembler
+ */
+ disable_interrupt();
+ if (eframe[EF_DMT0] && DMT_VALID)
+ {
+ trap(T_DATAFLT, eframe);
+ data_access_emulation(eframe);
+ }
+ mask = eframe[EF_MASK];
+ asm volatile ("st.b %0,%1" : "=r" (mask) : "" (int_mask_level));
+}
+
+/*
+ * check a word wide address.
+ * write < 0 -> check for write access.
+ * otherwise read.
+ */
+int wprobe(void *addr, unsigned int write)
+{
+ /* XXX only checking reads */
+ return badaddr((vm_offset_t)addr, sizeof(int));
+}
+
+cpu_exec_aout_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ int error = ENOEXEC;
+
+#ifdef COMPAT_SUNOS
+ extern sun_exec_aout_makecmds __P((struct proc *, struct exec_package *));
+ if ((error = sun_exec_aout_makecmds(p, epp)) == 0)
+ return 0;
+#endif
+ return error;
+}
+
+#if NOTYET
+/*
+ * nvram_read(BUF, ADDRESS, SIZE)
+ * nvram_write(BUF, ADDRESS, SIZE)
+ *
+ * Read and write non-volatile RAM.
+ * Only one byte from each word in the NVRAM area is accessable.
+ * ADDRESS points to the virtual starting address, which is some address
+ * after the nvram start (NVRAM_ADDR). SIZE refers to virtual size.
+ */
+void nvram_read(char *buf, vm_offset_t address, unsigned size)
+{
+ unsigned index = (unsigned)address - NVRAM_ADDR;
+ unsigned char *source = (char*)(NVRAM_ADDR + index * 4);
+
+ while (size-- > 0)
+ {
+ *buf++ = *source;
+ source += 4; /* bump up to point to next readable byte */
+ }
+}
+
+void nvram_write(char *buf, vm_offset_t address, unsigned size)
+{
+ unsigned index = (unsigned)address - NVRAM_ADDR;
+ unsigned char *source = (char*)(NVRAM_ADDR + index * 4);
+
+ while (size-- > 0)
+ {
+ *source = *buf++;
+ source += 4; /* bump up to point to next readable byte */
+ }
+}
+#endif /* NOTYET */
+
+struct sysarch_args {
+ int op;
+ char *parms;
+};
+
+sysarch(p, uap, retval)
+ struct proc *p;
+ register struct sysarch_args *uap;
+ int *retval;
+{
+ int error = 0;
+
+ switch(uap->op) {
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+/*
+ * machine dependent system variables.
+ */
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+
+ /* all sysctl names are this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ default:
+ return (EOPNOTSUPP);
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * insert an element into a queue
+ */
+#undef _insque
+_insque(element, head)
+ register struct prochd *element, *head;
+{
+ element->ph_link = head->ph_link;
+ head->ph_link = (struct proc *)element;
+ element->ph_rlink = (struct proc *)head;
+ ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
+}
+
+/*
+ * remove an element from a queue
+ */
+#undef _remque
+_remque(element)
+ register struct prochd *element;
+{
+ ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
+ ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
+ element->ph_rlink = (struct proc *)0;
+}
+
+#if 0
+/*
+ * Below written in C to allow access to debugging code
+ */
+copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
+ void *toaddr, *fromaddr;
+{
+ int c,tally;
+
+ tally = 0;
+ while (maxlength--) {
+ c = fubyte(fromaddr++);
+ if (c == -1) {
+ if(lencopied) *lencopied = tally;
+ return(EFAULT);
+ }
+ tally++;
+ *(char *)toaddr++ = (char) c;
+ if (c == 0){
+ if(lencopied) *lencopied = (u_int)tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = (u_int)tally;
+ return(ENAMETOOLONG);
+}
+
+copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
+ void *fromaddr, *toaddr;
+{
+ int c;
+ int tally;
+
+ tally = 0;
+ while (maxlength--) {
+ c = subyte(toaddr++, *(char *)fromaddr);
+ if (c == -1) return(EFAULT);
+ tally++;
+ if (*(char *)fromaddr++ == 0){
+ if(lencopied) *lencopied = tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = tally;
+ return(ENAMETOOLONG);
+}
+
+#endif /* 0 */
+
+copystr(fromaddr, toaddr, maxlength, lencopied)
+ u_int *lencopied, maxlength;
+ void *fromaddr, *toaddr;
+{
+ u_int tally;
+
+ tally = 0;
+ while (maxlength--) {
+ *(u_char *)toaddr = *(u_char *)fromaddr++;
+ tally++;
+ if (*(u_char *)toaddr++ == 0) {
+ if(lencopied) *lencopied = tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = tally;
+ return(ENAMETOOLONG);
+}
+
+void
+putchar(char c)
+{
+ bugoutchr(c);
+}
+/* dummys for now */
+
+bugsyscall()
+{
+}
+
+mmrw()
+{
+}
+
+netintr()
+{
+}
+
+MY_info(f, p, flags, s)
+struct trapframe *f;
+caddr_t p;
+int flags;
+char *s;
+{
+ regdump(f);
+ printf("proc %x flags %x type %s\n", p, flags, s);
+}
+
+MY_info_done(f, flags)
+struct trapframe *f;
+int flags;
+{
+ regdump(f);
+}
+
+regdump(struct trapframe *f)
+{
+#define R(i) f->r[i]
+ printf("R00-05: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ R(0),R(1),R(2),R(3),R(4),R(5));
+ printf("R06-11: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ R(6),R(7),R(8),R(9),R(10),R(11));
+ printf("R12-17: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ R(12),R(13),R(14),R(15),R(16),R(17));
+ printf("R18-23: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ R(18),R(19),R(20),R(21),R(22),R(23));
+ printf("R24-29: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ R(24),R(25),R(26),R(27),R(28),R(29));
+ printf("R30-31: 0x%08x 0x%08x\n",R(30),R(31));
+ printf("sxip %x snip %x sfip %x\n", f->sxip, f->snip, f->sfip);
+ if (f->vector == 0x3) { /* print dmt stuff for data access fault */
+ printf("dmt0 %x dmd0 %x dma0 %x\n", f->dmt0, f->dmd0, f->dma0);
+ printf("dmt1 %x dmd1 %x dma1 %x\n", f->dmt1, f->dmd1, f->dma1);
+ printf("dmt2 %x dmd2 %x dma2 %x\n", f->dmt2, f->dmd2, f->dma2);
+ }
+ if (longformat) {
+ printf("fpsr %x", f->fpsr);
+ printf("fpcr %x", f->fpcr);
+ printf("epsr %x", f->epsr);
+ printf("ssbr %x\n", f->ssbr);
+ printf("dmt0 %x", f->dmt0);
+ printf("dmd0 %x", f->dmd0);
+ printf("dma0 %x", f->dma0);
+ printf("dmt1 %x", f->dmt1);
+ printf("dmd1 %x", f->dmd1);
+ printf("dma1 %x", f->dma1);
+ printf("dmt2 %x", f->dmt2);
+ printf("dmd2 %x", f->dmd2);
+ printf("dma2 %x\n", f->dma2);
+ printf("fpecr %x", f->fpecr);
+ printf("fphs1 %x", f->fphs1);
+ printf("fpls1 %x", f->fpls1);
+ printf("fphs2 %x", f->fphs2);
+ printf("fpls2 %x", f->fpls2);
+ printf("fppt %x", f->fppt);
+ printf("fprh %x", f->fprh);
+ printf("fprl %x", f->fprl);
+ printf("fpit %x\n", f->fpit);
+ printf("vector %x", f->vector);
+ printf("mask %x", f->mask);
+ printf("mode %x", f->mode);
+ printf("scratch1 %x", f->scratch1);
+ printf("pad %x\n", f->pad);
+ }
+}
+
+#if DDB
+inline int
+db_splhigh(void)
+{
+ return (db_spln(6));
+}
+
+inline int
+db_splx(int s)
+{
+ return (db_spln(s));
+}
+#endif /* DDB */