2 * Copyright 2003 PathScale, Inc.
3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5 * Licensed under the GPL
9 #include <linux/sched.h>
10 #include <linux/errno.h>
11 #define __FRAME_OFFSETS
12 #include <asm/ptrace.h>
13 #include <asm/uaccess.h>
16 * determines which flags the user has access to.
17 * 1 = access 0 = no access
19 #define FLAG_MASK 0x44dd5UL
21 int putreg(struct task_struct
*child
, int regno
, unsigned long value
)
27 * Some code in the 64bit emulation may not be 64bit clean.
28 * Don't take any chances.
30 if (test_tsk_thread_flag(child
, TIF_IA32
))
40 if (value
&& (value
& 3) != 3)
47 if (!((value
>> 48) == 0 || (value
>> 48) == 0xffff))
53 tmp
= PT_REGS_EFLAGS(&child
->thread
.regs
) & ~FLAG_MASK
;
58 PT_REGS_SET(&child
->thread
.regs
, regno
, value
);
62 int poke_user(struct task_struct
*child
, long addr
, long data
)
64 if ((addr
& 3) || addr
< 0)
67 if (addr
< MAX_REG_OFFSET
)
68 return putreg(child
, addr
, data
);
69 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
70 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
71 addr
-= offsetof(struct user
, u_debugreg
[0]);
73 if ((addr
== 4) || (addr
== 5))
75 child
->thread
.arch
.debugregs
[addr
] = data
;
81 unsigned long getreg(struct task_struct
*child
, int regno
)
83 unsigned long retval
= ~0UL;
94 retval
&= PT_REG(&child
->thread
.regs
, regno
);
96 if (test_tsk_thread_flag(child
, TIF_IA32
))
103 int peek_user(struct task_struct
*child
, long addr
, long data
)
105 /* read the word at location addr in the USER area. */
108 if ((addr
& 3) || addr
< 0)
111 tmp
= 0; /* Default return condition */
112 if (addr
< MAX_REG_OFFSET
)
113 tmp
= getreg(child
, addr
);
114 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
115 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
116 addr
-= offsetof(struct user
, u_debugreg
[0]);
118 tmp
= child
->thread
.arch
.debugregs
[addr
];
120 return put_user(tmp
, (unsigned long *) data
);
123 /* XXX Mostly copied from sys-i386 */
124 int is_syscall(unsigned long addr
)
126 unsigned short instr
;
129 n
= copy_from_user(&instr
, (void __user
*) addr
, sizeof(instr
));
132 * access_process_vm() grants access to vsyscall and stub,
133 * while copy_from_user doesn't. Maybe access_process_vm is
134 * slow, but that doesn't matter, since it will be called only
135 * in case of singlestepping, if copy_from_user failed.
137 n
= access_process_vm(current
, addr
, &instr
, sizeof(instr
), 0);
138 if (n
!= sizeof(instr
)) {
139 printk("is_syscall : failed to read instruction from "
145 return instr
== 0x050f;
148 int get_fpregs(struct user_i387_struct __user
*buf
, struct task_struct
*child
)
150 int err
, n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
151 long fpregs
[HOST_FP_SIZE
];
153 BUG_ON(sizeof(*buf
) != sizeof(fpregs
));
154 err
= save_fp_registers(userspace_pid
[cpu
], fpregs
);
158 n
= copy_to_user(buf
, fpregs
, sizeof(fpregs
));
165 int set_fpregs(struct user_i387_struct __user
*buf
, struct task_struct
*child
)
167 int n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
168 long fpregs
[HOST_FP_SIZE
];
170 BUG_ON(sizeof(*buf
) != sizeof(fpregs
));
171 n
= copy_from_user(fpregs
, buf
, sizeof(fpregs
));
175 return restore_fp_registers(userspace_pid
[cpu
], fpregs
);
178 long subarch_ptrace(struct task_struct
*child
, long request
,
179 unsigned long addr
, unsigned long data
)
182 void __user
*datap
= (void __user
*) data
;
185 case PTRACE_GETFPXREGS
: /* Get the child FPU state. */
186 ret
= get_fpregs(datap
, child
);
188 case PTRACE_SETFPXREGS
: /* Set the child FPU state. */
189 ret
= set_fpregs(datap
, child
);