__setup("nohlt", nohlt_setup);
__setup("hlt", hlt_setup);
-/*
- * The following aren't currently used.
- */
-void (*pm_idle)(void);
-void (*pm_power_off)(void);
-
/*
* This is our default idle handler. We need to disable
* interrupts here to ensure we don't miss a wakeup call.
*/
-void default_idle(void)
-{
- local_irq_disable();
- if (!need_resched() && !hlt_counter)
- local_irq_enable();
-}
-
-/*
- * The idle thread. We try to conserve power, while trying to keep
- * overall latency low. The architecture specific idle is passed
- * a value to indicate the level of "idleness" of the system.
- */
void cpu_idle(void)
{
/* endless idle loop with no priority at all */
- preempt_disable();
while (1) {
- void (*idle)(void) = pm_idle;
- if (!idle)
- idle = default_idle;
- leds_event(led_idle_start);
while (!need_resched())
- idle();
- leds_event(led_idle_end);
+ cpu_relax();
+ preempt_enable_no_resched();
schedule();
+ preempt_disable();
}
}
__setup("reboot=", reboot_setup);
+/* ARM26 cant do these but we still need to define them. */
void machine_halt(void)
{
- leds_event(led_halted);
}
-
-EXPORT_SYMBOL(machine_halt);
-
void machine_power_off(void)
{
- leds_event(led_halted);
- if (pm_power_off)
- pm_power_off();
}
-EXPORT_SYMBOL(machine_power_off);
-
void machine_restart(char * __unused)
{
/*
while (1);
}
-EXPORT_SYMBOL(machine_restart);
-
void show_regs(struct pt_regs * regs)
{
unsigned long flags;
memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
memset(&thread->fpstate, 0, sizeof(union fp_state));
- current->used_math = 0;
+ clear_used_math();
}
void release_thread(struct task_struct *dead_task)
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
int
-copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
+copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
unsigned long unused, struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *thread = p->thread_info;
- struct pt_regs *childregs;
+ struct thread_info *thread = task_thread_info(p);
+ struct pt_regs *childregs = task_pt_regs(p);
- childregs = __get_user_regs(thread);
*childregs = *regs;
childregs->ARM_r0 = 0;
- childregs->ARM_sp = esp;
+ childregs->ARM_sp = stack_start;
memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
thread->cpu_context.sp = (unsigned long)childregs;
int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
{
struct thread_info *thread = current_thread_info();
- int used_math = current->used_math;
+ int used_math = !!used_math();
if (used_math)
memcpy(fp, &thread->fpstate.soft, sizeof (*fp));
}
/*
- * 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.
- * FIXME - taken from arm32
+ * Shuffle the argument into the correct register before calling the
+ * thread function. r1 is the thread argument, r2 is the pointer to
+ * the thread function, and r3 points to the exit function.
+ * FIXME - make sure this is right - the older code used to zero fp
+ * and cause the parent to call sys_exit (do_exit in this version)
+ */
+extern void kernel_thread_helper(void);
+
+asm( ".section .text\n"
+" .align\n"
+" .type kernel_thread_helper, #function\n"
+"kernel_thread_helper:\n"
+" mov r0, r1\n"
+" mov lr, r3\n"
+" mov pc, r2\n"
+" .size kernel_thread_helper, . - kernel_thread_helper\n"
+" .previous");
+
+/*
+ * Create a kernel thread.
*/
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
- register unsigned int r0 asm("r0") = flags | CLONE_VM | CLONE_UNTRACED;
- register unsigned int r1 asm("r1") = 0;
- register pid_t __ret asm("r0");
-
- __asm__ __volatile__(
- __syscall(clone)" @ kernel_thread sys_clone \n\
- movs %0, r0 @ if we are the child \n\
- bne 1f \n\
- mov fp, #0 @ ensure that fp is zero \n\
- mov r0, %4 \n\
- mov lr, pc \n\
- mov pc, %3 \n\
- b sys_exit \n\
-1: "
- : "=r" (__ret)
- : "0" (r0), "r" (r1), "r" (fn), "r" (arg)
- : "lr");
- return __ret;
+ struct pt_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+
+ regs.ARM_r1 = (unsigned long)arg;
+ regs.ARM_r2 = (unsigned long)fn;
+ regs.ARM_r3 = (unsigned long)do_exit;
+ regs.ARM_pc = (unsigned long)kernel_thread_helper | MODE_SVC26;
+
+ return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
}
+EXPORT_SYMBOL(kernel_thread);
-/*
- * These bracket the sleeping functions..
- */
-#define first_sched ((unsigned long) scheduling_functions_start_here)
-#define last_sched ((unsigned long) scheduling_functions_end_here)
unsigned long get_wchan(struct task_struct *p)
{
if (fp < stack_page || fp > 4092+stack_page)
return 0;
lr = pc_pointer (((unsigned long *)fp)[-1]);
- if (lr < first_sched || lr > last_sched)
+ if (!in_sched_functions(lr))
return lr;
fp = *(unsigned long *) (fp - 12);
} while (count ++ < 16);