process.c 13.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
 *  linux/arch/arm/kernel/process.c
 *
 *  Copyright (C) 1996-2000 Russell King - Converted to ARM.
 *  Original Copyright (C) 1995  Linus Torvalds
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <stdarg.h>

13
#include <linux/export.h>
L
Linus Torvalds 已提交
14 15 16 17 18 19 20 21 22 23 24
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#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>
25
#include <linux/cpu.h>
26
#include <linux/elfcore.h>
27
#include <linux/pm.h>
28
#include <linux/tick.h>
29
#include <linux/utsname.h>
30
#include <linux/uaccess.h>
31
#include <linux/random.h>
32
#include <linux/hw_breakpoint.h>
33
#include <linux/leds.h>
34
#include <linux/reboot.h>
L
Linus Torvalds 已提交
35

36
#include <asm/cacheflush.h>
37
#include <asm/idmap.h>
L
Linus Torvalds 已提交
38
#include <asm/processor.h>
39
#include <asm/thread_notify.h>
40
#include <asm/stacktrace.h>
41
#include <asm/system_misc.h>
42
#include <asm/mach/time.h>
43
#include <asm/tls.h>
L
Linus Torvalds 已提交
44

45 46 47 48 49 50
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif

51
static const char *processor_modes[] __maybe_unused = {
52 53
  "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
54 55
  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "MON_32" , "ABT_32" ,
  "UK8_32" , "UK9_32" , "HYP_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
56 57
};

58
static const char *isa_modes[] __maybe_unused = {
59 60 61
  "ARM" , "Thumb" , "Jazelle", "ThumbEE"
};

62 63 64 65 66 67 68 69 70 71 72 73 74
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)
75
{
76
	phys_reset_t phys_reset;
77

78
	/* Take out a flat memory mapping. */
79
	setup_mm_for_reboot();
80

81 82 83 84 85 86 87 88 89
	/* 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();

90 91 92
	/* Switch to the identity mapping. */
	phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
	phys_reset((unsigned long)addr);
93

94 95 96 97 98 99 100 101 102
	/* Should never get here. */
	BUG();
}

void soft_restart(unsigned long addr)
{
	u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);

	/* Disable interrupts first */
103
	raw_local_irq_disable();
104 105 106 107 108 109 110 111 112 113 114
	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();
115 116
}

L
Linus Torvalds 已提交
117
/*
118
 * Function pointers to optional machine specific functions
L
Linus Torvalds 已提交
119 120 121 122
 */
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);

123
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
124

L
Linus Torvalds 已提交
125
/*
N
Nicolas Pitre 已提交
126
 * This is our default idle handler.
L
Linus Torvalds 已提交
127
 */
N
Nicolas Pitre 已提交
128 129 130

void (*arm_pm_idle)(void);

131 132 133 134 135
/*
 * Called from the core idle loop.
 */

void arch_cpu_idle(void)
L
Linus Torvalds 已提交
136
{
N
Nicolas Pitre 已提交
137 138 139
	if (arm_pm_idle)
		arm_pm_idle();
	else
N
Nicolas Pitre 已提交
140
		cpu_do_idle();
141
	local_irq_enable();
L
Linus Torvalds 已提交
142 143
}

T
Thomas Gleixner 已提交
144
void arch_cpu_idle_prepare(void)
L
Linus Torvalds 已提交
145 146
{
	local_fiq_enable();
T
Thomas Gleixner 已提交
147
}
L
Linus Torvalds 已提交
148

T
Thomas Gleixner 已提交
149 150 151 152 153
void arch_cpu_idle_enter(void)
{
	ledtrig_cpu(CPU_LED_IDLE_START);
#ifdef CONFIG_PL310_ERRATA_769419
	wmb();
154
#endif
T
Thomas Gleixner 已提交
155
}
156

T
Thomas Gleixner 已提交
157 158 159 160 161 162 163 164 165 166
void arch_cpu_idle_exit(void)
{
	ledtrig_cpu(CPU_LED_IDLE_END);
}

