patch-2.1.44 linux/arch/sparc64/kernel/process.c
Next file: linux/arch/sparc64/kernel/ptrace.c
Previous file: linux/arch/sparc64/kernel/irq.c
Back to the patch index
Back to the overall index
- Lines: 430
- Date:
Mon Jul 7 08:18:54 1997
- Orig file:
v2.1.43/linux/arch/sparc64/kernel/process.c
- Orig date:
Mon Jun 16 16:35:54 1997
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $
+/* $Id: process.c,v 1.26 1997/07/01 21:15:07 jj Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -137,7 +137,7 @@
prom_reboot(cmd);
if (*reboot_command)
prom_reboot(reboot_command);
- prom_feval ("reset");
+ prom_reboot("");
panic("Reboot failed!");
}
@@ -146,8 +146,55 @@
machine_halt();
}
-void show_regwindow(struct reg_window *rw)
+static void show_regwindow32(struct pt_regs *regs)
{
+ struct reg_window32 *rw;
+ struct reg_window32 r_w;
+ unsigned long old_fs;
+
+ __asm__ __volatile__ ("flushw");
+ rw = (struct reg_window32 *)((long)(unsigned)regs->u_regs[14]);
+ old_fs = get_fs();
+ set_fs (USER_DS);
+ if (copy_from_user (&r_w, rw, sizeof(r_w))) {
+ set_fs (old_fs);
+ return;
+ }
+ rw = &r_w;
+ set_fs (old_fs);
+ printk("l0: %016x l1: %016x l2: %016x l3: %016x\n"
+ "l4: %016x l5: %016x l6: %016x l7: %016x\n",
+ rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
+ rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
+ printk("i0: %016x i1: %016x i2: %016x i3: %016x\n"
+ "i4: %016x i5: %016x i6: %016x i7: %016x\n",
+ rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
+ rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
+}
+
+static void show_regwindow(struct pt_regs *regs)
+{
+ struct reg_window *rw;
+ struct reg_window r_w;
+ unsigned long old_fs;
+
+ if ((regs->tstate & TSTATE_PRIV) || !(current->tss.flags & SPARC_FLAG_32BIT)) {
+ __asm__ __volatile__ ("flushw");
+ rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
+ if (!(regs->tstate & TSTATE_PRIV)) {
+ old_fs = get_fs();
+ set_fs (USER_DS);
+ if (copy_from_user (&r_w, rw, sizeof(r_w))) {
+ set_fs (old_fs);
+ return;
+ }
+ rw = &r_w;
+ set_fs (old_fs);
+ }
+ } else {
+ show_regwindow32(regs);
+ return;
+ }
printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n",
rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3]);
printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n",
@@ -158,18 +205,6 @@
rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
}
-void show_regwindow32(struct reg_window32 *rw)
-{
- printk("l0: %08x l1: %08x l2: %08x l3: %08x\n"
- "l4: %08x l5: %08x l6: %08x l7: %08x\n",
- rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
- rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
- printk("i0: %08x i1: %08x i2: %08x i3: %08x\n"
- "i4: %08x i5: %08x i6: %08x i7: %08x\n",
- rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
- rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
-}
-
void show_stackframe(struct sparc_stackf *sf)
{
unsigned long size;
@@ -231,7 +266,7 @@
#if __MPP__
printk("CID: %d\n",mpp_cid());
#endif
- printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %016lx\n", regs->tstate,
+ printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate,
regs->tpc, regs->tnpc, regs->y);
printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
@@ -245,9 +280,7 @@
printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
regs->u_regs[15]);
-#if 0
- show_regwindow((struct reg_window *)(regs->u_regs[14] + STACK_BIAS));
-#endif
+ show_regwindow(regs);
}
void show_regs32(struct pt_regs32 *regs)
@@ -269,7 +302,6 @@
printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n",
regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
regs->u_regs[15]);
- show_regwindow32((struct reg_window32 *)((unsigned long)regs->u_regs[14]));
}
void show_thread(struct thread_struct *tss)
@@ -290,46 +322,22 @@
continue;
printk("reg_window[%d]:\n", i);
printk("stack ptr: 0x%016lx\n", tss->rwbuf_stkptrs[i]);
- show_regwindow(&tss->reg_window[i]);
}
printk("w_saved: 0x%08lx\n", tss->w_saved);
- /* XXX missing: float_regs */
- printk("fsr: 0x%016lx\n", tss->fsr);
-
printk("sstk_info.stack: 0x%016lx\n",
(unsigned long)tss->sstk_info.the_stack);
printk("sstk_info.status: 0x%016lx\n",
(unsigned long)tss->sstk_info.cur_status);
- printk("flags: 0x%016lx\n", tss->flags);
- printk("current_ds: 0x%016x\n", tss->current_ds);
+ printk("flags: 0x%08x\n", tss->flags);
+ printk("current_ds: 0x%016lx\n", tss->current_ds);
/* XXX missing: core_exec */
}
-/*
- * Free current thread data structures etc..
- */
+/* Free current thread data structures etc.. */
void exit_thread(void)
{
-#ifndef __SMP__
- if(last_task_used_math == current) {
-#else
- if(current->flags & PF_USEDFPU) {
-#endif
- fprs_write(FPRS_FEF);
- if(current->tss.flags & SPARC_FLAG_32BIT)
- fpsave32((unsigned long *)¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- else
- fpsave((unsigned long *)¤t->tss.float_regs[0],
- ¤t->tss.fsr);
-#ifndef __SMP__
- last_task_used_math = NULL;
-#else
- current->flags &= ~PF_USEDFPU;
-#endif
- }
}
void flush_thread(void)
@@ -338,28 +346,12 @@
current->tss.sstk_info.cur_status = 0;
current->tss.sstk_info.the_stack = 0;
- /* No new signal delivery by default */
+ /* No new signal delivery by default. */
current->tss.new_signal = 0;
-#ifndef __SMP__
- if(last_task_used_math == current) {
-#else
- if(current->flags & PF_USEDFPU) {
-#endif
- fprs_write(FPRS_FEF);
- if(current->tss.flags & SPARC_FLAG_32BIT)
- fpsave32((unsigned long *)¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- else
- fpsave((unsigned long *)¤t->tss.float_regs[0],
- ¤t->tss.fsr);
-#ifndef __SMP__
- last_task_used_math = NULL;
-#else
- current->flags &= ~PF_USEDFPU;
-#endif
- }
+ current->flags &= ~PF_USEDFPU;
/* Now, this task is no longer a kernel thread. */
+ current->tss.current_ds = USER_DS;
if(current->tss.flags & SPARC_FLAG_KTHREAD) {
current->tss.flags &= ~SPARC_FLAG_KTHREAD;
@@ -368,56 +360,9 @@
*/
get_mmu_context(current);
}
- current->tss.current_ds = USER_DS;
- spitfire_set_secondary_context (current->mm->context);
-}
-
-static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
-{
- __asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
- "ldd\t[%1 + 0x08], %%g4\n\t"
- "ldd\t[%1 + 0x10], %%o4\n\t"
- "std\t%%g2, [%0 + 0x00]\n\t"
- "std\t%%g4, [%0 + 0x08]\n\t"
- "std\t%%o4, [%0 + 0x10]\n\t"
- "ldd\t[%1 + 0x18], %%g2\n\t"
- "ldd\t[%1 + 0x20], %%g4\n\t"
- "ldd\t[%1 + 0x28], %%o4\n\t"
- "std\t%%g2, [%0 + 0x18]\n\t"
- "std\t%%g4, [%0 + 0x20]\n\t"
- "std\t%%o4, [%0 + 0x28]\n\t"
- "ldd\t[%1 + 0x30], %%g2\n\t"
- "ldd\t[%1 + 0x38], %%g4\n\t"
- "ldd\t[%1 + 0x40], %%o4\n\t"
- "std\t%%g2, [%0 + 0x30]\n\t"
- "std\t%%g4, [%0 + 0x38]\n\t"
- "ldd\t[%1 + 0x48], %%g2\n\t"
- "std\t%%o4, [%0 + 0x40]\n\t"
- "std\t%%g2, [%0 + 0x48]\n\t" : :
- "r" (dst), "r" (src) :
- "g2", "g3", "g4", "g5", "o4", "o5");
-}
-
-static __inline__ void copy_regwin(struct reg_window *dst, struct reg_window *src)
-{
- __asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
- "ldd\t[%1 + 0x08], %%g4\n\t"
- "ldd\t[%1 + 0x10], %%o4\n\t"
- "std\t%%g2, [%0 + 0x00]\n\t"
- "std\t%%g4, [%0 + 0x08]\n\t"
- "std\t%%o4, [%0 + 0x10]\n\t"
- "ldd\t[%1 + 0x18], %%g2\n\t"
- "ldd\t[%1 + 0x20], %%g4\n\t"
- "ldd\t[%1 + 0x28], %%o4\n\t"
- "std\t%%g2, [%0 + 0x18]\n\t"
- "std\t%%g4, [%0 + 0x20]\n\t"
- "std\t%%o4, [%0 + 0x28]\n\t"
- "ldd\t[%1 + 0x30], %%g2\n\t"
- "ldd\t[%1 + 0x38], %%g4\n\t"
- "std\t%%g2, [%0 + 0x30]\n\t"
- "std\t%%g4, [%0 + 0x38]\n\t" : :
- "r" (dst), "r" (src) :
- "g2", "g3", "g4", "g5", "o4", "o5");
+ current->tss.ctx = current->mm->context & 0x1fff;
+ spitfire_set_secondary_context (current->tss.ctx);
+ __asm__ __volatile__("flush %g6");
}
static __inline__ struct sparc_stackf *
@@ -461,16 +406,19 @@
flush_user_windows();
if((window = tp->w_saved) != 0) {
int winsize = REGWIN_SZ;
+ int bias = 0;
#ifdef DEBUG_WINFIXUPS
printk("sus(%d", (int)window);
#endif
if(tp->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
+ else
+ bias = STACK_BIAS;
window -= 1;
do {
- unsigned long sp = tp->rwbuf_stkptrs[window];
+ unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
struct reg_window *rwin = &tp->reg_window[window];
if(!copy_to_user((char *)sp, rwin, winsize)) {
@@ -489,9 +437,12 @@
struct thread_struct *tp = ¤t->tss;
unsigned long window;
int winsize = REGWIN_SZ;
+ int bias = 0;
if(tp->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
+ else
+ bias = STACK_BIAS;
flush_user_windows();
window = tp->w_saved;
#ifdef DEBUG_WINFIXUPS
@@ -500,7 +451,7 @@
if(window != 0) {
window -= 1;
do {
- unsigned long sp = tp->rwbuf_stkptrs[window];
+ unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
struct reg_window *rwin = &tp->reg_window[window];
if(copy_to_user((char *)sp, rwin, winsize))
@@ -530,53 +481,37 @@
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct task_struct *p, struct pt_regs *regs)
{
- struct pt_regs *childregs;
- struct reg_window *new_stack, *old_stack;
unsigned long stack_offset;
+ char *child_trap_frame;
+ int tframe_size;
-#ifndef __SMP__
- if(last_task_used_math == current) {
-#else
- if(current->flags & PF_USEDFPU) {
-#endif
- fprs_write(FPRS_FEF);
- fpsave((unsigned long *)&p->tss.float_regs[0], &p->tss.fsr);
-#ifdef __SMP__
- current->flags &= ~PF_USEDFPU;
+#if 0 /* Now all syscall entries flip off the fpu. */
+ if(regs->tstate & TSTATE_PRIV)
+ regs->fprs = 0;
#endif
- }
-
/* Calculate offset to stack_frame & pt_regs */
- stack_offset = ((PAGE_SIZE<<1) - TRACEREG_SZ);
-
- if(regs->tstate & TSTATE_PRIV)
- stack_offset -= REGWIN_SZ;
-
- childregs = ((struct pt_regs *) (((unsigned long)p) + stack_offset));
- *childregs = *regs;
- new_stack = (((struct reg_window *) childregs) - 1);
- old_stack = (((struct reg_window *) regs) - 1);
- *new_stack = *old_stack;
-
- p->tss.ksp = ((unsigned long) new_stack) - STACK_BIAS;
+ stack_offset = (((PAGE_SIZE << 1) -
+ ((sizeof(unsigned int)*64) + (2*sizeof(unsigned long)))) &
+ ~(64 - 1)) - (TRACEREG_SZ+REGWIN_SZ);
+ tframe_size = (TRACEREG_SZ + REGWIN_SZ) +
+ (sizeof(unsigned int) * 64) + (2 * sizeof(unsigned long));
+ child_trap_frame = ((char *)p) + stack_offset;
+ memcpy(child_trap_frame, (((struct reg_window *)regs)-1), tframe_size);
+ p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
p->tss.kpc = ((unsigned long) ret_from_syscall) - 0x8;
- p->tss.kregs = childregs;
-
- /* Don't look... */
+ p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
p->tss.cwp = regs->u_regs[UREG_G0];
-
- /* tss.wstate was copied by do_fork() */
-
if(regs->tstate & TSTATE_PRIV) {
- childregs->u_regs[UREG_FP] = p->tss.ksp;
+ p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
p->tss.flags |= SPARC_FLAG_KTHREAD;
p->tss.current_ds = KERNEL_DS;
- childregs->u_regs[UREG_G6] = (unsigned long) p;
+ p->tss.ctx = 0;
+ p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
} else {
- childregs->u_regs[UREG_FP] = sp;
+ p->tss.kregs->u_regs[UREG_FP] = sp;
p->tss.flags &= ~SPARC_FLAG_KTHREAD;
p->tss.current_ds = USER_DS;
-
+ p->tss.ctx = (p->mm->context & 0x1fff);
#if 0
if (sp != regs->u_regs[UREG_FP]) {
struct sparc_stackf *childstack;
@@ -588,39 +523,20 @@
*/
childstack = (struct sparc_stackf *)sp;
parentstack = (struct sparc_stackf *)regs->u_regs[UREG_FP];
-
-#if 0
- printk("clone: parent stack:\n");
- show_stackframe(parentstack);
-#endif
-
childstack = clone_stackframe(childstack, parentstack);
if (!childstack)
return -EFAULT;
-
-#if 0
- printk("clone: child stack:\n");
- show_stackframe(childstack);
-#endif
-
childregs->u_regs[UREG_FP] = (unsigned long)childstack;
}
#endif
}
/* Set the return value for the child. */
- childregs->u_regs[UREG_I0] = current->pid;
- childregs->u_regs[UREG_I1] = 1;
+ p->tss.kregs->u_regs[UREG_I0] = current->pid;
+ p->tss.kregs->u_regs[UREG_I1] = 1;
- /* Set the return value for the parent. */
+ /* Set the second return value for the parent. */
regs->u_regs[UREG_I1] = 0;
-#if 0
- printk("CHILD register dump\n");
- show_regs(childregs);
- show_regwindow(new_stack);
- while(1)
- barrier();
-#endif
return 0;
}
@@ -682,5 +598,9 @@
error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1],
(char **) regs->u_regs[base + UREG_I2], regs);
putname(filename);
+ if(!error) {
+ fprs_write(0);
+ regs->fprs = 0;
+ }
return error;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov