2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
7 #include <linux/sched.h>
8 #include <linux/uaccess.h>
9 #include <linux/regset.h>
10 #include <asm/ptrace-abi.h>
11 #include <registers.h>
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 /* determines which flags the user has access to. */
28 /* 1 = access 0 = no access */
29 #define FLAG_MASK 0x00044dd5
31 static const int reg_offsets
[] = {
48 [ORIG_EAX
] = HOST_ORIG_AX
,
51 int putreg(struct task_struct
*child
, int regno
, unsigned long value
)
66 /* Update the syscall number. */
67 UPT_SYSCALL_NR(&child
->thread
.regs
.regs
) = value
;
70 if (value
&& (value
& 3) != 3)
74 if (value
&& (value
& 3) != 3)
79 if (value
&& (value
& 3) != 3)
91 child
->thread
.regs
.regs
.gp
[HOST_EFLAGS
] |= value
;
94 panic("Bad register in putreg() : %d\n", regno
);
96 child
->thread
.regs
.regs
.gp
[reg_offsets
[regno
]] = value
;
100 int poke_user(struct task_struct
*child
, long addr
, long data
)
102 if ((addr
& 3) || addr
< 0)
105 if (addr
< MAX_REG_OFFSET
)
106 return putreg(child
, addr
, data
);
107 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
108 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
109 addr
-= offsetof(struct user
, u_debugreg
[0]);
111 if ((addr
== 4) || (addr
== 5))
113 child
->thread
.arch
.debugregs
[addr
] = data
;
119 unsigned long getreg(struct task_struct
*child
, int regno
)
121 unsigned long mask
= ~0UL;
146 panic("Bad register in getreg() : %d\n", regno
);
148 return mask
& child
->thread
.regs
.regs
.gp
[reg_offsets
[regno
]];
151 /* read the word at location addr in the USER area. */
152 int peek_user(struct task_struct
*child
, long addr
, long data
)
156 if ((addr
& 3) || addr
< 0)
159 tmp
= 0; /* Default return condition */
160 if (addr
< MAX_REG_OFFSET
) {
161 tmp
= getreg(child
, addr
);
163 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
164 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
165 addr
-= offsetof(struct user
, u_debugreg
[0]);
167 tmp
= child
->thread
.arch
.debugregs
[addr
];
169 return put_user(tmp
, (unsigned long __user
*) data
);
172 long subarch_ptrace(struct task_struct
*child
, long request
,
173 unsigned long addr
, unsigned long data
)
176 void __user
*datap
= (void __user
*) data
;
178 case PTRACE_GETFPREGS
: /* Get the child FPU state. */
179 return copy_regset_to_user(child
, task_user_regset_view(child
),
181 0, sizeof(struct user_i387_struct
),
183 case PTRACE_SETFPREGS
: /* Set the child FPU state. */
184 return copy_regset_from_user(child
, task_user_regset_view(child
),
186 0, sizeof(struct user_i387_struct
),
188 case PTRACE_GETFPXREGS
: /* Get the child FPU state. */
189 return copy_regset_to_user(child
, task_user_regset_view(child
),
191 0, sizeof(struct user_fxsr_struct
),
193 case PTRACE_SETFPXREGS
: /* Set the child FPU state. */
194 return copy_regset_from_user(child
, task_user_regset_view(child
),
196 0, sizeof(struct user_fxsr_struct
),