#ifdef CONFIG_HOTPLUG_CPU
void arch_cpu_idle_dead(void)
{
	cpu_die();
}
167
#endif
T
Thomas Gleixner 已提交
168

169 170 171 172 173 174 175 176 177
/*
 * 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.
 */
178
void machine_shutdown(void)
L
Linus Torvalds 已提交
179
{
180
	disable_nonboot_cpus();
L
Linus Torvalds 已提交
181 182
}

183 184 185 186 187
/*
 * Halting simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this.
 */
188 189
void machine_halt(void)
{
190
	local_irq_disable();
191 192
	smp_send_stop();

193
	local_irq_disable();
194 195
	while (1);
}
L
Linus Torvalds 已提交
196

197 198 199 200 201 202
/*
 * 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.
 */
L
Linus Torvalds 已提交
203 204
void machine_power_off(void)
{
205
	local_irq_disable();
206 207
	smp_send_stop();

L
Linus Torvalds 已提交
208 209 210 211
	if (pm_power_off)
		pm_power_off();
}

212 213 214 215 216 217 218 219 220 221 222
/*
 * 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.
 */
223
void machine_restart(char *cmd)
L
Linus Torvalds 已提交
224
{
225
	local_irq_disable();
226
	smp_send_stop();
227

228 229 230 231
	if (arm_pm_restart)
		arm_pm_restart(reboot_mode, cmd);
	else
		do_kernel_restart(cmd);
232 233 234 235 236 237

	/* 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");
238
	local_irq_disable();
239
	while (1);
L
Linus Torvalds 已提交
240 241
}

R
Russell King 已提交
242
void __show_regs(struct pt_regs *regs)
L
Linus Torvalds 已提交
243
{
244 245
	unsigned long flags;
	char buf[64];
L
Linus Torvalds 已提交
246

247 248
	show_regs_print_info(KERN_DEFAULT);

L
Linus Torvalds 已提交
249 250
	print_symbol("PC is at %s\n", instruction_pointer(regs));
	print_symbol("LR is at %s\n", regs->ARM_lr);
251
	printk("pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
L
Linus Torvalds 已提交
252
	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
253 254
		regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
		regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
L
Linus Torvalds 已提交
255 256 257 258 259 260 261 262 263
	printk("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
		regs->ARM_r10, regs->ARM_r9,
		regs->ARM_r8);
	printk("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
		regs->ARM_r7, regs->ARM_r6,
		regs->ARM_r5, regs->ARM_r4);
	printk("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
		regs->ARM_r3, regs->ARM_r2,
		regs->ARM_r1, regs->ARM_r0);
264 265 266 267 268 269 270 271

	flags = regs->ARM_cpsr;
	buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
	buf[4] = '\0';

272
#ifndef CONFIG_CPU_V7M
273
	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
274
		buf, interrupts_enabled(regs) ? "n" : "ff",
L
Linus Torvalds 已提交
275 276
		fast_interrupts_enabled(regs) ? "n" : "ff",
		processor_modes[processor_mode(regs)],
277
		isa_modes[isa_mode(regs)],
L
Linus Torvalds 已提交
278
		get_fs() == get_ds() ? "kernel" : "user");
279 280 281 282
#else
	printk("xPSR: %08lx\n", regs->ARM_cpsr);
#endif

283
#ifdef CONFIG_CPU_CP15
L
Linus Torvalds 已提交
284
	{
285
		unsigned int ctrl;
286 287

		buf[0] = '\0';
288
#ifdef CONFIG_CPU_CP15_MMU
289 290 291 292 293 294 295 296
		{
			unsigned int transbase, dac;
			asm("mrc p15, 0, %0, c2, c0\n\t"
			    "mrc p15, 0, %1, c3, c0\n"
			    : "=r" (transbase), "=r" (dac));
			snprintf(buf, sizeof(buf), "  Table: %08x  DAC: %08x",
			  	transbase, dac);
		}
297
#endif
298 299 300 301
		asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));

		printk("Control: %08x%s\n", ctrl, buf);
	}
302
#endif
L
Linus Torvalds 已提交
303 304
}

R
Russell King 已提交
305 306 307
void show_regs(struct pt_regs * regs)
{
	__show_regs(regs);
308
	dump_stack();
R
Russell King 已提交
309 310
}

311 312 313 314
ATOMIC_NOTIFIER_HEAD(thread_notify_head);

EXPORT_SYMBOL_GPL(thread_notify_head);

L
Linus Torvalds 已提交
315 316 317 318 319
/*
 * Free current thread data structures etc..
 */
void exit_thread(void)
{
320
	thread_notify(THREAD_NOTIFY_EXIT, current_thread_info());
L
Linus Torvalds 已提交
321 322 323 324 325 326 327
}

void flush_thread(void)
{
	struct thread_info *thread = current_thread_info();
	struct task_struct *tsk = current;

328 329
	flush_ptrace_hw_breakpoint(tsk);

L
Linus Torvalds 已提交
330 331
	memset(thread->used_cp, 0, sizeof(thread->used_cp));
	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
332 333
	memset(&thread->fpstate, 0, sizeof(union fp_state));

334 335
	flush_tls();

336
	thread_notify(THREAD_NOTIFY_FLUSH, thread);
L
Linus Torvalds 已提交
337 338 339 340 341 342 343 344 345
}

void release_thread(struct task_struct *dead_task)
{
}

asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");

int
A
Alexey Dobriyan 已提交
346
copy_thread(unsigned long clone_flags, unsigned long stack_start,
347
	    unsigned long stk_sz, struct task_struct *p)
L
Linus Torvalds 已提交
348
{
A
Al Viro 已提交
349 350
	struct thread_info *thread = task_thread_info(p);
	struct pt_regs *childregs = task_pt_regs(p);
L
Linus Torvalds 已提交
351 352

	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
353

A
Al Viro 已提交
354 355
	if (likely(!(p->flags & PF_KTHREAD))) {
		*childregs = *current_pt_regs();
356
		childregs->ARM_r0 = 0;
A
Al Viro 已提交
357 358
		if (stack_start)
			childregs->ARM_sp = stack_start;
359
	} else {
360
		memset(childregs, 0, sizeof(struct pt_regs));
361 362 363 364
		thread->cpu_context.r4 = stk_sz;
		thread->cpu_context.r5 = stack_start;
		childregs->ARM_cpsr = SVC_MODE;
	}
365
	thread->cpu_context.pc = (unsigned long)ret_from_fork;
L
Linus Torvalds 已提交
366 367
	thread->cpu_context.sp = (unsigned long)childregs;

368 369
	clear_ptrace_hw_breakpoint(p);

L
Linus Torvalds 已提交
370
	if (clone_flags & CLONE_SETTLS)
371 372
		thread->tp_value[0] = childregs->ARM_r3;
	thread->tp_value[1] = get_tpuser();
L
Linus Torvalds 已提交
373

374 375
	thread_notify(THREAD_NOTIFY_COPY, thread);

L
Linus Torvalds 已提交
376 377 378
	return 0;
}

379 380 381 382 383 384 385 386 387
/*
 * Fill in the task's elfregs structure for a core dump.
 */
int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
{
	elf_core_copy_regs(elfregs, task_pt_regs(t));
	return 1;
}

L
Linus Torvalds 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
/*
 * fill in the fpe structure for a core dump...
 */
int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
{
	struct thread_info *thread = current_thread_info();
	int used_math = thread->used_cp[1] | thread->used_cp[2];

	if (used_math)
		memcpy(fp, &thread->fpstate.soft, sizeof (*fp));

	return used_math != 0;
}
EXPORT_SYMBOL(dump_fpu);

unsigned long get_wchan(struct task_struct *p)
{
405
	struct stackframe frame;
406
	unsigned long stack_page;
L
Linus Torvalds 已提交
407 408 409 410
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;

411 412 413 414
	frame.fp = thread_saved_fp(p);
	frame.sp = thread_saved_sp(p);
	frame.lr = 0;			/* recovered from the stack */
	frame.pc = thread_saved_pc(p);
415
	stack_page = (unsigned long)task_stack_page(p);
L
Linus Torvalds 已提交
416
	do {
417 418 419
		if (frame.sp < stack_page ||
		    frame.sp >= stack_page + THREAD_SIZE ||
		    unwind_frame(&frame) < 0)
L
Linus Torvalds 已提交
420
			return 0;
421 422
		if (!in_sched_functions(frame.pc))
			return frame.pc;
L
Linus Torvalds 已提交
423 424 425
	} while (count ++ < 16);
	return 0;
}
426 427 428 429 430 431

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
	unsigned long range_end = mm->brk + 0x02000000;
	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}
432

433
#ifdef CONFIG_MMU
434
#ifdef CONFIG_KUSER_HELPERS
435 436
/*
 * The vectors page is always readable from user space for the
437 438
 * atomic helpers. Insert it into the gate_vma so that it is visible
 * through ptrace and /proc/<pid>/mem.
439
 */
440 441 442 443 444
static struct vm_area_struct gate_vma = {
	.vm_start	= 0xffff0000,
	.vm_end		= 0xffff0000 + PAGE_SIZE,
	.vm_flags	= VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
};
445

446
static int __init gate_vma_init(void)
447
{
448
	gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
	return 0;
}
arch_initcall(gate_vma_init);

struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
{
	return &gate_vma;
}

int in_gate_area(struct mm_struct *mm, unsigned long addr)
{
	return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end);
}

int in_gate_area_no_mm(unsigned long addr)
{
	return in_gate_area(NULL, addr);
466
}
467
#define is_gate_vma(vma)	((vma) == &gate_vma)
468 469 470
#else
#define is_gate_vma(vma)	0
#endif
471 472 473

const char *arch_vma_name(struct vm_area_struct *vma)
{
474
	return is_gate_vma(vma) ? "[vectors]" : NULL;
475 476
}

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
/* If possible, provide a placement hint at a random offset from the
 * stack for the signal page.
 */
