process.c 13.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
7
 * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org)
L
Linus Torvalds 已提交
8 9
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 * Copyright (C) 2004 Thiemo Seufer
10
 * Copyright (C) 2013  Imagination Technologies Ltd.
L
Linus Torvalds 已提交
11 12 13
 */
#include <linux/errno.h>
#include <linux/sched.h>
14
#include <linux/tick.h>
L
Linus Torvalds 已提交
15 16 17 18
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
19
#include <linux/export.h>
L
Linus Torvalds 已提交
20 21 22 23 24 25 26
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/personality.h>
#include <linux/sys.h>
#include <linux/user.h>
#include <linux/init.h>
#include <linux/completion.h>
27
#include <linux/kallsyms.h>
28
#include <linux/random.h>
L
Linus Torvalds 已提交
29

30
#include <asm/asm.h>
L
Linus Torvalds 已提交
31 32
#include <asm/bootinfo.h>
#include <asm/cpu.h>
33
#include <asm/dsp.h>
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42
#include <asm/fpu.h>
#include <asm/pgtable.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/elf.h>
#include <asm/isadep.h>
#include <asm/inst.h>
43
#include <asm/stacktrace.h>
L
Linus Torvalds 已提交
44

T
Thomas Gleixner 已提交
45 46
#ifdef CONFIG_HOTPLUG_CPU
void arch_cpu_idle_dead(void)
L
Linus Torvalds 已提交
47
{
T
Thomas Gleixner 已提交
48 49 50 51 52
	/* What the heck is this check doing ? */
	if (!cpu_isset(smp_processor_id(), cpu_callin_map))
		play_dead();
}
#endif
53

T
Thomas Gleixner 已提交
54 55
void arch_cpu_idle(void)
{
56
#ifdef CONFIG_MIPS_MT_SMTC
T
Thomas Gleixner 已提交
57
	extern void smtc_idle_loop_hook(void);
58

T
Thomas Gleixner 已提交
59
	smtc_idle_loop_hook();
60
#endif
T
Thomas Gleixner 已提交
61 62 63 64
	if (cpu_wait)
		(*cpu_wait)();
	else
		local_irq_enable();
L
Linus Torvalds 已提交
65 66 67
}

asmlinkage void ret_from_fork(void);
A
Al Viro 已提交
68
asmlinkage void ret_from_kernel_thread(void);
L
Linus Torvalds 已提交
69 70 71 72 73 74

void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	unsigned long status;

	/* New thread loses kernel privileges. */
75
	status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
76
#ifdef CONFIG_64BIT
77
	status |= test_thread_flag(TIF_32BIT_REGS) ? 0 : ST0_FR;
L
Linus Torvalds 已提交
78 79 80 81
#endif
	status |= KU_USER;
	regs->cp0_status = status;
	clear_used_math();
82
	clear_fpu_owner();
83 84
	if (cpu_has_dsp)
		__init_dsp();
L
Linus Torvalds 已提交
85 86 87 88 89 90 91 92 93 94 95 96
	regs->cp0_epc = pc;
	regs->regs[29] = sp;
}

void exit_thread(void)
{
}

void flush_thread(void)
{
}

A
Alexey Dobriyan 已提交
97
int copy_thread(unsigned long clone_flags, unsigned long usp,
98
	unsigned long arg, struct task_struct *p)
L
Linus Torvalds 已提交
99
{
A
Al Viro 已提交
100
	struct thread_info *ti = task_thread_info(p);
101
	struct pt_regs *childregs, *regs = current_pt_regs();
102
	unsigned long childksp;
R
Ralf Baechle 已提交
103
	p->set_child_tid = p->clear_child_tid = NULL;
L
Linus Torvalds 已提交
104

A
Al Viro 已提交
105
	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
L
Linus Torvalds 已提交
106 107 108

	preempt_disable();

109
	if (is_fpu_owner())
L
Linus Torvalds 已提交
110
		save_fp(p);
111 112 113

	if (cpu_has_dsp)
		save_dsp(p);
L
Linus Torvalds 已提交
114 115 116 117 118

	preempt_enable();

	/* set up new TSS. */
	childregs = (struct pt_regs *) childksp - 1;
119 120
	/*  Put the stack after the struct pt_regs.  */
	childksp = (unsigned long) childregs;
A
Al Viro 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
	if (unlikely(p->flags & PF_KTHREAD)) {
		unsigned long status = p->thread.cp0_status;
		memset(childregs, 0, sizeof(struct pt_regs));
		ti->addr_limit = KERNEL_DS;
		p->thread.reg16 = usp; /* fn */
		p->thread.reg17 = arg;
		p->thread.reg29 = childksp;
		p->thread.reg31 = (unsigned long) ret_from_kernel_thread;
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
		status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |
			 ((status & (ST0_KUC | ST0_IEC)) << 2);
#else
		status |= ST0_EXL;
#endif
		childregs->cp0_status = status;
		return 0;
	}
L
Linus Torvalds 已提交
139
	*childregs = *regs;
R
Ralf Baechle 已提交
140 141
	childregs->regs[7] = 0; /* Clear error flag */
	childregs->regs[2] = 0; /* Child gets zero as return value */
142 143
	if (usp)
		childregs->regs[29] = usp;
A
Al Viro 已提交
144
	ti->addr_limit = USER_DS;
L
Linus Torvalds 已提交
145 146 147 148 149 150 151 152 153 154

	p->thread.reg29 = (unsigned long) childregs;
	p->thread.reg31 = (unsigned long) ret_from_fork;

	/*
	 * New tasks lose permission to use the fpu. This accelerates context
	 * switching for most programs since they don't use the fpu.
	 */
	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);

155
#ifdef CONFIG_MIPS_MT_SMTC
R
Ralf Baechle 已提交
156
	/*
157 158
	 * SMTC restores TCStatus after Status, and the CU bits
	 * are aliased there.
R
Ralf Baechle 已提交
159
	 */
160 161
	childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1);
#endif
L
Linus Torvalds 已提交
162 163
	clear_tsk_thread_flag(p, TIF_USEDFPU);

R
Ralf Baechle 已提交
164
#ifdef CONFIG_MIPS_MT_FPAFF
165
	clear_tsk_thread_flag(p, TIF_FPUBOUND);
R
Ralf Baechle 已提交
166 167
#endif /* CONFIG_MIPS_MT_FPAFF */

R
Ralf Baechle 已提交
168 169 170
	if (clone_flags & CLONE_SETTLS)
		ti->tp_value = regs->regs[7];

L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178 179 180 181
	return 0;
}

/* Fill in the fpu structure for a core dump.. */
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
{
	memcpy(r, &current->thread.fpu, sizeof(current->thread.fpu));

	return 1;
}

182
void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
{
	int i;

	for (i = 0; i < EF_R0; i++)
		gp[i] = 0;
	gp[EF_R0] = 0;
	for (i = 1; i <= 31; i++)
		gp[EF_R0 + i] = regs->regs[i];
	gp[EF_R26] = 0;
	gp[EF_R27] = 0;
	gp[EF_LO] = regs->lo;
	gp[EF_HI] = regs->hi;
	gp[EF_CP0_EPC] = regs->cp0_epc;
	gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
	gp[EF_CP0_STATUS] = regs->cp0_status;
	gp[EF_CP0_CAUSE] = regs->cp0_cause;
#ifdef EF_UNUSED0
	gp[EF_UNUSED0] = 0;
#endif
}

204
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
R
Ralf Baechle 已提交
205
{
A
Al Viro 已提交
206
	elf_dump_regs(*regs, task_pt_regs(tsk));
R
Ralf Baechle 已提交
207 208 209
	return 1;
}

210
int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
L
Linus Torvalds 已提交
211 212 213 214 215 216
{
	memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));

	return 1;
}

217 218 219 220 221 222 223 224 225
/*
 *
 */
struct mips_frame_info {
	void		*func;
	unsigned long	func_size;
	int		frame_size;
	int		pc_offset;
};
226

227 228
static inline int is_ra_save_ins(union mips_instruction *ip)
{
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
#ifdef CONFIG_CPU_MICROMIPS
	union mips_instruction mmi;

	/*
	 * swsp ra,offset
	 * swm16 reglist,offset(sp)
	 * swm32 reglist,offset(sp)
	 * sw32 ra,offset(sp)
	 * jradiussp - NOT SUPPORTED
	 *
	 * microMIPS is way more fun...
	 */
	if (mm_insn_16bit(ip->halfword[0])) {
		mmi.word = (ip->halfword[0] << 16);
		return ((mmi.mm16_r5_format.opcode == mm_swsp16_op &&
			 mmi.mm16_r5_format.rt == 31) ||
			(mmi.mm16_m_format.opcode == mm_pool16c_op &&
			 mmi.mm16_m_format.func == mm_swm16_op));
	}
	else {
		mmi.halfword[0] = ip->halfword[1];
		mmi.halfword[1] = ip->halfword[0];
		return ((mmi.mm_m_format.opcode == mm_pool32b_op &&
			 mmi.mm_m_format.rd > 9 &&
			 mmi.mm_m_format.base == 29 &&
			 mmi.mm_m_format.func == mm_swm32_func) ||
			(mmi.i_format.opcode == mm_sw32_op &&
			 mmi.i_format.rs == 29 &&
			 mmi.i_format.rt == 31));
	}
#else
260 261 262 263
	/* sw / sd $ra, offset($sp) */
	return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
		ip->i_format.rs == 29 &&
		ip->i_format.rt == 31;
264
#endif
265 266
}

267
static inline int is_jump_ins(union mips_instruction *ip)
268
{
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
#ifdef CONFIG_CPU_MICROMIPS
	/*
	 * jr16,jrc,jalr16,jalr16
	 * jal
	 * jalr/jr,jalr.hb/jr.hb,jalrs,jalrs.hb
	 * jraddiusp - NOT SUPPORTED
	 *
	 * microMIPS is kind of more fun...
	 */
	union mips_instruction mmi;

	mmi.word = (ip->halfword[0] << 16);

	if ((mmi.mm16_r5_format.opcode == mm_pool16c_op &&
	    (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) ||
	    ip->j_format.opcode == mm_jal32_op)
		return 1;
	if (ip->r_format.opcode != mm_pool32a_op ||
			ip->r_format.func != mm_pool32axf_op)
		return 0;
	return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op);
#else
291 292
	if (ip->j_format.opcode == j_op)
		return 1;
293 294 295 296 297
	if (ip->j_format.opcode == jal_op)
		return 1;
	if (ip->r_format.opcode != spec_op)
		return 0;
	return ip->r_format.func == jalr_op || ip->r_format.func == jr_op;
298
#endif
299 300 301 302
}

static inline int is_sp_move_ins(union mips_instruction *ip)
{
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
#ifdef CONFIG_CPU_MICROMIPS
	/*
	 * addiusp -imm
	 * addius5 sp,-imm
	 * addiu32 sp,sp,-imm
	 * jradiussp - NOT SUPPORTED
	 *
	 * microMIPS is not more fun...
	 */
	if (mm_insn_16bit(ip->halfword[0])) {
		union mips_instruction mmi;

		mmi.word = (ip->halfword[0] << 16);
		return ((mmi.mm16_r3_format.opcode == mm_pool16d_op &&
			 mmi.mm16_r3_format.simmediate && mm_addiusp_func) ||
			(mmi.mm16_r5_format.opcode == mm_pool16d_op &&
			 mmi.mm16_r5_format.rt == 29));
	}
	return (ip->mm_i_format.opcode == mm_addiu32_op &&
		 ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29);
#else
324 325 326 327 328
	/* addiu/daddiu sp,sp,-imm */
	if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
		return 0;
	if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
		return 1;
329
#endif
330 331 332
	return 0;
}

