]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sh/kernel/process.c
Merge branch 'ucc_geth' of master.kernel.org:/pub/scm/linux/kernel/git/leo/fsl-soc...
[linux-2.6-omap-h63xx.git] / arch / sh / kernel / process.c
index 329b3f3051de9d53bb5b58b7418e595d11d74e09..15ae322dbd741a594529835c2c543987125d37f9 100644 (file)
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
 #include <asm/ubc.h>
 
 static int hlt_counter;
 int ubc_usercnt = 0;
 
-#define HARD_IDLE_TIMEOUT (HZ / 3)
-
 void (*pm_idle)(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -41,16 +44,39 @@ void enable_hlt(void)
 }
 EXPORT_SYMBOL(enable_hlt);
 
+static int __init nohlt_setup(char *__unused)
+{
+       hlt_counter = 1;
+       return 1;
+}
+__setup("nohlt", nohlt_setup);
+
+static int __init hlt_setup(char *__unused)
+{
+       hlt_counter = 0;
+       return 1;
+}
+__setup("hlt", hlt_setup);
+
 void default_idle(void)
 {
-       if (!hlt_counter)
-               cpu_sleep();
-       else
-               cpu_relax();
+       if (!hlt_counter) {
+               clear_thread_flag(TIF_POLLING_NRFLAG);
+               smp_mb__after_clear_bit();
+               set_bl_bit();
+               while (!need_resched())
+                       cpu_sleep();
+               clear_bl_bit();
+               set_thread_flag(TIF_POLLING_NRFLAG);
+       } else
+               while (!need_resched())
+                       cpu_relax();
 }
 
 void cpu_idle(void)
 {
+       set_thread_flag(TIF_POLLING_NRFLAG);
+
        /* endless idle loop with no priority at all */
        while (1) {
                void (*idle)(void) = pm_idle;
@@ -58,12 +84,15 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
 
+               tick_nohz_stop_sched_tick();
                while (!need_resched())
                        idle();
+               tick_nohz_restart_sched_tick();
 
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
+               check_pgt_cache();
        }
 }
 
@@ -292,9 +321,7 @@ static void ubc_set_tracing(int asid, unsigned long pc)
        ctrl_outl(pc, UBC_BARA);
 
 #ifdef CONFIG_MMU
-       /* We don't have any ASID settings for the SH-2! */
-       if (current_cpu_data.type != CPU_SH7604)
-               ctrl_outb(asid, UBC_BASRA);
+       ctrl_outb(asid, UBC_BASRA);
 #endif
 
        ctrl_outl(0, UBC_BAMRA);
@@ -378,8 +405,8 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
                        unsigned long r6, unsigned long r7,
                        struct pt_regs __regs)
 {
-       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 #ifdef CONFIG_MMU
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
 #else
        /* fork almost works, enough to trick you into looking elsewhere :-( */
@@ -422,23 +449,20 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *ufilename, char **uargv,
-                         char **uenvp, unsigned long r7,
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+                         char __user * __user *uenvp, unsigned long r7,
                          struct pt_regs __regs)
 {
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int error;
        char *filename;
 
-       filename = getname((char __user *)ufilename);
+       filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename,
-                         (char __user * __user *)uargv,
-                         (char __user * __user *)uenvp,
-                         regs);
+       error = do_execve(filename, uargv, uenvp, regs);
        if (error == 0) {
                task_lock(current);
                current->ptrace &= ~PT_DTRACE;
@@ -451,7 +475,6 @@ out:
 
 unsigned long get_wchan(struct task_struct *p)
 {
-       unsigned long schedule_frame;
        unsigned long pc;
 
        if (!p || p == current || p->state == TASK_RUNNING)
@@ -461,10 +484,13 @@ unsigned long get_wchan(struct task_struct *p)
         * The same comment as on the Alpha applies here, too ...
         */
        pc = thread_saved_pc(p);
+
+#ifdef CONFIG_FRAME_POINTER
        if (in_sched_functions(pc)) {
-               schedule_frame = (unsigned long)p->thread.sp;
+               unsigned long schedule_frame = (unsigned long)p->thread.sp;
                return ((unsigned long *)schedule_frame)[21];
        }
+#endif
 
        return pc;
 }
@@ -495,9 +521,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+       if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
@@ -514,9 +540,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+       if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;