static unsigned long sigpage_addr(const struct mm_struct *mm,
				  unsigned int npages)
{
	unsigned long offset;
	unsigned long first;
	unsigned long last;
	unsigned long addr;
	unsigned int slots;

	first = PAGE_ALIGN(mm->start_stack);

	last = TASK_SIZE - (npages << PAGE_SHIFT);

	/* No room after stack? */
	if (first > last)
		return 0;

	/* Just enough room? */
	if (first == last)
		return first;

	slots = ((last - first) >> PAGE_SHIFT) + 1;

	offset = get_random_int() % slots;

	addr = first + (offset << PAGE_SHIFT);

	return addr;
508 509
}

510
static struct page *signal_page;
511 512
extern struct page *get_signal_page(void);

513 514 515 516 517
static const struct vm_special_mapping sigpage_mapping = {
	.name = "[sigpage]",
	.pages = &signal_page,
};

518 519 520
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
	struct mm_struct *mm = current->mm;
521
	struct vm_area_struct *vma;
522
	unsigned long addr;
523
	unsigned long hint;
524
	int ret = 0;
525

526 527 528
	if (!signal_page)
		signal_page = get_signal_page();
	if (!signal_page)
529 530 531
		return -ENOMEM;

	down_write(&mm->mmap_sem);
532 533
	hint = sigpage_addr(mm, 1);
	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
534 535 536 537 538
	if (IS_ERR_VALUE(addr)) {
		ret = addr;
		goto up_fail;
	}

539
	vma = _install_special_mapping(mm, addr, PAGE_SIZE,
540
		VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
541 542 543 544 545 546
		&sigpage_mapping);

	if (IS_ERR(vma)) {
		ret = PTR_ERR(vma);
		goto up_fail;
	}
547

548
	mm->context.sigpage = addr;
549 550 551 552

 up_fail:
	up_write(&mm->mmap_sem);
	return ret;
553
}
554
#endif