2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include "linux/sched.h"
8 #include "asm/ptrace.h"
9 #include "asm/uaccess.h"
10 #include "ptrace_user.h"
11 #include "sysdep/sigcontext.h"
12 #include "sysdep/sc.h"
14 void arch_switch(void)
16 update_debugregs(current
->thread
.arch
.debugregs_seq
);
19 int is_syscall(unsigned long addr
)
24 n
= copy_from_user(&instr
, (void *) addr
, sizeof(instr
));
26 printk("is_syscall : failed to read instruction from 0x%lu\n",
30 return(instr
== 0x80cd);
33 /* determines which flags the user has access to. */
34 /* 1 = access 0 = no access */
35 #define FLAG_MASK 0x00044dd5
37 int putreg(struct task_struct
*child
, int regno
, unsigned long value
)
42 if (value
&& (value
& 3) != 3)
44 PT_REGS_FS(&child
->thread
.regs
) = value
;
47 if (value
&& (value
& 3) != 3)
49 PT_REGS_GS(&child
->thread
.regs
) = value
;
53 if (value
&& (value
& 3) != 3)
65 value
|= PT_REGS_EFLAGS(&child
->thread
.regs
);
68 PT_REGS_SET(&child
->thread
.regs
, regno
, value
);
72 unsigned long getreg(struct task_struct
*child
, int regno
)
74 unsigned long retval
= ~0UL;
87 retval
&= PT_REG(&child
->thread
.regs
, regno
);
92 struct i387_fxsave_struct
{
103 long st_space
[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
104 long xmm_space
[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
109 * FPU tag word conversions.
112 static inline unsigned short twd_i387_to_fxsr( unsigned short twd
)
114 unsigned int tmp
; /* to avoid 16 bit prefixes in the code */
116 /* Transform each pair of bits into 01 (valid) or 00 (empty) */
118 tmp
= (tmp
| (tmp
>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
119 /* and move the valid bits to the lower byte. */
120 tmp
= (tmp
| (tmp
>> 1)) & 0x3333; /* 00VV00VV00VV00VV */
121 tmp
= (tmp
| (tmp
>> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
122 tmp
= (tmp
| (tmp
>> 4)) & 0x00ff; /* 00000000VVVVVVVV */
126 static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct
*fxsave
)
128 struct _fpxreg
*st
= NULL
;
129 unsigned long twd
= (unsigned long) fxsave
->twd
;
131 unsigned long ret
= 0xffff0000;
134 #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
136 for ( i
= 0 ; i
< 8 ; i
++ ) {
138 st
= (struct _fpxreg
*) FPREG_ADDR( fxsave
, i
);
140 switch ( st
->exponent
& 0x7fff ) {
142 tag
= 2; /* Special */
145 if ( !st
->significand
[0] &&
146 !st
->significand
[1] &&
147 !st
->significand
[2] &&
148 !st
->significand
[3] ) {
151 tag
= 2; /* Special */
155 if ( st
->significand
[3] & 0x8000 ) {
158 tag
= 2; /* Special */
165 ret
|= (tag
<< (2 * i
));
172 * FXSR floating point environment conversions.
175 #ifdef CONFIG_MODE_TT
176 static inline int convert_fxsr_to_user_tt(struct _fpstate
*buf
,
177 struct pt_regs
*regs
)
179 struct i387_fxsave_struct
*fxsave
= SC_FXSR_ENV(PT_REGS_SC(regs
));
180 unsigned long env
[7];
182 struct _fpxreg
*from
;
185 env
[0] = (unsigned long)fxsave
->cwd
| 0xffff0000;
186 env
[1] = (unsigned long)fxsave
->swd
| 0xffff0000;
187 env
[2] = twd_fxsr_to_i387(fxsave
);
188 env
[3] = fxsave
->fip
;
189 env
[4] = fxsave
->fcs
| ((unsigned long)fxsave
->fop
<< 16);
190 env
[5] = fxsave
->foo
;
191 env
[6] = fxsave
->fos
;
193 if ( __copy_to_user( buf
, env
, 7 * sizeof(unsigned long) ) )
197 from
= (struct _fpxreg
*) &fxsave
->st_space
[0];
198 for ( i
= 0 ; i
< 8 ; i
++, to
++, from
++ ) {
199 if ( __copy_to_user( to
, from
, sizeof(*to
) ) )
206 static inline int convert_fxsr_to_user(struct _fpstate
*buf
,
207 struct pt_regs
*regs
)
209 return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf
, regs
), 0));
212 #ifdef CONFIG_MODE_TT
213 static inline int convert_fxsr_from_user_tt(struct pt_regs
*regs
,
214 struct _fpstate
*buf
)
216 struct i387_fxsave_struct
*fxsave
= SC_FXSR_ENV(PT_REGS_SC(regs
));
217 unsigned long env
[7];
222 if ( __copy_from_user( env
, buf
, 7 * sizeof(long) ) )
225 fxsave
->cwd
= (unsigned short)(env
[0] & 0xffff);
226 fxsave
->swd
= (unsigned short)(env
[1] & 0xffff);
227 fxsave
->twd
= twd_i387_to_fxsr((unsigned short)(env
[2] & 0xffff));
228 fxsave
->fip
= env
[3];
229 fxsave
->fop
= (unsigned short)((env
[4] & 0xffff0000) >> 16);
230 fxsave
->fcs
= (env
[4] & 0xffff);
231 fxsave
->foo
= env
[5];
232 fxsave
->fos
= env
[6];
234 to
= (struct _fpxreg
*) &fxsave
->st_space
[0];
236 for ( i
= 0 ; i
< 8 ; i
++, to
++, from
++ ) {
237 if ( __copy_from_user( to
, from
, sizeof(*from
) ) )
244 static inline int convert_fxsr_from_user(struct pt_regs
*regs
,
245 struct _fpstate
*buf
)
247 return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs
, buf
), 0));
250 int get_fpregs(unsigned long buf
, struct task_struct
*child
)
254 err
= convert_fxsr_to_user((struct _fpstate
*) buf
,
255 &child
->thread
.regs
);
256 if(err
) return(-EFAULT
);
260 int set_fpregs(unsigned long buf
, struct task_struct
*child
)
264 err
= convert_fxsr_from_user(&child
->thread
.regs
,
265 (struct _fpstate
*) buf
);
266 if(err
) return(-EFAULT
);
270 #ifdef CONFIG_MODE_TT
271 int get_fpxregs_tt(unsigned long buf
, struct task_struct
*tsk
)
273 struct pt_regs
*regs
= &tsk
->thread
.regs
;
274 struct i387_fxsave_struct
*fxsave
= SC_FXSR_ENV(PT_REGS_SC(regs
));
277 err
= __copy_to_user((void *) buf
, fxsave
,
278 sizeof(struct user_fxsr_struct
));
279 if(err
) return -EFAULT
;
284 int get_fpxregs(unsigned long buf
, struct task_struct
*tsk
)
286 return(CHOOSE_MODE(get_fpxregs_tt(buf
, tsk
), 0));
289 #ifdef CONFIG_MODE_TT
290 int set_fpxregs_tt(unsigned long buf
, struct task_struct
*tsk
)
292 struct pt_regs
*regs
= &tsk
->thread
.regs
;
293 struct i387_fxsave_struct
*fxsave
= SC_FXSR_ENV(PT_REGS_SC(regs
));
296 err
= __copy_from_user(fxsave
, (void *) buf
,
297 sizeof(struct user_fxsr_struct
) );
298 if(err
) return -EFAULT
;
303 int set_fpxregs(unsigned long buf
, struct task_struct
*tsk
)
305 return(CHOOSE_MODE(set_fpxregs_tt(buf
, tsk
), 0));
309 int dump_fpu(struct pt_regs
*regs
, elf_fpregset_t
*fpu
)
311 fpu
->cwd
= (((SC_FP_CW(PT_REGS_SC(regs
)) & 0xffff) << 16) |
312 (SC_FP_SW(PT_REGS_SC(regs
)) & 0xffff));
313 fpu
->swd
= SC_FP_CSSEL(PT_REGS_SC(regs
)) & 0xffff;
314 fpu
->twd
= SC_FP_IPOFF(PT_REGS_SC(regs
));
315 fpu
->fip
= SC_FP_CSSEL(PT_REGS_SC(regs
)) & 0xffff;
316 fpu
->fcs
= SC_FP_DATAOFF(PT_REGS_SC(regs
));
317 fpu
->foo
= SC_FP_DATASEL(PT_REGS_SC(regs
));
319 memcpy(fpu
->st_space
, (void *) SC_FP_ST(PT_REGS_SC(regs
)),
320 sizeof(fpu
->st_space
));
325 #ifdef CONFIG_MODE_TT
326 static inline void copy_fpu_fxsave_tt(struct pt_regs
*regs
,
327 struct user_i387_struct
*buf
)
329 struct i387_fxsave_struct
*fpu
= SC_FXSR_ENV(PT_REGS_SC(regs
));
331 unsigned short *from
;
334 memcpy( buf
, fpu
, 7 * sizeof(long) );
336 to
= (unsigned short *) &buf
->st_space
[0];
337 from
= (unsigned short *) &fpu
->st_space
[0];
338 for ( i
= 0 ; i
< 8 ; i
++, to
+= 5, from
+= 8 ) {
339 memcpy( to
, from
, 5 * sizeof(unsigned short) );
344 static inline void copy_fpu_fxsave(struct pt_regs
*regs
,
345 struct user_i387_struct
*buf
)
347 (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs
, buf
), 0);
350 int dump_fpu(struct pt_regs
*regs
, elf_fpregset_t
*fpu
)
352 copy_fpu_fxsave(regs
, (struct user_i387_struct
*) fpu
);
357 * Overrides for Emacs so that we follow Linus's tabbing style.
358 * Emacs will notice this stuff at the end of the file and automatically
359 * adjust the settings for this buffer only. This must remain at the end
361 * ---------------------------------------------------------------------------
363 * c-file-style: "linux"