333
static int get_frame_info(struct mips_frame_info *info)
L
Linus Torvalds 已提交
334
{
335 336 337
#ifdef CONFIG_CPU_MICROMIPS
	union mips_instruction *ip = (void *) (((char *) info->func) - 1);
#else
338
	union mips_instruction *ip = info->func;
339
#endif
340 341
	unsigned max_insns = info->func_size / sizeof(union mips_instruction);
	unsigned i;
342

L
Linus Torvalds 已提交
343
	info->pc_offset = -1;
344
	info->frame_size = 0;
L
Linus Torvalds 已提交
345

346 347 348 349 350 351 352
	if (!ip)
		goto err;

	if (max_insns == 0)
		max_insns = 128U;	/* unknown function size */
	max_insns = min(128U, max_insns);

353 354
	for (i = 0; i < max_insns; i++, ip++) {

355
		if (is_jump_ins(ip))
356
			break;
357 358
		if (!info->frame_size) {
			if (is_sp_move_ins(ip))
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
			{
#ifdef CONFIG_CPU_MICROMIPS
				if (mm_insn_16bit(ip->halfword[0]))
				{
					unsigned short tmp;

					if (ip->halfword[0] & mm_addiusp_func)
					{
						tmp = (((ip->halfword[0] >> 1) & 0x1ff) << 2);
						info->frame_size = -(signed short)(tmp | ((tmp & 0x100) ? 0xfe00 : 0));
					} else {
						tmp = (ip->halfword[0] >> 1);
						info->frame_size = -(signed short)(tmp & 0xf);
					}
					ip = (void *) &ip->halfword[1];
					ip--;
				} else
#endif
377
				info->frame_size = - ip->i_format.simmediate;
378
			}
379
			continue;
380
		}
381
		if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
382 383
			info->pc_offset =
				ip->i_format.simmediate / sizeof(long);
384
			break;
L
Linus Torvalds 已提交
385 386
		}
	}
387 388 389 390 391
	if (info->frame_size && info->pc_offset >= 0) /* nested */
		return 0;
	if (info->pc_offset < 0) /* leaf */
		return 1;
	/* prologue seems boggus... */
392
err:
393
	return -1;
L
Linus Torvalds 已提交
394 395
}

396 397
static struct mips_frame_info schedule_mfi __read_mostly;

L
Linus Torvalds 已提交
398 399
static int __init frame_info_init(void)
{
400
	unsigned long size = 0;
401
#ifdef CONFIG_KALLSYMS
402 403
	unsigned long ofs;

404
	kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs);
405
#endif
406 407 408 409
	schedule_mfi.func = schedule;
	schedule_mfi.func_size = size;

	get_frame_info(&schedule_mfi);
410 411 412 413 414

	/*
	 * Without schedule() frame info, result given by
	 * thread_saved_pc() and get_wchan() are not reliable.
	 */
415
	if (schedule_mfi.pc_offset < 0)
416
		printk("Can't analyze schedule() prologue at %p\n", schedule);
417

L
Linus Torvalds 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
	return 0;
}

arch_initcall(frame_info_init);

/*
 * Return saved PC of a blocked thread.
 */
unsigned long thread_saved_pc(struct task_struct *tsk)
{
	struct thread_struct *t = &tsk->thread;

	/* New born processes are a special case */
	if (t->reg31 == (unsigned long) ret_from_fork)
		return t->reg31;
433
	if (schedule_mfi.pc_offset < 0)
L
Linus Torvalds 已提交
434
		return 0;
435
	return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
L
Linus Torvalds 已提交
436 437 438
}


