patch-2.2.7 linux/arch/sparc/kernel/process.c

Next file: linux/arch/sparc/kernel/setup.c
Previous file: linux/arch/sparc/kernel/irq.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.133 1999/03/24 11:42:30 davem Exp $
+/*  $Id: process.c,v 1.136 1999/04/16 01:20:33 anton Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -205,8 +205,10 @@
 	int cpu = smp_processor_id();
 
 	spin_lock_irqsave(&sparc_backtrace_lock, flags);
-	rw = (struct reg_window *) fp;
-	while(rw) {
+
+	rw = (struct reg_window *)fp;
+        while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
+            !(((unsigned long) rw) & 0x7)) {
 		printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
 		       "FP[%08lx] CALLER[%08lx]\n", cpu,
 		       rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
@@ -218,28 +220,21 @@
 	spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
 }
 
+#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
+#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
+#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp))
+
 void show_backtrace(void)
 {
 	unsigned long fp;
 
-	__asm__ __volatile__(
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"save %%sp, -64, %%sp\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"restore\n\t"
-		"mov %%i6, %0" : "=r" (fp));
+	__SAVE; __SAVE; __SAVE; __SAVE;
+	__SAVE; __SAVE; __SAVE; __SAVE;
+	__RESTORE; __RESTORE; __RESTORE; __RESTORE;
+	__RESTORE; __RESTORE; __RESTORE; __RESTORE;
+
+	__GET_FP(fp);
+
 	__show_backtrace(fp);
 }
 
@@ -381,8 +376,21 @@
 	current->tss.current_ds = USER_DS;
 	if (current->tss.flags & SPARC_FLAG_KTHREAD) {
 		current->tss.flags &= ~SPARC_FLAG_KTHREAD;
-		switch_to_context(current);
+
+		/* We must fixup kregs as well. */
+		current->tss.kregs = (struct pt_regs *)
+			(((unsigned long)current) +
+			 (TASK_UNION_SIZE - TRACEREG_SZ));
 	}
+
+	/* Exec'ing out of a vfork() shared address space is
+	 * tricky on sparc32.  exec_mmap will not set the mmu
+	 * context because it sets the new current->mm after
+	 * calling init_new_context and activate_context is
+	 * a nop on sparc32, so we gotta catch it here.  And
+	 * clone()'s had the same problem.  -DaveM
+	 */
+	switch_to_context(current);
 }
 
 static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
@@ -514,9 +522,11 @@
 	p->tss.kpsr = current->tss.fork_kpsr;
 #endif
 	p->tss.kwim = current->tss.fork_kwim;
-	p->tss.kregs = childregs;
 
 	if(regs->psr & PSR_PS) {
+		extern struct pt_regs fake_swapper_regs;
+
+		p->tss.kregs = &fake_swapper_regs;
 		new_stack = (struct reg_window *)
 			((((unsigned long)p) +
 			  (TASK_UNION_SIZE)) -
@@ -529,6 +539,7 @@
 		       sizeof(struct reg_window));
 		childregs->u_regs[UREG_G6] = (unsigned long) p;
 	} else {
+		p->tss.kregs = childregs;
 		childregs->u_regs[UREG_FP] = sp;
 		p->tss.flags &= ~SPARC_FLAG_KTHREAD;
 		p->tss.current_ds = USER_DS;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)