ptrace.c 19.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * 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) 1992 Ross Biro
 * Copyright (C) Linus Torvalds
 * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
 * Copyright (C) 1996 David S. Miller
 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
 * Copyright (C) 1999 MIPS Technologies, Inc.
 * Copyright (C) 2000 Ulf Carlsson
 *
 * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
 * binaries.
 */
#include <linux/compiler.h>
18
#include <linux/context_tracking.h>
19
#include <linux/elf.h>
L
Linus Torvalds 已提交
20 21 22 23 24
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
25
#include <linux/regset.h>
L
Linus Torvalds 已提交
26 27
#include <linux/smp.h>
#include <linux/security.h>
28
#include <linux/tracehook.h>
29 30
#include <linux/audit.h>
#include <linux/seccomp.h>
31
#include <linux/ftrace.h>
L
Linus Torvalds 已提交
32

33
#include <asm/byteorder.h>
L
Linus Torvalds 已提交
34
#include <asm/cpu.h>
35
#include <asm/cpu-info.h>
36
#include <asm/dsp.h>
L
Linus Torvalds 已提交
37 38
#include <asm/fpu.h>
#include <asm/mipsregs.h>
39
#include <asm/mipsmtregs.h>
L
Linus Torvalds 已提交
40 41
#include <asm/pgtable.h>
#include <asm/page.h>
42
#include <asm/syscall.h>
L
Linus Torvalds 已提交
43 44
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
45
#include <asm/reg.h>
L
Linus Torvalds 已提交
46

47 48 49
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
static void init_fp_ctx(struct task_struct *target)
{
	/* If FP has been used then the target already has context */
	if (tsk_used_math(target))
		return;

	/* Begin with data registers set to all 1s... */
	memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));

	/* ...and FCSR zeroed */
	target->thread.fpu.fcr31 = 0;

	/*
	 * Record that the target has "used" math, such that the context
	 * just initialised, and any modifications made by the caller,
	 * aren't discarded.
	 */
	set_stopped_child_used_math(target);
}

L
Linus Torvalds 已提交
70 71 72 73 74 75 76
/*
 * Called by kernel/ptrace.c when detaching..
 *
 * Make sure single step bits etc are not set.
 */
void ptrace_disable(struct task_struct *child)
{
77 78
	/* Don't load the watchpoint registers for the ex-child. */
	clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
L
Linus Torvalds 已提交
79 80
}

81
/*
R
Ralf Baechle 已提交
82
 * Read a general register set.	 We always use the 64-bit format, even
83 84 85
 * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
 * Registers are sign extended to fill the available space.
 */
86
int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
87 88 89 90 91 92 93
{
	struct pt_regs *regs;
	int i;

	if (!access_ok(VERIFY_WRITE, data, 38 * 8))
		return -EIO;

A
Al Viro 已提交
94
	regs = task_pt_regs(child);
95 96

	for (i = 0; i < 32; i++)
97 98 99 100 101 102 103
		__put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
	__put_user((long)regs->lo, (__s64 __user *)&data->lo);
	__put_user((long)regs->hi, (__s64 __user *)&data->hi);
	__put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
	__put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
	__put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
	__put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
104 105 106 107 108 109 110 111 112

	return 0;
}

/*
 * Write a general register set.  As for PTRACE_GETREGS, we always use
 * the 64-bit format.  On a 32-bit kernel only the lower order half
 * (according to endianness) will be used.
 */
113
int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
114 115 116 117 118 119 120
{
	struct pt_regs *regs;
	int i;

	if (!access_ok(VERIFY_READ, data, 38 * 8))
		return -EIO;

A
Al Viro 已提交
121
	regs = task_pt_regs(child);
122 123

	for (i = 0; i < 32; i++)
124 125 126 127
		__get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
	__get_user(regs->lo, (__s64 __user *)&data->lo);
	__get_user(regs->hi, (__s64 __user *)&data->hi);
	__get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
128 129 130 131 132 133

	/* badvaddr, status, and cause may not be written.  */

	return 0;
}

