process.c 9.9 KB
Newer Older
Catalin Marinas's avatar
Catalin Marinas committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Based on arch/arm/kernel/process.c
 *
 * Original Copyright (C) 1995  Linus Torvalds
 * Copyright (C) 1996-2000 Russell King - Converted to ARM.
 * Copyright (C) 2012 ARM Ltd.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdarg.h>

23
#include <linux/compat.h>
24
#include <linux/efi.h>
Catalin Marinas's avatar
Catalin Marinas committed
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <linux/export.h>
#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>
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/pm.h>
#include <linux/tick.h>
#include <linux/utsname.h>
#include <linux/uaccess.h>
#include <linux/random.h>
#include <linux/hw_breakpoint.h>
#include <linux/personality.h>
#include <linux/notifier.h>

#include <asm/compat.h>
#include <asm/cacheflush.h>
50
51
#include <asm/fpsimd.h>
#include <asm/mmu_context.h>
Catalin Marinas's avatar
Catalin Marinas committed
52
53
54
#include <asm/processor.h>
#include <asm/stacktrace.h>

55
56
57
58
59
60
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif

Catalin Marinas's avatar
Catalin Marinas committed
61
62
void soft_restart(unsigned long addr)
{
63
64
	setup_mm_for_reboot();
	cpu_soft_restart(virt_to_phys(cpu_reset), addr);
65
66
	/* Should never get here */
	BUG();
Catalin Marinas's avatar
Catalin Marinas committed
67
68
69
70
71
72
73
74
}

/*
 * Function pointers to optional machine specific functions
 */
void (*pm_power_off)(void);
EXPORT_SYMBOL_GPL(pm_power_off);

75
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
Catalin Marinas's avatar
Catalin Marinas committed
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#ifdef CONFIG_IPIPE
static void __ipipe_halt_root(void)
{
	struct ipipe_percpu_domain_data *p;

	/*
	 * Emulate idle entry sequence over the root domain, which is
	 * stalled on entry.
	 */
	hard_local_irq_disable();

	p = ipipe_this_cpu_root_context();
	__clear_bit(IPIPE_STALL_FLAG, &p->status);

	if (unlikely(__ipipe_ipending_p(p)))
		__ipipe_sync_stage();
	else {
		cpu_do_idle();
	}
}
#else /* !CONFIG_IPIPE */
static void __ipipe_halt_root(void)
{
	cpu_do_idle();
}
#endif /* !CONFIG_IPIPE */

Catalin Marinas's avatar
Catalin Marinas committed
104
105
106
/*
 * This is our default idle handler.
 */
Thomas Gleixner's avatar
Thomas Gleixner committed
107
void arch_cpu_idle(void)
Catalin Marinas's avatar
Catalin Marinas committed
108
109
110
111
112
{
	/*
	 * This should do all the clock switching and wait for interrupt
	 * tricks
	 */
113
114
	if (!need_resched())
		__ipipe_halt_root();
115
	local_irq_enable();
Catalin Marinas's avatar
Catalin Marinas committed
116
117
}

118
119
120
121
122
123
124
#ifdef CONFIG_HOTPLUG_CPU
void arch_cpu_idle_dead(void)
{
       cpu_die();
}
#endif

125
126
127
128
129
130
131
132
133
/*
 * 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.
 */
Catalin Marinas's avatar
Catalin Marinas committed
134
135
void machine_shutdown(void)
{
136
	disable_nonboot_cpus();
Catalin Marinas's avatar
Catalin Marinas committed
137
138
}

139
140
141
142
143
/*
 * Halting simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this.
 */
Catalin Marinas's avatar
Catalin Marinas committed
144
145
void machine_halt(void)
{
146
	local_irq_disable();
147
	smp_send_stop();
Catalin Marinas's avatar
Catalin Marinas committed
148
149
150
	while (1);
}

151
152
153
154
155
156
/*
 * 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.
 */
Catalin Marinas's avatar
Catalin Marinas committed
157
158
void machine_power_off(void)
{
159
	local_irq_disable();
160
	smp_send_stop();
Catalin Marinas's avatar
Catalin Marinas committed
161
162
163
164
	if (pm_power_off)
		pm_power_off();
}

165
166
167
168
169
170
171
172
173
174
175
/*
 * 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.
 */
