xref: /openbmc/linux/arch/x86/um/ptrace_64.c (revision 4f3db074)
1 /*
2  * Copyright 2003 PathScale, Inc.
3  * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4  *
5  * Licensed under the GPL
6  */
7 
8 #include <linux/mm.h>
9 #include <linux/sched.h>
10 #include <linux/errno.h>
11 #define __FRAME_OFFSETS
12 #include <asm/ptrace.h>
13 #include <asm/uaccess.h>
14 
15 /*
16  * determines which flags the user has access to.
17  * 1 = access 0 = no access
18  */
19 #define FLAG_MASK 0x44dd5UL
20 
21 static const int reg_offsets[] =
22 {
23 	[R8 >> 3] = HOST_R8,
24 	[R9 >> 3] = HOST_R9,
25 	[R10 >> 3] = HOST_R10,
26 	[R11 >> 3] = HOST_R11,
27 	[R12 >> 3] = HOST_R12,
28 	[R13 >> 3] = HOST_R13,
29 	[R14 >> 3] = HOST_R14,
30 	[R15 >> 3] = HOST_R15,
31 	[RIP >> 3] = HOST_IP,
32 	[RSP >> 3] = HOST_SP,
33 	[RAX >> 3] = HOST_AX,
34 	[RBX >> 3] = HOST_BX,
35 	[RCX >> 3] = HOST_CX,
36 	[RDX >> 3] = HOST_DX,
37 	[RSI >> 3] = HOST_SI,
38 	[RDI >> 3] = HOST_DI,
39 	[RBP >> 3] = HOST_BP,
40 	[CS >> 3] = HOST_CS,
41 	[SS >> 3] = HOST_SS,
42 	[FS_BASE >> 3] = HOST_FS_BASE,
43 	[GS_BASE >> 3] = HOST_GS_BASE,
44 	[DS >> 3] = HOST_DS,
45 	[ES >> 3] = HOST_ES,
46 	[FS >> 3] = HOST_FS,
47 	[GS >> 3] = HOST_GS,
48 	[EFLAGS >> 3] = HOST_EFLAGS,
49 	[ORIG_RAX >> 3] = HOST_ORIG_AX,
50 };
51 
52 int putreg(struct task_struct *child, int regno, unsigned long value)
53 {
54 #ifdef TIF_IA32
55 	/*
56 	 * Some code in the 64bit emulation may not be 64bit clean.
57 	 * Don't take any chances.
58 	 */
59 	if (test_tsk_thread_flag(child, TIF_IA32))
60 		value &= 0xffffffff;
61 #endif
62 	switch (regno) {
63 	case R8:
64 	case R9:
65 	case R10:
66 	case R11:
67 	case R12:
68 	case R13:
69 	case R14:
70 	case R15:
71 	case RIP:
72 	case RSP:
73 	case RAX:
74 	case RBX:
75 	case RCX:
76 	case RDX:
77 	case RSI:
78 	case RDI:
79 	case RBP:
80 	case ORIG_RAX:
81 		break;
82 
83 	case FS:
84 	case GS:
85 	case DS:
86 	case ES:
87 	case SS:
88 	case CS:
89 		if (value && (value & 3) != 3)
90 			return -EIO;
91 		value &= 0xffff;
92 		break;
93 
94 	case FS_BASE:
95 	case GS_BASE:
96 		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
97 			return -EIO;
98 		break;
99 
100 	case EFLAGS:
101 		value &= FLAG_MASK;
102 		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
103 		return 0;
104 
105 	default:
106 		panic("Bad register in putreg(): %d\n", regno);
107 	}
108 
109 	child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
110 	return 0;
111 }
112 
113 int poke_user(struct task_struct *child, long addr, long data)
114 {
115 	if ((addr & 3) || addr < 0)
116 		return -EIO;
117 
118 	if (addr < MAX_REG_OFFSET)
119 		return putreg(child, addr, data);
120 	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
121 		(addr <= offsetof(struct user, u_debugreg[7]))) {
122 		addr -= offsetof(struct user, u_debugreg[0]);
123 		addr = addr >> 2;
124 		if ((addr == 4) || (addr == 5))
125 			return -EIO;
126 		child->thread.arch.debugregs[addr] = data;
127 		return 0;
128 	}
129 	return -EIO;
130 }
131 
132 unsigned long getreg(struct task_struct *child, int regno)
133 {
134 	unsigned long mask = ~0UL;
135 #ifdef TIF_IA32
136 	if (test_tsk_thread_flag(child, TIF_IA32))
137 		mask = 0xffffffff;
138 #endif
139 	switch (regno) {
140 	case R8:
141 	case R9:
142 	case R10:
143 	case R11:
144 	case R12:
145 	case R13:
146 	case R14:
147 	case R15:
148 	case RIP:
149 	case RSP:
150 	case RAX:
151 	case RBX:
152 	case RCX:
153 	case RDX:
154 	case RSI:
155 	case RDI:
156 	case RBP:
157 	case ORIG_RAX:
158 	case EFLAGS:
159 	case FS_BASE:
160 	case GS_BASE:
161 		break;
162 	case FS:
163 	case GS:
164 	case DS:
165 	case ES:
166 	case SS:
167 	case CS:
168 		mask = 0xffff;
169 		break;
170 	default:
171 		panic("Bad register in getreg: %d\n", regno);
172 	}
173 	return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
174 }
175 
176 int peek_user(struct task_struct *child, long addr, long data)
177 {
178 	/* read the word at location addr in the USER area. */
179 	unsigned long tmp;
180 
181 	if ((addr & 3) || addr < 0)
182 		return -EIO;
183 
184 	tmp = 0;  /* Default return condition */
185 	if (addr < MAX_REG_OFFSET)
186 		tmp = getreg(child, addr);
187 	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
188 		(addr <= offsetof(struct user, u_debugreg[7]))) {
189 		addr -= offsetof(struct user, u_debugreg[0]);
190 		addr = addr >> 2;
191 		tmp = child->thread.arch.debugregs[addr];
192 	}
193 	return put_user(tmp, (unsigned long *) data);
194 }
195 
196 /* XXX Mostly copied from sys-i386 */
197 int is_syscall(unsigned long addr)
198 {
199 	unsigned short instr;
200 	int n;
201 
202 	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
203 	if (n) {
204 		/*
205 		 * access_process_vm() grants access to vsyscall and stub,
206 		 * while copy_from_user doesn't. Maybe access_process_vm is
207 		 * slow, but that doesn't matter, since it will be called only
208 		 * in case of singlestepping, if copy_from_user failed.
209 		 */
210 		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
211 		if (n != sizeof(instr)) {
212 			printk("is_syscall : failed to read instruction from "
213 			       "0x%lx\n", addr);
214 			return 1;
215 		}
216 	}
217 	/* sysenter */
218 	return instr == 0x050f;
219 }
220 
221 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
222 {
223 	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
224 	long fpregs[HOST_FP_SIZE];
225 
226 	BUG_ON(sizeof(*buf) != sizeof(fpregs));
227 	err = save_fp_registers(userspace_pid[cpu], fpregs);
228 	if (err)
229 		return err;
230 
231 	n = copy_to_user(buf, fpregs, sizeof(fpregs));
232 	if (n > 0)
233 		return -EFAULT;
234 
235 	return n;
236 }
237 
238 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
239 {
240 	int n, cpu = ((struct thread_info *) child->stack)->cpu;
241 	long fpregs[HOST_FP_SIZE];
242 
243 	BUG_ON(sizeof(*buf) != sizeof(fpregs));
244 	n = copy_from_user(fpregs, buf, sizeof(fpregs));
245 	if (n > 0)
246 		return -EFAULT;
247 
248 	return restore_fp_registers(userspace_pid[cpu], fpregs);
249 }
250 
251 long subarch_ptrace(struct task_struct *child, long request,
252 		    unsigned long addr, unsigned long data)
253 {
254 	int ret = -EIO;
255 	void __user *datap = (void __user *) data;
256 
257 	switch (request) {
258 	case PTRACE_GETFPREGS: /* Get the child FPU state. */
259 		ret = get_fpregs(datap, child);
260 		break;
261 	case PTRACE_SETFPREGS: /* Set the child FPU state. */
262 		ret = set_fpregs(datap, child);
263 		break;
264 	case PTRACE_ARCH_PRCTL:
265 		/* XXX Calls ptrace on the host - needs some SMP thinking */
266 		ret = arch_prctl(child, data, (void __user *) addr);
267 		break;
268 	}
269 
270 	return ret;
271 }
272