134
int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
135 136 137 138 139 140 141
{
	int i;

	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
		return -EIO;

	if (tsk_used_math(child)) {
P
Paul Burton 已提交
142
		union fpureg *fregs = get_fpu_regs(child);
143
		for (i = 0; i < 32; i++)
P
Paul Burton 已提交
144 145
			__put_user(get_fpr64(&fregs[i], 0),
				   i + (__u64 __user *)data);
146 147
	} else {
		for (i = 0; i < 32; i++)
148
			__put_user((__u64) -1, i + (__u64 __user *) data);
149 150
	}

151
	__put_user(child->thread.fpu.fcr31, data + 64);
152
	__put_user(boot_cpu_data.fpu_id, data + 65);
153 154 155 156

	return 0;
}

157
int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
158
{
P
Paul Burton 已提交
159 160
	union fpureg *fregs;
	u64 fpr_val;
161 162 163
	u32 fcr31;
	u32 value;
	u32 mask;
164 165 166 167 168
	int i;

	if (!access_ok(VERIFY_READ, data, 33 * 8))
		return -EIO;

169
	init_fp_ctx(child);
170 171
	fregs = get_fpu_regs(child);

P
Paul Burton 已提交
172 173 174 175
	for (i = 0; i < 32; i++) {
		__get_user(fpr_val, i + (__u64 __user *)data);
		set_fpr64(&fregs[i], 0, fpr_val);
	}
176

177 178
	__get_user(value, data + 64);
	fcr31 = child->thread.fpu.fcr31;
179
	mask = boot_cpu_data.fpu_msk31;
180
	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
181 182 183 184 185 186

	/* FIR may not be written.  */

	return 0;
}

187 188 189 190 191 192
int ptrace_get_watch_regs(struct task_struct *child,
			  struct pt_watch_regs __user *addr)
{
	enum pt_watch_style style;
	int i;

193
	if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
194 195 196 197 198 199 200 201 202 203 204 205 206
		return -EIO;
	if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
		return -EIO;

#ifdef CONFIG_32BIT
	style = pt_watch_style_mips32;
#define WATCH_STYLE mips32
#else
	style = pt_watch_style_mips64;
#define WATCH_STYLE mips64
#endif

	__put_user(style, &addr->style);
207
	__put_user(boot_cpu_data.watch_reg_use_cnt,
208
		   &addr->WATCH_STYLE.num_valid);
209
	for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
210 211 212 213
		__put_user(child->thread.watch.mips3264.watchlo[i],
			   &addr->WATCH_STYLE.watchlo[i]);
		__put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
			   &addr->WATCH_STYLE.watchhi[i]);
214
		__put_user(boot_cpu_data.watch_reg_masks[i],
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
			   &addr->WATCH_STYLE.watch_masks[i]);
	}
	for (; i < 8; i++) {
		__put_user(0, &addr->WATCH_STYLE.watchlo[i]);
		__put_user(0, &addr->WATCH_STYLE.watchhi[i]);
		__put_user(0, &addr->WATCH_STYLE.watch_masks[i]);
	}

	return 0;
}

int ptrace_set_watch_regs(struct task_struct *child,
			  struct pt_watch_regs __user *addr)
{
	int i;
	int watch_active = 0;
	unsigned long lt[NUM_WATCH_REGS];
	u16 ht[NUM_WATCH_REGS];

234
	if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
235 236 237 238
		return -EIO;
	if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
		return -EIO;
	/* Check the values. */
239
	for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
		__get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]);
#ifdef CONFIG_32BIT
		if (lt[i] & __UA_LIMIT)
			return -EINVAL;
#else
		if (test_tsk_thread_flag(child, TIF_32BIT_ADDR)) {
			if (lt[i] & 0xffffffff80000000UL)
				return -EINVAL;
		} else {
			if (lt[i] & __UA_LIMIT)
				return -EINVAL;
		}
#endif
		__get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]);
		if (ht[i] & ~0xff8)
			return -EINVAL;
	}
	/* Install them. */
258
	for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
		if (lt[i] & 7)
			watch_active = 1;
		child->thread.watch.mips3264.watchlo[i] = lt[i];
		/* Set the G bit. */
		child->thread.watch.mips3264.watchhi[i] = ht[i];
	}

	if (watch_active)
		set_tsk_thread_flag(child, TIF_LOAD_WATCH);
	else
		clear_tsk_thread_flag(child, TIF_LOAD_WATCH);

	return 0;
}