Catalin Marinas's avatar
Catalin Marinas committed
176
177
178
179
void machine_restart(char *cmd)
{
	/* Disable interrupts first */
	local_irq_disable();
180
	smp_send_stop();
Catalin Marinas's avatar
Catalin Marinas committed
181

182
183
184
185
186
187
188
	/*
	 * UpdateCapsule() depends on the system being reset via
	 * ResetSystem().
	 */
	if (efi_enabled(EFI_RUNTIME_SERVICES))
		efi_reboot(reboot_mode, NULL);

Catalin Marinas's avatar
Catalin Marinas committed
189
	/* Now call the architecture specific reboot code. */
190
	if (arm_pm_restart)
191
		arm_pm_restart(reboot_mode, cmd);
192
193
	else
		do_kernel_restart(cmd);
Catalin Marinas's avatar
Catalin Marinas committed
194
195
196
197
198
199
200
201
202
203

	/*
	 * Whoops - the architecture was unable to reboot.
	 */
	printk("Reboot failed -- System halted\n");
	while (1);
}

void __show_regs(struct pt_regs *regs)
{
204
205
206
207
208
209
210
211
212
213
214
215
	int i, top_reg;
	u64 lr, sp;

	if (compat_user_mode(regs)) {
		lr = regs->compat_lr;
		sp = regs->compat_sp;
		top_reg = 12;
	} else {
		lr = regs->regs[30];
		sp = regs->sp;
		top_reg = 29;
	}
Catalin Marinas's avatar
Catalin Marinas committed
216

217
	show_regs_print_info(KERN_DEFAULT);
Catalin Marinas's avatar
Catalin Marinas committed
218
	print_symbol("PC is at %s\n", instruction_pointer(regs));
219
	print_symbol("LR is at %s\n", lr);
Catalin Marinas's avatar
Catalin Marinas committed
220
	printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
221
222
223
	       regs->pc, lr, regs->pstate);
	printk("sp : %016llx\n", sp);
	for (i = top_reg; i >= 0; i--) {
Catalin Marinas's avatar
Catalin Marinas committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
		printk("x%-2d: %016llx ", i, regs->regs[i]);
		if (i % 2 == 0)
			printk("\n");
	}
	printk("\n");
}

void show_regs(struct pt_regs * regs)
{
	printk("\n");
	__show_regs(regs);
}

/*
 * Free current thread data structures etc..
 */
void exit_thread(void)
{
}

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
static void tls_thread_flush(void)
{
	asm ("msr tpidr_el0, xzr");

	if (is_compat_task()) {
		current->thread.tp_value = 0;

		/*
		 * We need to ensure ordering between the shadow state and the
		 * hardware state, so that we don't corrupt the hardware state
		 * with a stale shadow state during context switch.
		 */
		barrier();
		asm ("msr tpidrro_el0, xzr");
	}
}

Catalin Marinas's avatar
Catalin Marinas committed
261
262
263
void flush_thread(void)
{
	fpsimd_flush_thread();
264
	tls_thread_flush();
Catalin Marinas's avatar
Catalin Marinas committed
265
266
267
268
269
270
271
272
273
	flush_ptrace_hw_breakpoint(current);
}

void release_thread(struct task_struct *dead_task)
{
}

int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
274
	fpsimd_preserve_current_state();
Catalin Marinas's avatar
Catalin Marinas committed
275
276
277
278
279
280
281
	*dst = *src;
	return 0;
}

asmlinkage void ret_from_fork(void) asm("ret_from_fork");

int copy_thread(unsigned long clone_flags, unsigned long stack_start,
282
		unsigned long stk_sz, struct task_struct *p)
