- patches.apparmor/remove_suid_new_case_in_2.6.22.diff: Merge fix.
[linux-flexiantxendom0-3.2.10.git] / arch / sh / kernel / process.c
index e760736..a11e2aa 100644 (file)
@@ -7,7 +7,7 @@
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *                  Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
- *                  Copyright (C) 2002 - 2006  Paul Mundt
+ *                  Copyright (C) 2002 - 2007  Paul Mundt
  */
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
+#include <linux/kdebug.h>
+#include <linux/tick.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);
@@ -40,16 +42,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;
@@ -57,12 +82,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();
        }
 }
 
@@ -299,7 +327,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
        ctrl_outl(0, UBC_BAMRA);
 
        if (current_cpu_data.type == CPU_SH7729 ||
-           current_cpu_data.type == CPU_SH7710) {
+           current_cpu_data.type == CPU_SH7710 ||
+           current_cpu_data.type == CPU_SH7712) {
                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
        } else {
@@ -493,7 +522,11 @@ 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, "debug trap", regs, 0, regs->tra & 0xff,
+                      SIGTRAP) == NOTIFY_STOP)
+               return;
 
        force_sig(SIGTRAP, current);
 }
@@ -508,7 +541,11 @@ 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, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
+                      SIGTRAP) == NOTIFY_STOP)
+               return;
 
 #ifdef CONFIG_BUG
        if (__kernel_text_address(instruction_pointer(regs))) {