MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / um / sys-i386 / ptrace.c
blob817ef7479d3fc1b869d9f09cad7767ac50552231
1 /*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
6 #include "linux/sched.h"
7 #include "asm/elf.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)
21 unsigned short instr;
22 int n;
24 n = copy_from_user(&instr, (void *) addr, sizeof(instr));
25 if(n){
26 printk("is_syscall : failed to read instruction from 0x%lu\n",
27 addr);
28 return(0);
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)
39 regno >>= 2;
40 switch (regno) {
41 case FS:
42 if (value && (value & 3) != 3)
43 return -EIO;
44 PT_REGS_FS(&child->thread.regs) = value;
45 return 0;
46 case GS:
47 if (value && (value & 3) != 3)
48 return -EIO;
49 PT_REGS_GS(&child->thread.regs) = value;
50 return 0;
51 case DS:
52 case ES:
53 if (value && (value & 3) != 3)
54 return -EIO;
55 value &= 0xffff;
56 break;
57 case SS:
58 case CS:
59 if ((value & 3) != 3)
60 return -EIO;
61 value &= 0xffff;
62 break;
63 case EFL:
64 value &= FLAG_MASK;
65 value |= PT_REGS_EFLAGS(&child->thread.regs);
66 break;
68 PT_REGS_SET(&child->thread.regs, regno, value);
69 return 0;
72 unsigned long getreg(struct task_struct *child, int regno)
74 unsigned long retval = ~0UL;
76 regno >>= 2;
77 switch (regno) {
78 case FS:
79 case GS:
80 case DS:
81 case ES:
82 case SS:
83 case CS:
84 retval = 0xffff;
85 /* fall through */
86 default:
87 retval &= PT_REG(&child->thread.regs, regno);
89 return retval;
92 struct i387_fxsave_struct {
93 unsigned short cwd;
94 unsigned short swd;
95 unsigned short twd;
96 unsigned short fop;
97 long fip;
98 long fcs;
99 long foo;
100 long fos;
101 long mxcsr;
102 long reserved;
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 */
105 long padding[56];
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) */
117 tmp = ~twd;
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 */
123 return tmp;
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;
130 unsigned long tag;
131 unsigned long ret = 0xffff0000;
132 int i;
134 #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
136 for ( i = 0 ; i < 8 ; i++ ) {
137 if ( twd & 0x1 ) {
138 st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
140 switch ( st->exponent & 0x7fff ) {
141 case 0x7fff:
142 tag = 2; /* Special */
143 break;
144 case 0x0000:
145 if ( !st->significand[0] &&
146 !st->significand[1] &&
147 !st->significand[2] &&
148 !st->significand[3] ) {
149 tag = 1; /* Zero */
150 } else {
151 tag = 2; /* Special */
153 break;
154 default:
155 if ( st->significand[3] & 0x8000 ) {
156 tag = 0; /* Valid */
157 } else {
158 tag = 2; /* Special */
160 break;
162 } else {
163 tag = 3; /* Empty */
165 ret |= (tag << (2 * i));
166 twd = twd >> 1;
168 return ret;
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];
181 struct _fpreg *to;
182 struct _fpxreg *from;
183 int i;
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) ) )
194 return 1;
196 to = &buf->_st[0];
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) ) )
200 return 1;
202 return 0;
204 #endif
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];
218 struct _fpxreg *to;
219 struct _fpreg *from;
220 int i;
222 if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
223 return 1;
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];
235 from = &buf->_st[0];
236 for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
237 if ( __copy_from_user( to, from, sizeof(*from) ) )
238 return 1;
240 return 0;
242 #endif
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)
252 int err;
254 err = convert_fxsr_to_user((struct _fpstate *) buf,
255 &child->thread.regs);
256 if(err) return(-EFAULT);
257 else return(0);
260 int set_fpregs(unsigned long buf, struct task_struct *child)
262 int err;
264 err = convert_fxsr_from_user(&child->thread.regs,
265 (struct _fpstate *) buf);
266 if(err) return(-EFAULT);
267 else return(0);
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));
275 int err;
277 err = __copy_to_user((void *) buf, fxsave,
278 sizeof(struct user_fxsr_struct));
279 if(err) return -EFAULT;
280 else return 0;
282 #endif
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));
294 int err;
296 err = __copy_from_user(fxsave, (void *) buf,
297 sizeof(struct user_fxsr_struct) );
298 if(err) return -EFAULT;
299 else return 0;
301 #endif
303 int set_fpxregs(unsigned long buf, struct task_struct *tsk)
305 return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
308 #ifdef notdef
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));
318 fpu->fos = 0;
319 memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)),
320 sizeof(fpu->st_space));
321 return(1);
323 #endif
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));
330 unsigned short *to;
331 unsigned short *from;
332 int i;
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) );
342 #endif
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);
353 return(1);
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
360 * of the file.
361 * ---------------------------------------------------------------------------
362 * Local variables:
363 * c-file-style: "linux"
364 * End: