diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
| -rw-r--r-- | arch/arm/kernel/process.c | 159 | 
1 files changed, 14 insertions, 145 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index fdfa3a78ec8c..f192a2a41719 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -17,12 +17,9 @@  #include <linux/stddef.h>  #include <linux/unistd.h>  #include <linux/user.h> -#include <linux/delay.h> -#include <linux/reboot.h>  #include <linux/interrupt.h>  #include <linux/kallsyms.h>  #include <linux/init.h> -#include <linux/cpu.h>  #include <linux/elfcore.h>  #include <linux/pm.h>  #include <linux/tick.h> @@ -31,16 +28,14 @@  #include <linux/random.h>  #include <linux/hw_breakpoint.h>  #include <linux/leds.h> -#include <linux/reboot.h> -#include <asm/cacheflush.h> -#include <asm/idmap.h>  #include <asm/processor.h>  #include <asm/thread_notify.h>  #include <asm/stacktrace.h>  #include <asm/system_misc.h>  #include <asm/mach/time.h>  #include <asm/tls.h> +#include <asm/vdso.h>  #ifdef CONFIG_CC_STACKPROTECTOR  #include <linux/stackprotector.h> @@ -59,69 +54,6 @@ static const char *isa_modes[] __maybe_unused = {    "ARM" , "Thumb" , "Jazelle", "ThumbEE"  }; -extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); -typedef void (*phys_reset_t)(unsigned long); - -/* - * A temporary stack to use for CPU reset. This is static so that we - * don't clobber it with the identity mapping. When running with this - * stack, any references to the current task *will not work* so you - * should really do as little as possible before jumping to your reset - * code. - */ -static u64 soft_restart_stack[16]; - -static void __soft_restart(void *addr) -{ -	phys_reset_t phys_reset; - -	/* Take out a flat memory mapping. */ -	setup_mm_for_reboot(); - -	/* Clean and invalidate caches */ -	flush_cache_all(); - -	/* Turn off caching */ -	cpu_proc_fin(); - -	/* Push out any further dirty data, and ensure cache is empty */ -	flush_cache_all(); - -	/* Switch to the identity mapping. */ -	phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); -	phys_reset((unsigned long)addr); - -	/* Should never get here. */ -	BUG(); -} - -void soft_restart(unsigned long addr) -{ -	u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); - -	/* Disable interrupts first */ -	raw_local_irq_disable(); -	local_fiq_disable(); - -	/* Disable the L2 if we're the last man standing. */ -	if (num_online_cpus() == 1) -		outer_disable(); - -	/* Change to the new stack and continue with the reset. */ -	call_with_stack(__soft_restart, (void *)addr, (void *)stack); - -	/* Should never get here. */ -	BUG(); -} - -/* - * Function pointers to optional machine specific functions - */ -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); -  /*   * This is our default idle handler.   */ @@ -166,79 +98,6 @@ void arch_cpu_idle_dead(void)  }  #endif -/* - * Called by kexec, immediately prior to machine_kexec(). - * - * This must completely disable all secondary CPUs; simply causing those CPUs - * to execute e.g. a RAM-based pin loop is not sufficient. This allows the - * kexec'd kernel to use any and all RAM as it sees fit, without having to - * avoid any code or data used by any SW CPU pin loop. The CPU hotplug - * functionality embodied in disable_nonboot_cpus() to achieve this. - */ -void machine_shutdown(void) -{ -	disable_nonboot_cpus(); -} - -/* - * Halting simply requires that the secondary CPUs stop performing any - * activity (executing tasks, handling interrupts). smp_send_stop() - * achieves this. - */ -void machine_halt(void) -{ -	local_irq_disable(); -	smp_send_stop(); - -	local_irq_disable(); -	while (1); -} - -/* - * Power-off simply requires that the secondary CPUs stop performing any - * activity (executing tasks, handling interrupts). smp_send_stop() - * achieves this. When the system power is turned off, it will take all CPUs - * with it. - */ -void machine_power_off(void) -{ -	local_irq_disable(); -	smp_send_stop(); - -	if (pm_power_off) -		pm_power_off(); -} - -/* - * Restart requires that the secondary CPUs stop performing any activity - * while the primary CPU resets the system. Systems with a single CPU can - * use soft_restart() as their machine descriptor's .restart hook, since that - * will cause the only available CPU to reset. Systems with multiple CPUs must - * provide a HW restart implementation, to ensure that all CPUs reset at once. - * This is required so that any code running after reset on the primary CPU - * doesn't have to co-ordinate with other CPUs to ensure they aren't still - * executing pre-reset code, and using RAM that the primary CPU's code wishes - * to use. Implementing such co-ordination would be essentially impossible. - */ -void machine_restart(char *cmd) -{ -	local_irq_disable(); -	smp_send_stop(); - -	if (arm_pm_restart) -		arm_pm_restart(reboot_mode, cmd); -	else -		do_kernel_restart(cmd); - -	/* Give a grace period for failure to restart of 1s */ -	mdelay(1000); - -	/* Whoops - the platform was unable to reboot. Tell the user! */ -	printk("Reboot failed -- System halted\n"); -	local_irq_disable(); -	while (1); -} -  void __show_regs(struct pt_regs *regs)  {  	unsigned long flags; @@ -475,7 +334,7 @@ const char *arch_vma_name(struct vm_area_struct *vma)  }  /* If possible, provide a placement hint at a random offset from the - * stack for the signal page. + * stack for the sigpage and vdso pages.   */  static unsigned long sigpage_addr(const struct mm_struct *mm,  				  unsigned int npages) @@ -519,6 +378,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)  {  	struct mm_struct *mm = current->mm;  	struct vm_area_struct *vma; +	unsigned long npages;  	unsigned long addr;  	unsigned long hint;  	int ret = 0; @@ -528,9 +388,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)  	if (!signal_page)  		return -ENOMEM; +	npages = 1; /* for sigpage */ +	npages += vdso_total_pages; +  	down_write(&mm->mmap_sem); -	hint = sigpage_addr(mm, 1); -	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0); +	hint = sigpage_addr(mm, npages); +	addr = get_unmapped_area(NULL, hint, npages << PAGE_SHIFT, 0, 0);  	if (IS_ERR_VALUE(addr)) {  		ret = addr;  		goto up_fail; @@ -547,6 +410,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)  	mm->context.sigpage = addr; +	/* Unlike the sigpage, failure to install the vdso is unlikely +	 * to be fatal to the process, so no error check needed +	 * here. +	 */ +	arm_install_vdso(mm, addr + PAGE_SIZE); +   up_fail:  	up_write(&mm->mmap_sem);  	return ret;  |