cregit-Linux how code gets into the kernel

Release 4.10 arch/mips/kernel/ptrace.c

Directory: arch/mips/kernel
/*
 * 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>
#include <linux/context_tracking.h>
#include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/regset.h>
#include <linux/smp.h>
#include <linux/security.h>
#include <linux/stddef.h>
#include <linux/tracehook.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/ftrace.h>

#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/syscall.h>
#include <linux/uaccess.h>
#include <asm/bootinfo.h>
#include <asm/reg.h>


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


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)); /* FCSR has been preset by `mips_set_personality_nan'. */ /* * 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); }

Contributors

PersonTokensPropCommitsCommitProp
paul burtonpaul burton5398.15%150.00%
maciej w. rozyckimaciej w. rozycki11.85%150.00%
Total54100.00%2100.00%

/* * Called by kernel/ptrace.c when detaching.. * * Make sure single step bits etc are not set. */
void ptrace_disable(struct task_struct *child) { /* Don't load the watchpoint registers for the ex-child. */ clear_tsk_thread_flag(child, TIF_LOAD_WATCH); }

Contributors

PersonTokensPropCommitsCommitProp
daniel jacobowitzdaniel jacobowitz1055.56%150.00%
david daneydavid daney844.44%150.00%
Total18100.00%2100.00%

/* * Poke at FCSR according to its mask. Set the Cause bits even * if a corresponding Enable bit is set. This will be noticed at * the time the thread is switched to and SIGFPE thrown accordingly. */
static void ptrace_setfcr31(struct task_struct *child, u32 value) { u32 fcr31; u32 mask; fcr31 = child->thread.fpu.fcr31; mask = boot_cpu_data.fpu_msk31; child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); }

Contributors

PersonTokensPropCommitsCommitProp
maciej w. rozyckimaciej w. rozycki57100.00%1100.00%
Total57100.00%1100.00%

/* * Read a general register set. We always use the 64-bit format, even * for 32-bit kernels and for 32-bit processes on a 64-bit kernel. * Registers are sign extended to fill the available space. */
int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data) { struct pt_regs *regs; int i; if (!access_ok(VERIFY_WRITE, data, 38 * 8)) return -EIO; regs = task_pt_regs(child); for (i = 0; i < 32; i++) __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); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
daniel jacobowitzdaniel jacobowitz12860.66%125.00%
alex smithalex smith6028.44%125.00%
atsushi nemotoatsushi nemoto219.95%125.00%
al viroal viro20.95%125.00%
Total211100.00%4100.00%

/* * 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. */
int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data) { struct pt_regs *regs; int i; if (!access_ok(VERIFY_READ, data, 38 * 8)) return -EIO; regs = task_pt_regs(child); for (i = 0; i < 32; i++) __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); /* badvaddr, status, and cause may not be written. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
daniel jacobowitzdaniel jacobowitz10272.86%133.33%
alex smithalex smith3625.71%133.33%
al viroal viro21.43%133.33%
Total140100.00%3100.00%


int ptrace_getfpregs(struct task_struct *child, __u32 __user *data) { int i; if (!access_ok(VERIFY_WRITE, data, 33 * 8)) return -EIO; if (tsk_used_math(child)) { union fpureg *fregs = get_fpu_regs(child); for (i = 0; i < 32; i++) __put_user(get_fpr64(&fregs[i], 0), i + (__u64 __user *)data); } else { for (i = 0; i < 32; i++) __put_user((__u64) -1, i + (__u64 __user *) data); } __put_user(child->thread.fpu.fcr31, data + 64); __put_user(boot_cpu_data.fpu_id, data + 65); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
daniel jacobowitzdaniel jacobowitz14392.86%125.00%
paul burtonpaul burton106.49%250.00%
alex smithalex smith10.65%125.00%
Total154100.00%4100.00%


int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) { union fpureg *fregs; u64 fpr_val; u32 value; int i; if (!access_ok(VERIFY_READ, data, 33 * 8)) return -EIO; init_fp_ctx(child); fregs = get_fpu_regs(child); for (i = 0; i < 32; i++) { __get_user(fpr_val, i + (__u64 __user *)data); set_fpr64(&fregs[i], 0, fpr_val); } __get_user(value, data + 64); ptrace_setfcr31(child, value); /* FIR may not be written. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
daniel jacobowitzdaniel jacobowitz7057.85%114.29%
paul burtonpaul burton2823.14%342.86%
maciej w. rozyckimaciej w. rozycki1512.40%228.57%
linus torvaldslinus torvalds86.61%114.29%
Total121100.00%7100.00%


int ptrace_get_watch_regs(struct task_struct *child, struct pt_watch_regs __user *addr) { enum pt_watch_style style; int i; if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) 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); __put_user(boot_cpu_data.watch_reg_use_cnt, &addr->WATCH_STYLE.num_valid); for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __put_user(child->thread.watch.mips3264.watchlo[i], &addr->WATCH_STYLE.watchlo[i]); __put_user(child->thread.watch.mips3264.watchhi[i] & (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW), &addr->WATCH_STYLE.watchhi[i]); __put_user(boot_cpu_data.watch_reg_masks[i], &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; }

Contributors

PersonTokensPropCommitsCommitProp
david daneydavid daney25196.54%133.33%
james hoganjames hogan51.92%133.33%
alex smithalex smith41.54%133.33%
Total260100.00%3100.00%


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]; if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) return -EIO; if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) return -EIO; /* Check the values. */ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __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] & ~MIPS_WATCHHI_MASK) return -EINVAL; } /* Install them. */ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { if (lt[i] & MIPS_WATCHLO_IRW) 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; }

Contributors

PersonTokensPropCommitsCommitProp
david daneydavid daney28598.28%133.33%
alex smithalex smith31.03%133.33%
james hoganjames hogan20.69%133.33%
Total290100.00%3100.00%

/* regset get/set implementations */ #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) { struct pt_regs *regs = task_pt_regs(target); 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; return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, sizeof(uregs)); }

Contributors

PersonTokensPropCommitsCommitProp
alex smithalex smith175100.00%1100.00%
Total175100.00%1100.00%


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) { 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; }

Contributors

PersonTokensPropCommitsCommitProp
alex smithalex smith227100.00%1100.00%
Total227100.00%1100.00%

#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)); }

Contributors

PersonTokensPropCommitsCommitProp
alex smithalex smith10962.29%150.00%
ralf baechleralf baechle6637.71%150.00%
Total175100.00%2100.00%


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; 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; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
alex smithalex smith14165.89%150.00%
ralf baechleralf baechle7334.11%150.00%
Total214100.00%2100.00%

#endif /* CONFIG_64BIT */
static int fpr_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { unsigned i; int err; u64 fpr_val; /* XXX fcr31 */ 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; }

Contributors

PersonTokensPropCommitsCommitProp
paul burtonpaul burton11363.84%150.00%
ralf baechleralf baechle6436.16%150.00%
Total177100.00%2100.00%


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) { unsigned i; int err; u64 fpr_val; /* XXX fcr31 */ init_fp_ctx(target); 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; }

Contributors

PersonTokensPropCommitsCommitProp
paul burtonpaul burton11864.13%266.67%
ralf baechleralf baechle6635.87%133.33%
Total184100.00%3100.00%