Catalin Marinas's avatar
Catalin Marinas committed
283
284
285
286
{
	struct pt_regs *childregs = task_pt_regs(p);
	unsigned long tls = p->thread.tp_value;

287
	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
Catalin Marinas's avatar
Catalin Marinas committed
288

289
290
	if (likely(!(p->flags & PF_KTHREAD))) {
		*childregs = *current_pt_regs();
291
292
		childregs->regs[0] = 0;
		if (is_compat_thread(task_thread_info(p))) {
293
294
			if (stack_start)
				childregs->compat_sp = stack_start;
295
296
297
298
299
300
		} else {
			/*
			 * Read the current TLS pointer from tpidr_el0 as it may be
			 * out-of-sync with the saved value.
			 */
			asm("mrs %0, tpidr_el0" : "=r" (tls));
301
302
303
304
305
306
			if (stack_start) {
				/* 16-byte aligned stack mandatory on AArch64 */
				if (stack_start & 15)
					return -EINVAL;
				childregs->sp = stack_start;
			}
307
		}
Catalin Marinas's avatar
Catalin Marinas committed
308
		/*
309
310
		 * If a TLS pointer was passed to clone (4th argument), use it
		 * for the new thread.
Catalin Marinas's avatar
Catalin Marinas committed
311
		 */
312
		if (clone_flags & CLONE_SETTLS)
313
			tls = childregs->regs[3];
314
315
316
317
318
	} else {
		memset(childregs, 0, sizeof(struct pt_regs));
		childregs->pstate = PSR_MODE_EL1h;
		p->thread.cpu_context.x19 = stack_start;
		p->thread.cpu_context.x20 = stk_sz;
Catalin Marinas's avatar
Catalin Marinas committed
319
320
	}
	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
321
	p->thread.cpu_context.sp = (unsigned long)childregs;
Catalin Marinas's avatar
Catalin Marinas committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
	p->thread.tp_value = tls;

	ptrace_hw_copy_thread(p);

	return 0;
}

static void tls_thread_switch(struct task_struct *next)
{
	unsigned long tpidr, tpidrro;

	if (!is_compat_task()) {
		asm("mrs %0, tpidr_el0" : "=r" (tpidr));
		current->thread.tp_value = tpidr;
	}

	if (is_compat_thread(task_thread_info(next))) {
		tpidr = 0;
		tpidrro = next->thread.tp_value;
	} else {
		tpidr = next->thread.tp_value;
		tpidrro = 0;
	}

	asm(
	"	msr	tpidr_el0, %0\n"
	"	msr	tpidrro_el0, %1"
	: : "r" (tpidr), "r" (tpidrro));
}

/*
 * Thread switching.
 */
struct task_struct *__switch_to(struct task_struct *prev,
				struct task_struct *next)
{
	struct task_struct *last;
359
	unsigned long flags;
Catalin Marinas's avatar
Catalin Marinas committed
360

361
	flags = hard_cond_local_irq_save();
Catalin Marinas's avatar
Catalin Marinas committed
362
363
364
	fpsimd_thread_switch(next);
	tls_thread_switch(next);
	hw_breakpoint_thread_switch(next);
365
	contextidr_thread_switch(next);
Catalin Marinas's avatar
Catalin Marinas committed
366

367
368
369
370
	/*
	 * Complete any pending TLB or cache maintenance on this CPU in case
	 * the thread migrates to a different CPU.
	 */
371
	dsb(ish);
Catalin Marinas's avatar
Catalin Marinas committed
372
373
374

	/* the actual thread switch */
	last = cpu_switch_to(prev, next);
375
	hard_cond_local_irq_restore(flags);
Catalin Marinas's avatar
Catalin Marinas committed
376
377
378
379
380
381
382

	return last;
}

unsigned long get_wchan(struct task_struct *p)
{
	struct stackframe frame;
383
	unsigned long stack_page;
Catalin Marinas's avatar
Catalin Marinas committed
384
385
386
387
388
389
390
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;

	frame.fp = thread_saved_fp(p);
	frame.sp = thread_saved_sp(p);
	frame.pc = thread_saved_pc(p);
391
	stack_page = (unsigned long)task_stack_page(p);
Catalin Marinas's avatar
Catalin Marinas committed
392
	do {
393
394
395
		if (frame.sp < stack_page ||
		    frame.sp >= stack_page + THREAD_SIZE ||
		    unwind_frame(&frame))
Catalin Marinas's avatar
Catalin Marinas committed
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
			return 0;
		if (!in_sched_functions(frame.pc))
			return frame.pc;
	} while (count ++ < 16);
	return 0;
}

unsigned long arch_align_stack(unsigned long sp)
{
	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
		sp -= get_random_int() & ~PAGE_MASK;
	return sp & ~0xf;
}

static unsigned long randomize_base(unsigned long base)
{
	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
	return randomize_range(base, range_end, 0) ? : base;
}

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
	return randomize_base(mm->brk);
}