2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
7 #include <linux/sched.h>
8 #include <asm/uaccess.h>
9 #include <asm/ptrace-abi.h>
12 extern int arch_switch_tls(struct task_struct
*to
);
14 void arch_switch_to(struct task_struct
*to
)
16 int err
= arch_switch_tls(to
);
21 printk(KERN_WARNING
"arch_switch_tls failed, errno %d, "
22 "not EINVAL\n", -err
);
24 printk(KERN_WARNING
"arch_switch_tls failed, errno = EINVAL\n");
27 int is_syscall(unsigned long addr
)
32 n
= copy_from_user(&instr
, (void __user
*) addr
, sizeof(instr
));
34 /* access_process_vm() grants access to vsyscall and stub,
35 * while copy_from_user doesn't. Maybe access_process_vm is
36 * slow, but that doesn't matter, since it will be called only
37 * in case of singlestepping, if copy_from_user failed.
39 n
= access_process_vm(current
, addr
, &instr
, sizeof(instr
), 0);
40 if (n
!= sizeof(instr
)) {
41 printk(KERN_ERR
"is_syscall : failed to read "
42 "instruction from 0x%lx\n", addr
);
46 /* int 0x80 or sysenter */
47 return (instr
== 0x80cd) || (instr
== 0x340f);
50 /* determines which flags the user has access to. */
51 /* 1 = access 0 = no access */
52 #define FLAG_MASK 0x00044dd5
54 static const int reg_offsets
[] = {
71 [ORIG_EAX
] = HOST_ORIG_AX
,
74 int putreg(struct task_struct
*child
, int regno
, unsigned long value
)
89 /* Update the syscall number. */
90 UPT_SYSCALL_NR(&child
->thread
.regs
.regs
) = value
;
93 if (value
&& (value
& 3) != 3)
97 if (value
&& (value
& 3) != 3)
102 if (value
&& (value
& 3) != 3)
108 if ((value
& 3) != 3)
114 child
->thread
.regs
.regs
.gp
[HOST_EFLAGS
] |= value
;
117 panic("Bad register in putreg() : %d\n", regno
);
119 child
->thread
.regs
.regs
.gp
[reg_offsets
[regno
]] = value
;
123 int poke_user(struct task_struct
*child
, long addr
, long data
)
125 if ((addr
& 3) || addr
< 0)
128 if (addr
< MAX_REG_OFFSET
)
129 return putreg(child
, addr
, data
);
130 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
131 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
132 addr
-= offsetof(struct user
, u_debugreg
[0]);
134 if ((addr
== 4) || (addr
== 5))
136 child
->thread
.arch
.debugregs
[addr
] = data
;
142 unsigned long getreg(struct task_struct
*child
, int regno
)
144 unsigned long mask
= ~0UL;
169 panic("Bad register in getreg() : %d\n", regno
);
171 return mask
& child
->thread
.regs
.regs
.gp
[reg_offsets
[regno
]];
174 /* read the word at location addr in the USER area. */
175 int peek_user(struct task_struct
*child
, long addr
, long data
)
179 if ((addr
& 3) || addr
< 0)
182 tmp
= 0; /* Default return condition */
183 if (addr
< MAX_REG_OFFSET
) {
184 tmp
= getreg(child
, addr
);
186 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
187 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
188 addr
-= offsetof(struct user
, u_debugreg
[0]);
190 tmp
= child
->thread
.arch
.debugregs
[addr
];
192 return put_user(tmp
, (unsigned long __user
*) data
);
195 static int get_fpregs(struct user_i387_struct __user
*buf
, struct task_struct
*child
)
197 int err
, n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
198 struct user_i387_struct fpregs
;
200 err
= save_i387_registers(userspace_pid
[cpu
],
201 (unsigned long *) &fpregs
);
205 n
= copy_to_user(buf
, &fpregs
, sizeof(fpregs
));
212 static int set_fpregs(struct user_i387_struct __user
*buf
, struct task_struct
*child
)
214 int n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
215 struct user_i387_struct fpregs
;
217 n
= copy_from_user(&fpregs
, buf
, sizeof(fpregs
));
221 return restore_i387_registers(userspace_pid
[cpu
],
222 (unsigned long *) &fpregs
);
225 static int get_fpxregs(struct user_fxsr_struct __user
*buf
, struct task_struct
*child
)
227 int err
, n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
228 struct user_fxsr_struct fpregs
;
230 err
= save_fpx_registers(userspace_pid
[cpu
], (unsigned long *) &fpregs
);
234 n
= copy_to_user(buf
, &fpregs
, sizeof(fpregs
));
241 static int set_fpxregs(struct user_fxsr_struct __user
*buf
, struct task_struct
*child
)
243 int n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
244 struct user_fxsr_struct fpregs
;
246 n
= copy_from_user(&fpregs
, buf
, sizeof(fpregs
));
250 return restore_fpx_registers(userspace_pid
[cpu
],
251 (unsigned long *) &fpregs
);
254 long subarch_ptrace(struct task_struct
*child
, long request
,
255 unsigned long addr
, unsigned long data
)
258 void __user
*datap
= (void __user
*) data
;
260 case PTRACE_GETFPREGS
: /* Get the child FPU state. */
261 ret
= get_fpregs(datap
, child
);
263 case PTRACE_SETFPREGS
: /* Set the child FPU state. */
264 ret
= set_fpregs(datap
, child
);
266 case PTRACE_GETFPXREGS
: /* Get the child FPU state. */
267 ret
= get_fpxregs(datap
, child
);
269 case PTRACE_SETFPXREGS
: /* Set the child FPU state. */
270 ret
= set_fpxregs(datap
, child
);
This page took 0.058614 seconds and 6 git commands to generate.