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

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

diff -u --recursive --new-file v1.3.3/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
@@ -1,7 +1,7 @@
 /*
- *  linux/arch/i386/kernel/process.c
+ *  linux/arch/sparc/kernel/process.c
  *
- *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
 /*
@@ -20,47 +20,43 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 
+#include <asm/oplib.h>
 #include <asm/segment.h>
 #include <asm/system.h>
-
-void ret_from_sys_call(void) { __asm__("nop"); }
+#include <asm/processor.h>
 
 /*
- * The idle loop on a i386..
+ * The idle loop on a sparc... ;)
  */
 asmlinkage int sys_idle(void)
 {
+
 	if (current->pid != 0)
 		return -EPERM;
 
+	printk("in sys_idle...\n");
 	/* Map out the low memory: it's no longer needed */
 	/* Sparc version RSN */
 
 	/* endless idle loop with no priority at all */
 	current->counter = -100;
 	for (;;) {
-		schedule();
+	  printk("calling schedule() aieee!\n");
+	  schedule();
+	  printk("schedule() returned, halting...\n");
+	  halt();
 	}
 }
 
 void hard_reset_now(void)
 {
-	halt();
+	prom_reboot("boot vmlinux");
 }
 
 void show_regs(struct pt_regs * regs)
 {
-        printk("\nSP: %08lx PC: %08lx NPC: %08lx\n", regs->sp, regs->pc,
-	       regs->npc);
-}
-
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-void start_thread(struct pt_regs * regs, unsigned long sp, unsigned long fp)
-{
-	regs->sp = sp;
-	regs->fp = fp;
+        printk("\nFP: %08lx PC: %08lx NPC: %08lx\n", regs->u_regs[14],
+	       regs->pc, regs->npc);
 }
 
 /*
@@ -76,15 +72,60 @@
   halt();
 }
 
-void copy_thread(int nr, unsigned long clone_flags, unsigned long sp, struct task_struct * p, struct pt_regs * regs)
+extern void ret_sys_call(void);
+
+/*
+ * Copy a Sparc thread.  The context of a process on the Sparc is
+ * composed of the following:
+ *  1) status registers  %psr (for condition codes + CWP) and %wim
+ *  2) current register window (in's and global registers)
+ *  3) the current live stack frame, it contains the register
+ *     windows the child may 'restore' into, this is important
+ *  4) kernel stack pointer, user stack pointer (which is %i6)
+ *  5) The pc and npc the child returns to during a switch
+ */
+
+void copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+		 struct task_struct * p, struct pt_regs * regs)
 {
-	struct pt_regs * childregs;
+	struct pt_regs *childregs;
+	unsigned char *old_stack;
+	unsigned char *new_stack;
+	int i;
+
+	/* This process has no context yet. */
+	p->tss.context = -1;
+
+	/* Grrr, Sparc stack alignment restrictions make things difficult. */
+	childregs = ((struct pt_regs *) 
+		     ((p->kernel_stack_page + PAGE_SIZE - 80)&(~7)));
 
-	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
-	p->tss.usp = (unsigned long) childregs;
 	*childregs = *regs;
-	childregs->sp = sp;
-	p->tss.psr = regs->psr; /* for condition codes */
+
+	p->tss.usp = sp;    /* both processes have the same user stack */
+	/* See entry.S */
+
+	/* Allocate new processes kernel stack right under pt_regs.
+	 * Hopefully this should align things the right way.
+	 */
+	p->tss.ksp = (unsigned long) ((p->kernel_stack_page + PAGE_SIZE - 80 - 96)&(~7));
+	new_stack = (unsigned char *) (p->tss.ksp);
+	old_stack = (unsigned char *) (((unsigned long) regs) - 96);
+
+	/* Copy c-stack. */
+	for(i=0; i<96; i++) *new_stack++ = *old_stack++;
+
+	/* These pc values are only used when we switch to the child for
+	 * the first time, it jumps the child to ret_sys_call in entry.S
+	 * so that the child returns from the sys_call just like parent.
+	 */
+	p->tss.pc = (((unsigned long) ret_sys_call) - 8);
+	p->tss.npc = p->tss.pc+4;
+
+	/* Set the return values for both the parent and the child */
+	regs->u_regs[8] = p->pid;
+	childregs->u_regs[8] = 0;
+
 	return;
 }
 
@@ -96,9 +137,9 @@
   return; /* solaris does this enough */
 }
 
-asmlinkage int sys_fork(struct pt_regs regs)
+asmlinkage int sys_fork(struct pt_regs *regs)
 {
-	return do_fork(COPYVM | SIGCHLD, regs.sp, &regs);
+  return do_fork(COPYVM | SIGCHLD, regs->u_regs[14], regs);
 }
 
 /*
@@ -106,6 +147,7 @@
  */
 asmlinkage int sys_execve(struct pt_regs regs)
 {
+  printk("sys_execve()... halting\n");
   halt();
   return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this