enum mips_regset { REGSET_GPR, REGSET_FPR, }; struct pt_regs_offset { const char *name; int offset; }; #define REG_OFFSET_NAME(reg, r) { \ .name = #reg, \ .offset = offsetof(struct pt_regs, r) \ } #define REG_OFFSET_END { \ .name = NULL, \ .offset = 0 \ } static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(r0, regs[0]), REG_OFFSET_NAME(r1, regs[1]), REG_OFFSET_NAME(r2, regs[2]), REG_OFFSET_NAME(r3, regs[3]), REG_OFFSET_NAME(r4, regs[4]), REG_OFFSET_NAME(r5, regs[5]), REG_OFFSET_NAME(r6, regs[6]), REG_OFFSET_NAME(r7, regs[7]), REG_OFFSET_NAME(r8, regs[8]), REG_OFFSET_NAME(r9, regs[9]), REG_OFFSET_NAME(r10, regs[10]), REG_OFFSET_NAME(r11, regs[11]), REG_OFFSET_NAME(r12, regs[12]), REG_OFFSET_NAME(r13, regs[13]), REG_OFFSET_NAME(r14, regs[14]), REG_OFFSET_NAME(r15, regs[15]), REG_OFFSET_NAME(r16, regs[16]), REG_OFFSET_NAME(r17, regs[17]), REG_OFFSET_NAME(r18, regs[18]), REG_OFFSET_NAME(r19, regs[19]), REG_OFFSET_NAME(r20, regs[20]), REG_OFFSET_NAME(r21, regs[21]), REG_OFFSET_NAME(r22, regs[22]), REG_OFFSET_NAME(r23, regs[23]), REG_OFFSET_NAME(r24, regs[24]), REG_OFFSET_NAME(r25, regs[25]), REG_OFFSET_NAME(r26, regs[26]), REG_OFFSET_NAME(r27, regs[27]), REG_OFFSET_NAME(r28, regs[28]), REG_OFFSET_NAME(r29, regs[29]), REG_OFFSET_NAME(r30, regs[30]), REG_OFFSET_NAME(r31, regs[31]), REG_OFFSET_NAME(c0_status, cp0_status), REG_OFFSET_NAME(hi, hi), REG_OFFSET_NAME(lo, lo), #ifdef CONFIG_CPU_HAS_SMARTMIPS REG_OFFSET_NAME(acx, acx), #endif REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr), REG_OFFSET_NAME(c0_cause, cp0_cause), REG_OFFSET_NAME(c0_epc, cp0_epc), #ifdef CONFIG_CPU_CAVIUM_OCTEON REG_OFFSET_NAME(mpl0, mpl[0]), REG_OFFSET_NAME(mpl1, mpl[1]), REG_OFFSET_NAME(mpl2, mpl[2]), REG_OFFSET_NAME(mtp0, mtp[0]), REG_OFFSET_NAME(mtp1, mtp[1]), REG_OFFSET_NAME(mtp2, mtp[2]), #endif REG_OFFSET_END, }; /** * regs_query_register_offset() - query register offset from its name * @name: the name of a register * * regs_query_register_offset() returns the offset of a register in struct * pt_regs from its name. If the name is invalid, this returns -EINVAL; */
int regs_query_register_offset(const char *name) { const struct pt_regs_offset *roff; for (roff = regoffset_table; roff->name != NULL; roff++) if (!strcmp(roff->name, name)) return roff->offset; return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle52100.00%1100.00%
Total52100.00%1100.00%

#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) 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), .get = gpr32_get, .set = gpr32_set, }, [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), }; #endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ #ifdef CONFIG_64BIT 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), .get = gpr64_get, .set = gpr64_set, }, [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 = { .name = "mips64", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, .regsets = mips64_regsets, .n = ARRAY_SIZE(mips64_regsets), }; #endif /* CONFIG_64BIT */
const struct user_regset_view *task_user_regset_view(struct task_struct *task) { #ifdef CONFIG_32BIT return &user_mips_view; #else #ifdef CONFIG_MIPS32_O32 if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) return &user_mips_view; #endif return &user_mips64_view; #endif }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle3984.78%133.33%
alex smithalex smith715.22%266.67%
Total46100.00%3100.00%


long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { int ret; void __user *addrp = (void __user *) addr; void __user *datavp = (void __user *) data; unsigned long __user *datalp = (void __user *) data; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: ret = generic_ptrace_peekdata(child, addr, data); break; /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; union fpureg *fregs; unsigned long tmp = 0; regs = task_pt_regs(child); ret = 0; /* Default return value. */ switch (addr) { case 0 ... 31: tmp = regs->regs[addr]; break; case FPR_BASE ... FPR_BASE + 31: if (!tsk_used_math(child)) { /* FP not yet used */ tmp = -1; break; } fregs = get_fpu_regs(child); #ifdef CONFIG_32BIT 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. */ tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1); break; } #endif tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); 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; #ifdef CONFIG_CPU_HAS_SMARTMIPS case ACX: tmp = regs->acx; break; #endif case FPC_CSR: tmp = child->thread.fpu.fcr31; break; case FPC_EIR: /* implementation / version register */ tmp = boot_cpu_data.fpu_id; break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; if (!cpu_has_dsp) { tmp = 0; ret = -EIO; goto out; } dregs = __get_dsp_regs(child); tmp = (unsigned long) (dregs[addr - DSP_BASE]); break; } case DSP_CONTROL: if (!cpu_has_dsp) { tmp = 0; ret = -EIO; goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; goto out; } ret = put_user(tmp, datalp); 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: ret = generic_ptrace_pokedata(child, addr, data); break; case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; regs = task_pt_regs(child); switch (addr) { case 0 ... 31: regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { union fpureg *fregs = get_fpu_regs(child); init_fp_ctx(child); #ifdef CONFIG_32BIT 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. */ set_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1, data); break; } #endif set_fpr64(&fregs[addr - FPR_BASE], 0, data); break; } case PC: regs->cp0_epc = data; break; case MMHI: regs->hi = data; break; case MMLO: regs->lo = data; break; #ifdef CONFIG_CPU_HAS_SMARTMIPS case ACX: regs->acx = data; break; #endif case FPC_CSR: init_fp_ctx(child); ptrace_setfcr31(child, data); break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; if (!cpu_has_dsp) { ret = -EIO; break; } dregs = __get_dsp_regs(child); dregs[addr - DSP_BASE] = data; break; } case DSP_CONTROL: if (!cpu_has_dsp) { ret = -EIO; break; } child->thread.dsp.dspcontrol = data; break; default: /* The rest are not allowed. */ ret = -EIO; break; } break; } case PTRACE_GETREGS: ret = ptrace_getregs(child, datavp); break; case PTRACE_SETREGS: ret = ptrace_setregs(child, datavp); break; case PTRACE_GETFPREGS: ret = ptrace_getfpregs(child, datavp); break; case PTRACE_SETFPREGS: ret = ptrace_setfpregs(child, datavp); break; case PTRACE_GET_THREAD_AREA: ret = put_user(task_thread_info(child)->tp_value, datalp); break; case PTRACE_GET_WATCH_REGS: ret = ptrace_get_watch_regs(child, addrp); break; case PTRACE_SET_WATCH_REGS: ret = ptrace_set_watch_regs(child, addrp); break; default: ret = ptrace_request(child, request, addr, data); break; } out: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git30837.38%820.51%
ralf baechleralf baechle21926.58%717.95%
paul burtonpaul burton698.37%410.26%
daniel jacobowitzdaniel jacobowitz587.04%25.13%
namhyung kimnamhyung kim475.70%25.13%
linus torvaldslinus torvalds344.13%37.69%
franck bui-huufranck bui-huu303.64%12.56%
david daneydavid daney242.91%12.56%
christoph hellwigchristoph hellwig101.21%25.13%
maciej w. rozyckimaciej w. rozycki91.09%25.13%
al viroal viro70.85%25.13%
alexey dobriyanalexey dobriyan30.36%25.13%
andrea arcangeliandrea arcangeli30.36%12.56%
andrew mortonandrew morton20.24%12.56%
alex smithalex smith10.12%12.56%
Total824100.00%39100.00%

/* * Notification of system call entry/exit * - triggered by current->work.syscall_trace */
asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) { user_exit(); current_thread_info()->syscall = syscall; if (test_thread_flag(TIF_SYSCALL_TRACE) && tracehook_report_syscall_entry(regs)) return -1; if (secure_computing(NULL) == -1) return -1; if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_enter(regs, regs->regs[2]); audit_syscall_entry(syscall, regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); return syscall; }

Contributors

PersonTokensPropCommitsCommitProp
david woodhousedavid woodhouse3228.57%17.14%
ralf baechleralf baechle3026.79%428.57%
markos chandrasmarkos chandras1614.29%214.29%
kees cookkees cook1412.50%17.14%
lars perssonlars persson76.25%17.14%
pre-gitpre-git76.25%321.43%
andrew mortonandrew morton43.57%17.14%
andy lutomirskiandy lutomirski21.79%17.14%
Total112100.00%14100.00%

/* * Notification of system call entry/exit * - triggered by current->work.syscall_trace */
asmlinkage void syscall_trace_leave(struct pt_regs *regs) { /* * 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(); audit_syscall_exit(regs); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->regs[2]); if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); user_enter(); }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle59100.00%4100.00%
Total59100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle146533.01%1824.32%
alex smithalex smith81018.25%56.76%
david daneydavid daney56812.80%11.35%
daniel jacobowitzdaniel jacobowitz51511.60%22.70%
paul burtonpaul burton3918.81%79.46%
pre-gitpre-git3447.75%1013.51%
maciej w. rozyckimaciej w. rozycki861.94%45.41%
namhyung kimnamhyung kim471.06%22.70%
linus torvaldslinus torvalds461.04%56.76%
david woodhousedavid woodhouse320.72%11.35%
franck bui-huufranck bui-huu300.68%11.35%
atsushi nemotoatsushi nemoto210.47%11.35%
markos chandrasmarkos chandras160.36%22.70%
kees cookkees cook140.32%11.35%
al viroal viro110.25%22.70%
christoph hellwigchristoph hellwig100.23%22.70%
lars perssonlars persson70.16%11.35%
james hoganjames hogan70.16%11.35%
andrew mortonandrew morton60.14%22.70%
andrea arcangeliandrea arcangeli30.07%11.35%
alexey dobriyanalexey dobriyan30.07%22.70%
jesper juhljesper juhl20.05%11.35%
andy lutomirskiandy lutomirski20.05%11.35%
yoichi yuasayoichi yuasa20.05%11.35%
Total4438100.00%74100.00%
Directory: arch/mips/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.