274 275
/* regset get/set implementations */

276 277 278 279 280 281
#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)

static int gpr32_get(struct task_struct *target,
		     const struct user_regset *regset,
		     unsigned int pos, unsigned int count,
		     void *kbuf, void __user *ubuf)
282 283
{
	struct pt_regs *regs = task_pt_regs(target);
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
	u32 uregs[ELF_NGREG] = {};
	unsigned i;

	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
		/* k0/k1 are copied as zero. */
		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
			continue;

		uregs[i] = regs->regs[i - MIPS32_EF_R0];
	}

	uregs[MIPS32_EF_LO] = regs->lo;
	uregs[MIPS32_EF_HI] = regs->hi;
	uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
	uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
	uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
	uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
301

302 303
	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
				   sizeof(uregs));
304 305
}

306 307 308 309
static int gpr32_set(struct task_struct *target,
		     const struct user_regset *regset,
		     unsigned int pos, unsigned int count,
		     const void *kbuf, const void __user *ubuf)
310
{
311 312 313 314 315 316 317 318 319 320 321 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 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
	struct pt_regs *regs = task_pt_regs(target);
	u32 uregs[ELF_NGREG];
	unsigned start, num_regs, i;
	int err;

	start = pos / sizeof(u32);
	num_regs = count / sizeof(u32);

	if (start + num_regs > ELF_NGREG)
		return -EIO;

	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
				 sizeof(uregs));
	if (err)
		return err;

	for (i = start; i < num_regs; i++) {
		/*
		 * Cast all values to signed here so that if this is a 64-bit
		 * kernel, the supplied 32-bit values will be sign extended.
		 */
		switch (i) {
		case MIPS32_EF_R1 ... MIPS32_EF_R25:
			/* k0/k1 are ignored. */
		case MIPS32_EF_R28 ... MIPS32_EF_R31:
			regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
			break;
		case MIPS32_EF_LO:
			regs->lo = (s32)uregs[i];
			break;
		case MIPS32_EF_HI:
			regs->hi = (s32)uregs[i];
			break;
		case MIPS32_EF_CP0_EPC:
			regs->cp0_epc = (s32)uregs[i];
			break;
		}
	}

	return 0;
}

#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */

#ifdef CONFIG_64BIT

static int gpr64_get(struct task_struct *target,
		     const struct user_regset *regset,
		     unsigned int pos, unsigned int count,
		     void *kbuf, void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	u64 uregs[ELF_NGREG] = {};
	unsigned i;

	for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
		/* k0/k1 are copied as zero. */
		if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
			continue;

		uregs[i] = regs->regs[i - MIPS64_EF_R0];
	}

	uregs[MIPS64_EF_LO] = regs->lo;
	uregs[MIPS64_EF_HI] = regs->hi;
	uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
	uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
	uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
	uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;

	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
				   sizeof(uregs));
}
384

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
static int gpr64_set(struct task_struct *target,
		     const struct user_regset *regset,
		     unsigned int pos, unsigned int count,
		     const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	u64 uregs[ELF_NGREG];
	unsigned start, num_regs, i;
	int err;

	start = pos / sizeof(u64);
	num_regs = count / sizeof(u64);

	if (start + num_regs > ELF_NGREG)
		return -EIO;
400

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
				 sizeof(uregs));
	if (err)
		return err;

	for (i = start; i < num_regs; i++) {
		switch (i) {
		case MIPS64_EF_R1 ... MIPS64_EF_R25:
			/* k0/k1 are ignored. */
		case MIPS64_EF_R28 ... MIPS64_EF_R31:
			regs->regs[i - MIPS64_EF_R0] = uregs[i];
			break;
		case MIPS64_EF_LO:
			regs->lo = uregs[i];
			break;
		case MIPS64_EF_HI:
			regs->hi = uregs[i];
			break;
		case MIPS64_EF_CP0_EPC:
			regs->cp0_epc = uregs[i];
			break;
		}
	}
424 425 426 427

	return 0;
}

428 429
#endif /* CONFIG_64BIT */

