X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=arch%2Fblackfin%2Fkernel%2Fprocess.c;h=53c2cd255441ff5a23a55ce9cc8e5702ef1ec966;hb=19d6d7d53c8ff809182a1f092d2c6918146414e9;hp=5bf15125f0d6064fa14f6e5ce4b6cccd4847cd59;hpb=1265edb8fd2869d17128f1d60683dd6f4191d550;p=~andy%2Flinux diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 5bf15125f0d..53c2cd25544 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -31,17 +31,15 @@ #include #include #include -#include #include +#include +#include #include #include #include #include -#define LED_ON 0 -#define LED_OFF 1 - asmlinkage void ret_from_fork(void); /* Points to the SDRAM backup memory for the stack that is currently in @@ -69,65 +67,48 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); -/* - * We are using a different LED from the one used to indicate timer interrupt. - */ -#if defined(CONFIG_BFIN_IDLE_LED) -static inline void leds_switch(int flag) -{ - unsigned short tmp = 0; - - tmp = bfin_read_CONFIG_BFIN_IDLE_LED_PORT(); - SSYNC(); - - if (flag == LED_ON) - tmp &= ~CONFIG_BFIN_IDLE_LED_PIN; /* light on */ - else - tmp |= CONFIG_BFIN_IDLE_LED_PIN; /* light off */ - - bfin_write_CONFIG_BFIN_IDLE_LED_PORT(tmp); - SSYNC(); - -} -#else -static inline void leds_switch(int flag) -{ -} -#endif - /* * The idle loop on BFIN */ #ifdef CONFIG_IDLE_L1 -void default_idle(void)__attribute__((l1_text)); +static void default_idle(void)__attribute__((l1_text)); void cpu_idle(void)__attribute__((l1_text)); #endif -void default_idle(void) +/* + * This is our default idle handler. We need to disable + * interrupts here to ensure we don't miss a wakeup call. + */ +static void default_idle(void) { - while (!need_resched()) { - leds_switch(LED_OFF); - local_irq_disable(); - if (likely(!need_resched())) - idle_with_irq_disabled(); - local_irq_enable(); - leds_switch(LED_ON); - } -} + local_irq_disable(); + if (!need_resched()) + idle_with_irq_disabled(); -void (*idle)(void) = default_idle; + local_irq_enable(); +} /* - * 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) + * 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 */ while (1) { - idle(); + void (*idle)(void) = pm_idle; + +#ifdef CONFIG_HOTPLUG_CPU + if (cpu_is_offline(smp_processor_id())) + cpu_die(); +#endif + 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(); @@ -221,7 +202,7 @@ copy_thread(int nr, unsigned long clone_flags, * sys_execve() executes a new program. */ -asmlinkage int sys_execve(char *name, char **argv, char **envp) +asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp) { int error; char *filename; @@ -264,23 +245,25 @@ unsigned long get_wchan(struct task_struct *p) void finish_atomic_sections (struct pt_regs *regs) { + int __user *up0 = (int __user *)regs->p0; + if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END) return; switch (regs->pc) { case ATOMIC_XCHG32 + 2: - put_user(regs->r1, (int *)regs->p0); + put_user(regs->r1, up0); regs->pc += 2; break; case ATOMIC_CAS32 + 2: case ATOMIC_CAS32 + 4: if (regs->r0 == regs->r1) - put_user(regs->r2, (int *)regs->p0); + put_user(regs->r2, up0); regs->pc = ATOMIC_CAS32 + 8; break; case ATOMIC_CAS32 + 6: - put_user(regs->r2, (int *)regs->p0); + put_user(regs->r2, up0); regs->pc += 2; break; @@ -288,7 +271,7 @@ void finish_atomic_sections (struct pt_regs *regs) regs->r0 = regs->r1 + regs->r0; /* fall through */ case ATOMIC_ADD32 + 4: - put_user(regs->r0, (int *)regs->p0); + put_user(regs->r0, up0); regs->pc = ATOMIC_ADD32 + 6; break; @@ -296,7 +279,7 @@ void finish_atomic_sections (struct pt_regs *regs) regs->r0 = regs->r1 - regs->r0; /* fall through */ case ATOMIC_SUB32 + 4: - put_user(regs->r0, (int *)regs->p0); + put_user(regs->r0, up0); regs->pc = ATOMIC_SUB32 + 6; break; @@ -304,7 +287,7 @@ void finish_atomic_sections (struct pt_regs *regs) regs->r0 = regs->r1 | regs->r0; /* fall through */ case ATOMIC_IOR32 + 4: - put_user(regs->r0, (int *)regs->p0); + put_user(regs->r0, up0); regs->pc = ATOMIC_IOR32 + 6; break; @@ -312,7 +295,7 @@ void finish_atomic_sections (struct pt_regs *regs) regs->r0 = regs->r1 & regs->r0; /* fall through */ case ATOMIC_AND32 + 4: - put_user(regs->r0, (int *)regs->p0); + put_user(regs->r0, up0); regs->pc = ATOMIC_AND32 + 6; break; @@ -320,13 +303,14 @@ void finish_atomic_sections (struct pt_regs *regs) regs->r0 = regs->r1 ^ regs->r0; /* fall through */ case ATOMIC_XOR32 + 4: - put_user(regs->r0, (int *)regs->p0); + put_user(regs->r0, up0); regs->pc = ATOMIC_XOR32 + 6; break; } } #if defined(CONFIG_ACCESS_CHECK) +/* Return 1 if access to memory range is OK, 0 otherwise */ int _access_ok(unsigned long addr, unsigned long size) { if (size == 0) @@ -340,6 +324,12 @@ int _access_ok(unsigned long addr, unsigned long size) return 1; if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end) return 1; + +#ifdef CONFIG_ROMFS_MTD_FS + /* For XIP, allow user space to use pointers within the ROMFS. */ + if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end) + return 1; +#endif #else if (addr >= memory_start && (addr + size) <= physical_mem_end) return 1;