aboutsummaryrefslogtreecommitdiff
path: root/sys/powerpc/aim/machdep.c
diff options
context:
space:
mode:
authorPeter Grehan <grehan@FreeBSD.org>2002-09-19 04:30:43 +0000
committerPeter Grehan <grehan@FreeBSD.org>2002-09-19 04:30:43 +0000
commit81a6d01d1c2dbfd022ddcff4a790f93cebe25a55 (patch)
tree8d9032ca261d0692d23244031689e8751050cd0a /sys/powerpc/aim/machdep.c
parent3f3331903d5a20d19a2bf2d6519f729d34d42aec (diff)
downloadsrc-81a6d01d1c2dbfd022ddcff4a790f93cebe25a55.tar.gz
src-81a6d01d1c2dbfd022ddcff4a790f93cebe25a55.zip
- implemented sendsig/sigreturn
- sysctl for cacheline size, required by libc/rtld - init'd more exception vectors - fixed problem with register overwrite in exec_setregs - removed redundant NetBSD code Approved by: benno
Notes
Notes: svn path=/head/; revision=103600
Diffstat (limited to 'sys/powerpc/aim/machdep.c')
-rw-r--r--sys/powerpc/aim/machdep.c507
1 files changed, 169 insertions, 338 deletions
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 8d10987e14f8..3c44ba975d5a 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -88,6 +88,7 @@ static const char rcsid[] =
#include <sys/linker.h>
#include <sys/cons.h>
#include <sys/ucontext.h>
+#include <sys/sysent.h>
#include <net/netisr.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@@ -129,6 +130,10 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
static char model[128];
SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
+static int cacheline_size = CACHELINESIZE;
+SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
+ CTLFLAG_RD, &cacheline_size, 0, "");
+
char bootpath[256];
#ifdef DDB
@@ -146,9 +151,7 @@ int restore_ofw_mapping(void);
void install_extint(void (*)(void));
-#ifdef COMPAT_43
-void osendsig(sig_t, int, sigset_t *, u_long);
-#endif
+int setfault(faultbuf); /* defined in locore.S */
static int
sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
@@ -382,12 +385,15 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
/*
* XXX: Initialize the interrupt tables.
*/
- bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
- bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_ALI, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
/*
* Start initializing proc0 and thread0.
@@ -412,6 +418,11 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
mutex_init();
/*
+ * Make sure translation has been enabled
+ */
+ mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
+
+ /*
* Initialise virtual memory.
*/
pmap_bootstrap(startkernel, endkernel);
@@ -437,307 +448,6 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
msgbufinit(msgbufp, MSGBUF_SIZE);
}
-#if 0 /* XXX: Old powerpc_init */
-void
-powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
-{
- unsigned int exc, scratch;
- struct mem_region *allmem, *availmem, *mp;
- struct pcpu *pcpup;
-
- /*
- * Set up BAT0 to only map the lowest 256 MB area
- */
- battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
- battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
-
- /*
- * Map PCI memory space.
- */
- battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW);
- battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
-
- battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW);
- battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
-
- battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW);
- battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
-
- /*
- * Map obio devices.
- */
- battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW);
- battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
-
- /*
- * Now setup fixed bat registers
- *
- * Note that we still run in real mode, and the BAT
- * registers were cleared above.
- */
- /* BAT0 used for initial 256 MB segment */
- __asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;"
- "mtdbatl 0,%0; mtdbatu 0,%1;"
- :: "r"(battable[0].batl), "r"(battable[0].batu));
- /*
- * Set up battable to map all RAM regions.
- * This is here because mem_regions() call needs bat0 set up.
- */
- mem_regions(&allmem, &availmem);
-
- /* Calculate the physical memory in the machine */
- for (mp = allmem; mp->size; mp++)
- physmem += btoc(mp->size);
-
- for (mp = allmem; mp->size; mp++) {
- vm_offset_t pa = mp->start & 0xf0000000;
- vm_offset_t end = mp->start + mp->size;
-
- do {
- u_int n = pa >> 28;
-
- battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
- battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
- pa += 0x10000000;
- } while (pa < end);
- }
-
- chosen = OF_finddevice("/chosen");
- save_ofw_mapping();
-
- pmap_setavailmem(startkernel, endkernel);
-
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
-
- proc0uarea = (struct user *)pmap_steal_memory(UAREA_PAGES * PAGE_SIZE);
- proc0kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE);
- proc0.p_uarea = proc0uarea;
- thread0.td_kstack = proc0kstack;
- thread0.td_pcb = (struct pcb *)
- (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
-
- pcpup = pmap_steal_memory(round_page(sizeof(struct pcpu)));
-
- /*
- * XXX: Pass 0 as CPU id. This is bad. We need to work out
- * XXX: which CPU we are somehow.
- */
- pcpu_init(pcpup, 0, sizeof(struct pcpu));
- __asm ("mtsprg 0, %0" :: "r"(pcpup));
-
- /* Init basic tunables, hz etc */
- init_param1();
- init_param2(physmem);
-
- PCPU_SET(curthread, &thread0);
-
-/* XXX: NetBSDism I _think_. Not sure yet. */
-#if 0
- curpm = PCPU_GET(curpcb)->pcb_pmreal = PCPU_GET(curpcb)->pcb_pm = kernel_pmap;
-#endif
-
- mutex_init();
-
- /*
- * Initialise console.
- */
- cninit();
-
-#ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */
- OF_set_callback(callback);
-#endif
-
- /*
- * Set up trap vectors
- */
- for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
- switch (exc) {
- default:
- bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
- break;
- case EXC_DECR:
- bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
- break;
-#if 0 /* XXX: Not enabling these traps yet. */
- case EXC_EXI:
- /*
- * This one is (potentially) installed during autoconf
- */
- break;
- case EXC_ALI:
- bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
- break;
- case EXC_DSI:
- bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
- break;
- case EXC_ISI:
- bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
- break;
- case EXC_IMISS:
- bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
- break;
- case EXC_DLMISS:
- bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
- break;
- case EXC_DSMISS:
- bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
- break;
-#if defined(DDB) || defined(IPKDB)
- case EXC_TRC:
- case EXC_PGM:
- case EXC_BPT:
-#if defined(DDB)
- bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
-#else
- bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize);
-#endif
- break;
-#endif /* DDB || IPKDB */
-#endif
- }
- }
-
-#if 0 /* XXX: coming soon... */
- /*
- * external interrupt handler install
- */
- install_extint(ext_intr);
-#endif
-
- __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
-
- /*
- * Now enable translation (and machine checks/recoverable interrupts).
- */
- __asm ("mfmsr %0" : "=r"(scratch));
- scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI;
- __asm ("mtmsr %0" :: "r"(scratch));
-
- ofmsr &= ~PSL_IP;
-
- /*
- * Parse arg string.
- */
-#ifdef DDB
- bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym));
- bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym));
- if (startsym == NULL || endsym == NULL)
- startsym = endsym = NULL;
-#endif
-
- strcpy(bootpath, args);
- args = bootpath;
- while (*++args && *args != ' ');
- if (*args) {
- *args++ = 0;
- while (*args) {
- switch (*args++) {
- case 'a':
- boothowto |= RB_ASKNAME;
- break;
- case 's':
- boothowto |= RB_SINGLE;
- break;
- case 'd':
- boothowto |= RB_KDB;
- break;
- case 'v':
- boothowto |= RB_VERBOSE;
- break;
- }
- }
- }
-
-#ifdef DDB
- ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
-#endif
-#ifdef IPKDB
- /*
- * Now trap to IPKDB
- */
- ipkdb_init();
- if (boothowto & RB_KDB)
- ipkdb_connect(0);
-#endif
-
- /*
- * Set the page size.
- */
-#if 0
- vm_set_page_size();
-#endif
-
- /*
- * Initialize pmap module.
- */
- pmap_bootstrap();
-
- restore_ofw_mapping();
-
- PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */
-
- /* setup proc 0's pcb */
- thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
- thread0.td_frame = &proc0_tf;
-}
-#endif
-
-static int N_mapping;
-static struct {
- vm_offset_t va;
- int len;
- vm_offset_t pa;
- int mode;
-} ofw_mapping[256];
-
-int
-save_ofw_mapping()
-{
- int mmui, mmu;
-
- OF_getprop(chosen, "mmu", &mmui, 4);
- mmu = OF_instance_to_package(mmui);
-
- bzero(ofw_mapping, sizeof(ofw_mapping));
-
- N_mapping =
- OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping));
- N_mapping /= sizeof(ofw_mapping[0]);
-
- return 0;
-}
-
-int
-restore_ofw_mapping()
-{
- int i;
- struct vm_page pg;
-
- pmap_pinit(&ofw_pmap);
-
- ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
-
- for (i = 0; i < N_mapping; i++) {
- vm_offset_t pa = ofw_mapping[i].pa;
- vm_offset_t va = ofw_mapping[i].va;
- int size = ofw_mapping[i].len;
-
- if (va < 0x80000000) /* XXX */
- continue;
-
- while (size > 0) {
- pg.phys_addr = pa;
- pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL,
- VM_PROT_ALL);
- pa += PAGE_SIZE;
- va += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- }
-
- return 0;
-}
-
void
bzero(void *buf, size_t len)
{
@@ -775,34 +485,117 @@ bzero(void *buf, size_t len)
}
}
-#if 0
void
-delay(unsigned n)
+sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
- u_long tb;
+ struct trapframe *tf;
+ struct sigframe *sfp;
+ struct sigacts *psp;
+ struct sigframe sf;
+ struct thread *td;
+ struct proc *p;
+ int oonstack, rndfsize;
- do {
- __asm __volatile("mftb %0" : "=r" (tb));
- } while (n > (int)(tb & 0xffffffff));
-}
-#endif
+ td = curthread;
+ p = td->td_proc;
+ psp = p->p_sigacts;
+ tf = td->td_frame;
+ oonstack = sigonstack(tf->fixreg[1]);
-#ifdef COMPAT_43
-void
-osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
-{
+ rndfsize = ((sizeof(sf) + 15) / 16) * 16;
- /* XXX: To be done */
- return;
-}
-#endif
+ CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+ catcher, sig);
-void
-sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
-{
+ /*
+ * Save user context
+ */
+ memset(&sf, 0, sizeof(sf));
+ sf.sf_uc.uc_sigmask = *mask;
+ sf.sf_uc.uc_stack = p->p_sigstk;
+ sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
+ ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+
+ sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+ memcpy(&sf.sf_uc.uc_mcontext.mc_frame, tf, sizeof(struct trapframe));
+
+ /*
+ * Allocate and validate space for the signal handler context.
+ */
+ if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp +
+ p->p_sigstk.ss_size - rndfsize);
+ } else {
+ sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
+ }
+ PROC_UNLOCK(p);
+
+ /*
+ * Translate the signal if appropriate (Linux emu ?)
+ */
+ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
+ sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+ /*
+ * Save the floating-point state, if necessary, then copy it.
+ */
+ /* XXX */
+
+ /*
+ * Set up the registers to return to sigcode.
+ *
+ * r1/sp - sigframe ptr
+ * lr - sig function, dispatched to by blrl in trampoline
+ * r3 - sig number
+ * r4 - SIGINFO ? &siginfo : exception code
+ * r5 - user context
+ * srr0 - trampoline function addr
+ */
+ tf->lr = (register_t)catcher;
+ tf->fixreg[1] = (register_t)sfp;
+ tf->fixreg[FIRSTARG] = sig;
+ tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
+
+ PROC_LOCK(p);
+ if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ /*
+ * Signal handler installed with SA_SIGINFO.
+ */
+ tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
+
+ /*
+ * Fill siginfo structure.
+ */
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_code = code;
+ sf.sf_si.si_addr = (void *)tf->srr0;
+ sf.sf_si.si_pid = p->p_pid;
+ sf.sf_si.si_uid = p->p_ucred->cr_uid;
+ } else {
+ /* Old FreeBSD-style arguments. */
+ tf->fixreg[FIRSTARG+1] = code;
+ }
+ PROC_UNLOCK(p);
+
+ tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
+
+ /*
+ * copy the frame out to userland.
+ */
+ if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) {
+ /*
+ * Process has trashed its stack. Kill it.
+ */
+ CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
+ tf->srr0, tf->fixreg[1]);
- /* XXX: To be done */
- return;
+ PROC_LOCK(p);
}
/*
@@ -820,9 +613,47 @@ osigreturn(struct thread *td, struct osigreturn_args *uap)
int
sigreturn(struct thread *td, struct sigreturn_args *uap)
{
+ struct trapframe *tf;
+ struct proc *p;
+ ucontext_t uc;
- /* XXX: To be done */
- return(ENOSYS);
+ CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
+
+ if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
+ CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
+ return (EFAULT);
+ }
+
+ /*
+ * Don't let the user set privileged MSR bits
+ */
+ tf = td->td_frame;
+ if ((uc.uc_mcontext.mc_frame.srr1 & PSL_USERSTATIC) !=
+ (tf->srr1 & PSL_USERSTATIC)) {
+ return (EINVAL);
+ }
+
+ /*
+ * Restore the user-supplied context
+ */
+ memcpy(tf, &uc.uc_mcontext.mc_frame, sizeof(struct trapframe));
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ p->p_sigmask = uc.uc_sigmask;
+ SIG_CANTMASK(p->p_sigmask);
+ signotify(p);
+ PROC_UNLOCK(p);
+
+ /*
+ * Restore FP state
+ */
+ /* XXX */
+
+ CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
+ td, tf->srr0, tf->fixreg[1]);
+
+ return (EJUSTRETURN);
}
void
@@ -873,6 +704,14 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
* XXX We have to set both regs and retval here due to different
* XXX calling convention in trap.c and init_main.c.
*/
+ /*
+ * XXX PG: these get overwritten in the syscall return code.
+ * execve() should return EJUSTRETURN, like it does on NetBSD.
+ * Emulate by setting the syscall return value cells. The
+ * registers still have to be set for init's fork trampoline.
+ */
+ td->td_retval[0] = arginfo.ps_nargvstr;
+ td->td_retval[1] = (register_t)arginfo.ps_argvstr;
tf->fixreg[3] = arginfo.ps_nargvstr;
tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
tf->fixreg[5] = (register_t)arginfo.ps_envstr;
@@ -953,14 +792,6 @@ ptrace_single_step(struct thread *td)
return (ENOSYS);
}
-int
-ptrace_clear_single_step(struct thread *td)
-{
-
- /* XXX: coming soon... */
- return (ENOSYS);
-}
-
/*
* Initialise a struct pcpu.
*/