430 431 432 433 434
static int fpr_get(struct task_struct *target,
		   const struct user_regset *regset,
		   unsigned int pos, unsigned int count,
		   void *kbuf, void __user *ubuf)
{
435 436 437 438
	unsigned i;
	int err;
	u64 fpr_val;

439
	/* XXX fcr31  */
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455

	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
					   &target->thread.fpu,
					   0, sizeof(elf_fpregset_t));

	for (i = 0; i < NUM_FPU_REGS; i++) {
		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
					  &fpr_val, i * sizeof(elf_fpreg_t),
					  (i + 1) * sizeof(elf_fpreg_t));
		if (err)
			return err;
	}

	return 0;
456 457 458 459 460 461 462
}

static int fpr_set(struct task_struct *target,
		   const struct user_regset *regset,
		   unsigned int pos, unsigned int count,
		   const void *kbuf, const void __user *ubuf)
{
463 464 465 466
	unsigned i;
	int err;
	u64 fpr_val;

467
	/* XXX fcr31  */
468

469 470
	init_fp_ctx(target);

471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					  &target->thread.fpu,
					  0, sizeof(elf_fpregset_t));

	for (i = 0; i < NUM_FPU_REGS; i++) {
		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 &fpr_val, i * sizeof(elf_fpreg_t),
					 (i + 1) * sizeof(elf_fpreg_t));
		if (err)
			return err;
		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
	}

	return 0;
486 487 488 489 490 491 492
}

enum mips_regset {
	REGSET_GPR,
	REGSET_FPR,
};

493 494
#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)

495 496 497 498 499 500
static const struct user_regset mips_regsets[] = {
	[REGSET_GPR] = {
		.core_note_type	= NT_PRSTATUS,
		.n		= ELF_NGREG,
		.size		= sizeof(unsigned int),
		.align		= sizeof(unsigned int),
501 502
		.get		= gpr32_get,
		.set		= gpr32_set,
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
	},
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
};

static const struct user_regset_view user_mips_view = {
	.name		= "mips",
	.e_machine	= ELF_ARCH,
	.ei_osabi	= ELF_OSABI,
	.regsets	= mips_regsets,
	.n		= ARRAY_SIZE(mips_regsets),
};

522 523 524 525
#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */

#ifdef CONFIG_64BIT

526 527 528 529 530 531
static const struct user_regset mips64_regsets[] = {
	[REGSET_GPR] = {
		.core_note_type	= NT_PRSTATUS,
		.n		= ELF_NGREG,
		.size		= sizeof(unsigned long),
		.align		= sizeof(unsigned long),
532 533
		.get		= gpr64_get,
		.set		= gpr64_set,
534 535 536 537 538 539 540 541 542 543 544 545
	},
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
};

static const struct user_regset_view user_mips64_view = {
546
	.name		= "mips64",
547 548 549
	.e_machine	= ELF_ARCH,
	.ei_osabi	= ELF_OSABI,
	.regsets	= mips64_regsets,
550
	.n		= ARRAY_SIZE(mips64_regsets),
551 552
};

553 554
#endif /* CONFIG_64BIT */

555 556 557 558
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
#ifdef CONFIG_32BIT
	return &user_mips_view;
559
#else
560
#ifdef CONFIG_MIPS32_O32
561 562
	if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
		return &user_mips_view;
563 564
#endif
	return &user_mips64_view;
565
#endif
566 567
}

