Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
new file mode 100644
index 0000000..9c708c3
--- /dev/null
+++ b/arch/v850/kernel/process.c
@@ -0,0 +1,236 @@
+/*
+ * arch/v850/kernel/process.c -- Arch-dependent process handling
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+extern void ret_from_fork (void);
+
+
+/* The idle loop.  */
+void default_idle (void)
+{
+	while (1) {
+		while (! need_resched ())
+			asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
+		schedule ();
+	}
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle (void)
+{
+	/* endless idle loop with no priority at all */
+	(*idle) ();
+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process (ie the swapper or direct descendants who
+ * haven't done an "execve()") should use this: it will work within a system
+ * call from a "real" process, but the process memory space will not be free'd
+ * until both the parent and the child have exited.
+ */
+int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
+{
+	register mm_segment_t fs = get_fs ();
+	register unsigned long syscall asm (SYSCALL_NUM);
+	register unsigned long arg0 asm (SYSCALL_ARG0);
+	register unsigned long ret asm (SYSCALL_RET);
+
+	set_fs (KERNEL_DS);
+
+	/* Clone this thread.  Note that we don't pass the clone syscall's
+	   second argument -- it's ignored for calls from kernel mode (the
+	   child's SP is always set to the top of the kernel stack).  */
+	arg0 = flags | CLONE_VM;
+	syscall = __NR_clone;
+	asm volatile ("trap " SYSCALL_SHORT_TRAP
+		      : "=r" (ret), "=r" (syscall)
+		      : "1" (syscall), "r" (arg0)
+		      : SYSCALL_SHORT_CLOBBERS);
+
+	if (ret == 0) {
+		/* In child thread, call FN and exit.  */
+		arg0 = (*fn) (arg);
+		syscall = __NR_exit;
+		asm volatile ("trap " SYSCALL_SHORT_TRAP
+			      : "=r" (ret), "=r" (syscall)
+			      : "1" (syscall), "r" (arg0)
+			      : SYSCALL_SHORT_CLOBBERS);
+	}
+
+	/* In parent.  */
+	set_fs (fs);
+
+	return ret;
+}
+
+void flush_thread (void)
+{
+	set_fs (USER_DS);
+}
+
+int copy_thread (int nr, unsigned long clone_flags,
+		 unsigned long stack_start, unsigned long stack_size,
+		 struct task_struct *p, struct pt_regs *regs)
+{
+	/* Start pushing stuff from the top of the child's kernel stack.  */
+	unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE;
+	unsigned long ksp = orig_ksp;
+	/* We push two `state save' stack fames (see entry.S) on the new
+	   kernel stack:
+	     1) The innermost one is what switch_thread would have
+	        pushed, and is used when we context switch to the child
+		thread for the first time.  It's set up to return to
+		ret_from_fork in entry.S.
+	     2) The outermost one (nearest the top) is what a syscall
+	        trap would have pushed, and is set up to return to the
+		same location as the parent thread, but with a return
+		value of 0. */
+	struct pt_regs *child_switch_regs, *child_trap_regs;
+
+	/* Trap frame.  */
+	ksp -= STATE_SAVE_SIZE;
+	child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
+	/* Switch frame.  */
+	ksp -= STATE_SAVE_SIZE;
+	child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
+
+	/* First copy parent's register state to child.  */
+	*child_switch_regs = *regs;
+	*child_trap_regs = *regs;
+
+	/* switch_thread returns to the restored value of the lp
+	   register (r31), so we make that the place where we want to
+	   jump when the child thread begins running.  */
+	child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
+
+	if (regs->kernel_mode)
+		/* Since we're returning to kernel-mode, make sure the child's
+		   stored kernel stack pointer agrees with what the actual
+		   stack pointer will be at that point (the trap return code
+		   always restores the SP, even when returning to
+		   kernel-mode).  */
+		child_trap_regs->gpr[GPR_SP] = orig_ksp;
+	else
+		/* Set the child's user-mode stack-pointer (the name
+		   `stack_start' is a misnomer, it's just the initial SP
+		   value).  */
+		child_trap_regs->gpr[GPR_SP] = stack_start;
+
+	/* Thread state for the child (everything else is on the stack).  */
+	p->thread.ksp = ksp;
+
+	return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread (struct pt_regs *regs, struct user *dump)
+{
+#if 0  /* Later.  XXX */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = regs->gpr[GPR_SP];
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk +
+					  (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+
+	if (dump->start_stack < TASK_SIZE)
+		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+
+	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
+	dump->regs = *regs;
+	dump->u_fpvalid = 0;
+#endif
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
+{
+	char *filename = getname (name);
+	int error = PTR_ERR (filename);
+
+	if (! IS_ERR (filename)) {
+		error = do_execve (filename, argv, envp, regs);
+		putname (filename);
+	}
+
+	return error;
+}
+
+
+/*
+ * These bracket the sleeping functions..
+ */
+#define first_sched	((unsigned long)__sched_text_start)
+#define last_sched	((unsigned long)__sched_text_end)
+
+unsigned long get_wchan (struct task_struct *p)
+{
+#if 0  /* Barf.  Figure out the stack-layout later.  XXX  */
+	unsigned long fp, pc;
+	int count = 0;
+
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	pc = thread_saved_pc (p);
+
+	/* This quite disgusting function walks up the stack, following
+	   saved return address, until it something that's out of bounds
+	   (as defined by `first_sched' and `last_sched').  It then
+	   returns the last PC that was in-bounds.  */
+	do {
+		if (fp < stack_page + sizeof (struct task_struct) ||
+		    fp >= 8184+stack_page)
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		if (pc < first_sched || pc >= last_sched)
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+#endif
+
+	return 0;
+}