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"
11 extern int arch_switch_tls(struct task_struct
*from
, struct task_struct
*to
);
13 void arch_switch_to(struct task_struct
*from
, struct task_struct
*to
)
15 int err
= arch_switch_tls(from
, to
);
20 printk(KERN_WARNING
"arch_switch_tls failed, errno %d, "
21 "not EINVAL\n", -err
);
23 printk(KERN_WARNING
"arch_switch_tls failed, errno = EINVAL\n");
26 int is_syscall(unsigned long addr
)
31 n
= copy_from_user(&instr
, (void __user
*) addr
, sizeof(instr
));
33 /* access_process_vm() grants access to vsyscall and stub,
34 * while copy_from_user doesn't. Maybe access_process_vm is
35 * slow, but that doesn't matter, since it will be called only
36 * in case of singlestepping, if copy_from_user failed.
38 n
= access_process_vm(current
, addr
, &instr
, sizeof(instr
), 0);
39 if (n
!= sizeof(instr
)) {
40 printk(KERN_ERR
"is_syscall : failed to read "
41 "instruction from 0x%lx\n", addr
);
45 /* int 0x80 or sysenter */
46 return (instr
== 0x80cd) || (instr
== 0x340f);
49 /* determines which flags the user has access to. */
50 /* 1 = access 0 = no access */
51 #define FLAG_MASK 0x00044dd5
53 int putreg(struct task_struct
*child
, int regno
, unsigned long value
)
58 if (value
&& (value
& 3) != 3)
60 PT_REGS_FS(&child
->thread
.regs
) = value
;
63 if (value
&& (value
& 3) != 3)
65 PT_REGS_GS(&child
->thread
.regs
) = value
;
69 if (value
&& (value
& 3) != 3)
81 value
|= PT_REGS_EFLAGS(&child
->thread
.regs
);
84 PT_REGS_SET(&child
->thread
.regs
, regno
, value
);
88 int poke_user(struct task_struct
*child
, long addr
, long data
)
90 if ((addr
& 3) || addr
< 0)
93 if (addr
< MAX_REG_OFFSET
)
94 return putreg(child
, addr
, data
);
95 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
96 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
97 addr
-= offsetof(struct user
, u_debugreg
[0]);
99 if ((addr
== 4) || (addr
== 5))
101 child
->thread
.arch
.debugregs
[addr
] = data
;
107 unsigned long getreg(struct task_struct
*child
, int regno
)
109 unsigned long retval
= ~0UL;
122 retval
&= PT_REG(&child
->thread
.regs
, regno
);
127 /* read the word at location addr in the USER area. */
128 int peek_user(struct task_struct
*child
, long addr
, long data
)
132 if ((addr
& 3) || addr
< 0)
135 tmp
= 0; /* Default return condition */
136 if (addr
< MAX_REG_OFFSET
) {
137 tmp
= getreg(child
, addr
);
139 else if ((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
140 (addr
<= offsetof(struct user
, u_debugreg
[7]))) {
141 addr
-= offsetof(struct user
, u_debugreg
[0]);
143 tmp
= child
->thread
.arch
.debugregs
[addr
];
145 return put_user(tmp
, (unsigned long __user
*) data
);
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 int get_fpxregs(struct user_fxsr_struct __user
*buf
, struct task_struct
*child
)
180 int err
, n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
181 long fpregs
[HOST_XFP_SIZE
];
183 BUG_ON(sizeof(*buf
) != sizeof(fpregs
));
184 err
= save_fpx_registers(userspace_pid
[cpu
], fpregs
);
188 n
= copy_to_user(buf
, fpregs
, sizeof(fpregs
));
195 int set_fpxregs(struct user_fxsr_struct __user
*buf
, struct task_struct
*child
)
197 int n
, cpu
= ((struct thread_info
*) child
->stack
)->cpu
;
198 long fpregs
[HOST_XFP_SIZE
];
200 BUG_ON(sizeof(*buf
) != sizeof(fpregs
));
201 n
= copy_from_user(fpregs
, buf
, sizeof(fpregs
));
205 return restore_fpx_registers(userspace_pid
[cpu
], fpregs
);
208 long subarch_ptrace(struct task_struct
*child
, long request
, long addr
,