439
#ifdef CONFIG_KALLSYMS
440 441 442 443 444
/* generic stack unwinding function */
unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
					      unsigned long *sp,
					      unsigned long pc,
					      unsigned long *ra)
445 446 447
{
	struct mips_frame_info info;
	unsigned long size, ofs;
F
Franck Bui-Huu 已提交
448
	int leaf;
449 450
	extern void ret_from_irq(void);
	extern void ret_from_exception(void);
451 452 453 454

	if (!stack_page)
		return 0;

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
	/*
	 * If we reached the bottom of interrupt context,
	 * return saved pc in pt_regs.
	 */
	if (pc == (unsigned long)ret_from_irq ||
	    pc == (unsigned long)ret_from_exception) {
		struct pt_regs *regs;
		if (*sp >= stack_page &&
		    *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) {
			regs = (struct pt_regs *)*sp;
			pc = regs->cp0_epc;
			if (__kernel_text_address(pc)) {
				*sp = regs->regs[29];
				*ra = regs->regs[31];
				return pc;
			}
		}
		return 0;
	}
474
	if (!kallsyms_lookup_size_offset(pc, &size, &ofs))
475
		return 0;
476
	/*
L
Lucas De Marchi 已提交
477
	 * Return ra if an exception occurred at the first instruction
478
	 */
479 480 481 482 483
	if (unlikely(ofs == 0)) {
		pc = *ra;
		*ra = 0;
		return pc;
	}
484 485 486

	info.func = (void *)(pc - ofs);
	info.func_size = ofs;	/* analyze from start to ofs */
F
Franck Bui-Huu 已提交
487 488
	leaf = get_frame_info(&info);
	if (leaf < 0)
489
		return 0;
F
Franck Bui-Huu 已提交
490 491 492

	if (*sp < stack_page ||
	    *sp + info.frame_size > stack_page + THREAD_SIZE - 32)
493 494
		return 0;

F
Franck Bui-Huu 已提交
495 496 497 498 499 500 501
	if (leaf)
		/*
		 * For some extreme cases, get_frame_info() can
		 * consider wrongly a nested function as a leaf
		 * one. In that cases avoid to return always the
		 * same value.
		 */
502
		pc = pc != *ra ? *ra : 0;
F
Franck Bui-Huu 已提交
503 504 505 506
	else
		pc = ((unsigned long *)(*sp))[info.pc_offset];

	*sp += info.frame_size;
507
	*ra = 0;
F
Franck Bui-Huu 已提交
508
	return __kernel_text_address(pc) ? pc : 0;
509
}
510 511 512 513 514 515 516 517 518
EXPORT_SYMBOL(unwind_stack_by_address);

/* used by show_backtrace() */
unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
			   unsigned long pc, unsigned long *ra)
{
	unsigned long stack_page = (unsigned long)task_stack_page(task);
	return unwind_stack_by_address(stack_page, sp, pc, ra);
}
519
#endif
520 521 522 523 524 525 526 527 528

/*
 * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
 */
unsigned long get_wchan(struct task_struct *task)
{
	unsigned long pc = 0;
#ifdef CONFIG_KALLSYMS
	unsigned long sp;
529
	unsigned long ra = 0;
530 531 532 533 534 535 536 537 538 539 540 541 542
#endif

	if (!task || task == current || task->state == TASK_RUNNING)
		goto out;
	if (!task_stack_page(task))
		goto out;

	pc = thread_saved_pc(task);

#ifdef CONFIG_KALLSYMS
	sp = task->thread.reg29 + schedule_mfi.frame_size;

	while (in_sched_functions(pc))
543
		pc = unwind_stack(task, &sp, pc, &ra);
544 545 546 547 548
#endif

out:
	return pc;
}
549 550 551 552 553 554 555 556 557 558 559 560

/*
 * Don't forget that the stack pointer must be aligned on a 8 bytes
 * boundary for 32-bits ABI and 16 bytes for 64-bits ABI.
 */
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 & ALMASK;
}