1/* 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6#include <stdio.h> 7#include <stddef.h> 8#include <errno.h> 9#include <unistd.h> 10#include "ptrace_user.h" 11/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */ 12#include <asm/user.h> 13#include "kern_util.h" 14#include "sysdep/thread.h" 15#include "user.h" 16#include "os.h" 17#include "uml-config.h" 18 19int ptrace_getregs(long pid, unsigned long *regs_out) 20{ 21 if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) 22 return -errno; 23 return 0; 24} 25 26int ptrace_setregs(long pid, unsigned long *regs) 27{ 28 if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) 29 return -errno; 30 return 0; 31} 32 33int ptrace_getfpregs(long pid, unsigned long *regs) 34{ 35 if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0) 36 return -errno; 37 return 0; 38} 39 40int ptrace_setfpregs(long pid, unsigned long *regs) 41{ 42 if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) 43 return -errno; 44 return 0; 45} 46 47#ifdef UML_CONFIG_MODE_TT 48 49static void write_debugregs(int pid, unsigned long *regs) 50{ 51 struct user *dummy; 52 int nregs, i; 53 54 dummy = NULL; 55 nregs = ARRAY_SIZE(dummy->u_debugreg); 56 for(i = 0; i < nregs; i++){ 57 if((i == 4) || (i == 5)) continue; 58 if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], 59 regs[i]) < 0) 60 printk("write_debugregs - ptrace failed on " 61 "register %d, value = 0x%lx, errno = %d\n", i, 62 regs[i], errno); 63 } 64} 65 66static void read_debugregs(int pid, unsigned long *regs) 67{ 68 struct user *dummy; 69 int nregs, i; 70 71 dummy = NULL; 72 nregs = ARRAY_SIZE(dummy->u_debugreg); 73 for(i = 0; i < nregs; i++){ 74 regs[i] = ptrace(PTRACE_PEEKUSR, pid, 75 &dummy->u_debugreg[i], 0); 76 } 77} 78 79/* Accessed only by the tracing thread */ 80static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; 81 82void arch_enter_kernel(void *task, int pid) 83{ 84 read_debugregs(pid, TASK_DEBUGREGS(task)); 85 write_debugregs(pid, kernel_debugregs); 86} 87 88void arch_leave_kernel(void *task, int pid) 89{ 90 read_debugregs(pid, kernel_debugregs); 91 write_debugregs(pid, TASK_DEBUGREGS(task)); 92} 93 94#ifdef UML_CONFIG_PT_PROXY 95/* Accessed only by the tracing thread */ 96static int debugregs_seq; 97 98/* Only called by the ptrace proxy */ 99void ptrace_pokeuser(unsigned long addr, unsigned long data) 100{ 101 if((addr < offsetof(struct user, u_debugreg[0])) || 102 (addr > offsetof(struct user, u_debugreg[7]))) 103 return; 104 addr -= offsetof(struct user, u_debugreg[0]); 105 addr = addr >> 2; 106 if(kernel_debugregs[addr] == data) return; 107 108 kernel_debugregs[addr] = data; 109 debugregs_seq++; 110} 111 112static void update_debugregs_cb(void *arg) 113{ 114 int pid = *((int *) arg); 115 116 write_debugregs(pid, kernel_debugregs); 117} 118 119/* Optimized out in its header when not defined */ 120void update_debugregs(int seq) 121{ 122 int me; 123 124 if(seq == debugregs_seq) return; 125 126 me = os_getpid(); 127 initial_thread_cb(update_debugregs_cb, &me); 128} 129#endif 130 131#endif 132