568 569
long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
L
Linus Torvalds 已提交
570 571
{
	int ret;
572 573 574
	void __user *addrp = (void __user *) addr;
	void __user *datavp = (void __user *) data;
	unsigned long __user *datalp = (void __user *) data;
L
Linus Torvalds 已提交
575 576 577 578

	switch (request) {
	/* when I and D space are separate, these will need to be fixed. */
	case PTRACE_PEEKTEXT: /* read word at location addr. */
A
Alexey Dobriyan 已提交
579 580
	case PTRACE_PEEKDATA:
		ret = generic_ptrace_peekdata(child, addr, data);
L
Linus Torvalds 已提交
581 582 583 584 585
		break;

	/* Read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR: {
		struct pt_regs *regs;
P
Paul Burton 已提交
586
		union fpureg *fregs;
L
Linus Torvalds 已提交
587 588
		unsigned long tmp = 0;

A
Al Viro 已提交
589
		regs = task_pt_regs(child);
L
Linus Torvalds 已提交
590 591 592 593 594 595 596
		ret = 0;  /* Default return value. */

		switch (addr) {
		case 0 ... 31:
			tmp = regs->regs[addr];
			break;
		case FPR_BASE ... FPR_BASE + 31:
597 598 599 600 601 602
			if (!tsk_used_math(child)) {
				/* FP not yet used */
				tmp = -1;
				break;
			}
			fregs = get_fpu_regs(child);
L
Linus Torvalds 已提交
603

604
#ifdef CONFIG_32BIT
605
			if (test_thread_flag(TIF_32BIT_FPREGS)) {
L
Linus Torvalds 已提交
606 607 608 609 610
				/*
				 * The odd registers are actually the high
				 * order bits of the values stored in the even
				 * registers - unless we're using r2k_switch.S.
				 */
P
Paul Burton 已提交
611 612
				tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
						addr & 1);
613
				break;
L
Linus Torvalds 已提交
614
			}
615
#endif
P
Paul Burton 已提交
616
			tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
L
Linus Torvalds 已提交
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
			break;
		case PC:
			tmp = regs->cp0_epc;
			break;
		case CAUSE:
			tmp = regs->cp0_cause;
			break;
		case BADVADDR:
			tmp = regs->cp0_badvaddr;
			break;
		case MMHI:
			tmp = regs->hi;
			break;
		case MMLO:
			tmp = regs->lo;
			break;
633 634 635 636 637
#ifdef CONFIG_CPU_HAS_SMARTMIPS
		case ACX:
			tmp = regs->acx;
			break;
#endif
L
Linus Torvalds 已提交
638
		case FPC_CSR:
639
			tmp = child->thread.fpu.fcr31;
L
Linus Torvalds 已提交
640
			break;
641 642
		case FPC_EIR:
			/* implementation / version register */
643
			tmp = boot_cpu_data.fpu_id;
L
Linus Torvalds 已提交
644
			break;
645 646 647
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

648 649 650
			if (!cpu_has_dsp) {
				tmp = 0;
				ret = -EIO;
651
				goto out;
652
			}
R
Ralf Baechle 已提交
653 654
			dregs = __get_dsp_regs(child);
			tmp = (unsigned long) (dregs[addr - DSP_BASE]);
655
			break;
656
		}
657 658 659 660
		case DSP_CONTROL:
			if (!cpu_has_dsp) {
				tmp = 0;
				ret = -EIO;
661
				goto out;
662 663 664
			}
			tmp = child->thread.dsp.dspcontrol;
			break;
L
Linus Torvalds 已提交
665 666 667
		default:
			tmp = 0;
			ret = -EIO;
668
			goto out;
L
Linus Torvalds 已提交
669
		}
670
		ret = put_user(tmp, datalp);
L
Linus Torvalds 已提交
671 672 673 674 675 676
		break;
	}

	/* when I and D space are separate, this will have to be fixed. */
	case PTRACE_POKETEXT: /* write the word at location addr. */
	case PTRACE_POKEDATA:
A
Alexey Dobriyan 已提交
677
		ret = generic_ptrace_pokedata(child, addr, data);
L
Linus Torvalds 已提交
678 679 680 681 682
		break;

	case PTRACE_POKEUSR: {
		struct pt_regs *regs;
		ret = 0;
A
Al Viro 已提交
683
		regs = task_pt_regs(child);
L
Linus Torvalds 已提交
684 685 686 687 688 689

		switch (addr) {
		case 0 ... 31:
			regs->regs[addr] = data;
			break;
		case FPR_BASE ... FPR_BASE + 31: {
P
Paul Burton 已提交
690
			union fpureg *fregs = get_fpu_regs(child);
L
Linus Torvalds 已提交
691

692
			init_fp_ctx(child);
693
#ifdef CONFIG_32BIT
694 695 696 697 698 699
			if (test_thread_flag(TIF_32BIT_FPREGS)) {
				/*
				 * The odd registers are actually the high
				 * order bits of the values stored in the even
				 * registers - unless we're using r2k_switch.S.
				 */
P
Paul Burton 已提交
700 701
				set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
					  addr & 1, data);
702
				break;
L
Linus Torvalds 已提交
703 704
			}
#endif
P
Paul Burton 已提交
705
			set_fpr64(&fregs[addr - FPR_BASE], 0, data);
L
Linus Torvalds 已提交
706 707 708 709 710 711 712 713 714 715 716
			break;
		}
		case PC:
			regs->cp0_epc = data;
			break;
		case MMHI:
			regs->hi = data;
			break;
		case MMLO:
			regs->lo = data;
			break;
717 718 719 720 721
#ifdef CONFIG_CPU_HAS_SMARTMIPS
		case ACX:
			regs->acx = data;
			break;
#endif
L
Linus Torvalds 已提交
722
		case FPC_CSR:
723
			child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
L
Linus Torvalds 已提交
724
			break;
725 726 727
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

728 729 730 731 732
			if (!cpu_has_dsp) {
				ret = -EIO;
				break;
			}

733
			dregs = __get_dsp_regs(child);
734 735
			dregs[addr - DSP_BASE] = data;
			break;
736
		}
737 738 739 740 741 742 743
		case DSP_CONTROL:
			if (!cpu_has_dsp) {
				ret = -EIO;
				break;
			}
			child->thread.dsp.dspcontrol = data;
			break;
L
Linus Torvalds 已提交
744 745 746 747 748 749 750 751
		default:
			/* The rest are not allowed. */
			ret = -EIO;
			break;
		}
		break;
		}

752
	case PTRACE_GETREGS:
753
		ret = ptrace_getregs(child, datavp);
754 755 756
		break;

	case PTRACE_SETREGS:
757
		ret = ptrace_setregs(child, datavp);
758 759 760
		break;

	case PTRACE_GETFPREGS:
761
		ret = ptrace_getfpregs(child, datavp);
762 763 764
		break;

	case PTRACE_SETFPREGS:
765
		ret = ptrace_setfpregs(child, datavp);
766 767
		break;

R
Ralf Baechle 已提交
768
	case PTRACE_GET_THREAD_AREA:
769
		ret = put_user(task_thread_info(child)->tp_value, datalp);
R
Ralf Baechle 已提交
770 771
		break;

772
	case PTRACE_GET_WATCH_REGS:
773
		ret = ptrace_get_watch_regs(child, addrp);
774 775 776
		break;

	case PTRACE_SET_WATCH_REGS:
777
		ret = ptrace_set_watch_regs(child, addrp);
778 779
		break;

L
Linus Torvalds 已提交
780 781 782 783
	default:
		ret = ptrace_request(child, request, addr, data);
		break;
	}
784
 out:
L
Linus Torvalds 已提交
785 786 787 788 789 790 791
	return ret;
}

/*
 * Notification of system call entry/exit
 * - triggered by current->work.syscall_trace
 */
792
asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
L
Linus Torvalds 已提交
793
{
794
	long ret = 0;
795 796
	user_exit();

797 798
	current_thread_info()->syscall = syscall;

799
	if (secure_computing() == -1)
800
		return -1;
L
Linus Torvalds 已提交
801

802 803 804
	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
	    tracehook_report_syscall_entry(regs))
		ret = -1;
805

806 807 808
	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_enter(regs, regs->regs[2]);

809
	audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
810
			    regs->regs[6], regs->regs[7]);
811
	return syscall;
L
Linus Torvalds 已提交
812
}
813 814 815 816 817 818 819

/*
 * Notification of system call entry/exit
 * - triggered by current->work.syscall_trace
 */
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
820 821 822 823 824 825 826
        /*
	 * We may come here right after calling schedule_user()
	 * or do_notify_resume(), in which case we can be in RCU
	 * user mode.
	 */
	user_exit();

827
	audit_syscall_exit(regs);
828

829 830 831
	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_exit(regs, regs->regs[2]);

832 833
	if (test_thread_flag(TIF_SYSCALL_TRACE))
		tracehook_report_syscall_exit(regs, 0);
834 835

	user_enter();
836
}