Create the necessary functions for wineserver contexts for Alpha.
[wine] / server / context_alpha.c
1 /*
2  * Alpha register context support
3  *
4  * Copyright (C) 2004 Vincent BĂ©ron
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #ifdef __ALPHA__
24
25 #include <assert.h>
26 #include <errno.h>
27 #ifdef HAVE_SYS_REG_H
28 # include <sys/reg.h>
29 #endif
30 #include <stdarg.h>
31 #include <unistd.h>
32 #ifdef HAVE_SYS_PTRACE_H
33 # include <sys/ptrace.h>
34 #endif
35
36 #include "file.h"
37 #include "thread.h"
38 #include "request.h"
39
40 #ifdef HAVE_SYS_USER_H
41 # include <sys/user.h>
42 #endif
43
44 /* user definitions from asm/user.h */
45 struct kernel_user_struct
46 {
47     unsigned long regs[EF_SIZE/8+32];
48     size_t u_tsize;
49     size_t u_dsize;
50     size_t u_ssize;
51     unsigned long start_code;
52     unsigned long start_data;
53     unsigned long start_stack;
54     long int signal;
55     struct regs * u_ar0;
56     unsigned long magic;
57     char u_comm[32];
58 };
59
60 /* get thread context */
61 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
62 {
63     int pid = get_ptrace_pid(thread);
64     if (flags & CONTEXT_FULL)
65     {
66         struct kernel_user_struct regs;
67         if (ptrace( PTRACE_GETREGS, pid, 0, &regs ) == -1) goto error;
68         if (flags & CONTEXT_INTEGER)
69         {
70             context->IntV0 = regs.regs[EF_V0];
71             context->IntT0 = regs.regs[EF_T0];
72             context->IntT1 = regs.regs[EF_T1];
73             context->IntT2 = regs.regs[EF_T2];
74             context->IntT3 = regs.regs[EF_T3];
75             context->IntT4 = regs.regs[EF_T4];
76             context->IntT5 = regs.regs[EF_T5];
77             context->IntT6 = regs.regs[EF_T6];
78             context->IntT7 = regs.regs[EF_T7];
79             context->IntS0 = regs.regs[EF_S0];
80             context->IntS1 = regs.regs[EF_S1];
81             context->IntS2 = regs.regs[EF_S2];
82             context->IntS3 = regs.regs[EF_S3];
83             context->IntS4 = regs.regs[EF_S4];
84             context->IntS5 = regs.regs[EF_S5];
85             context->IntFp = regs.regs[EF_S6];
86             context->IntA0 = regs.regs[EF_A0];
87             context->IntA1 = regs.regs[EF_A1];
88             context->IntA2 = regs.regs[EF_A2];
89             context->IntA3 = regs.regs[EF_A3];
90             context->IntA4 = regs.regs[EF_A4];
91             context->IntA5 = regs.regs[EF_A5];
92             context->IntT8 = regs.regs[EF_T8];
93             context->IntT9 = regs.regs[EF_T9];
94             context->IntT10 = regs.regs[EF_T10];
95             context->IntT11 = regs.regs[EF_T11];
96             context->IntT12 = regs.regs[EF_T12];
97             context->IntAt = regs.regs[EF_AT];
98             context->IntZero = 0;
99         }
100         if (flags & CONTEXT_CONTROL)
101         {
102             context->IntRa = regs.regs[EF_RA];
103             context->IntGp = regs.regs[EF_GP];
104             context->IntSp = regs.regs[EF_SP];
105             context->Fir = regs.regs[EF_PC];
106             context->Psr = regs.regs[EF_PS];
107         }
108         if (flags & CONTEXT_FLOATING_POINT)
109         {
110             context->FltF0 = regs.regs[EF_SIZE/8+0];
111             context->FltF1 = regs.regs[EF_SIZE/8+1];
112             context->FltF2 = regs.regs[EF_SIZE/8+2];
113             context->FltF3 = regs.regs[EF_SIZE/8+3];
114             context->FltF4 = regs.regs[EF_SIZE/8+4];
115             context->FltF5 = regs.regs[EF_SIZE/8+5];
116             context->FltF6 = regs.regs[EF_SIZE/8+6];
117             context->FltF7 = regs.regs[EF_SIZE/8+7];
118             context->FltF8 = regs.regs[EF_SIZE/8+8];
119             context->FltF9 = regs.regs[EF_SIZE/8+9];
120             context->FltF10 = regs.regs[EF_SIZE/8+10];
121             context->FltF11 = regs.regs[EF_SIZE/8+11];
122             context->FltF12 = regs.regs[EF_SIZE/8+12];
123             context->FltF13 = regs.regs[EF_SIZE/8+13];
124             context->FltF14 = regs.regs[EF_SIZE/8+14];
125             context->FltF15 = regs.regs[EF_SIZE/8+15];
126             context->FltF16 = regs.regs[EF_SIZE/8+16];
127             context->FltF17 = regs.regs[EF_SIZE/8+17];
128             context->FltF18 = regs.regs[EF_SIZE/8+18];
129             context->FltF19 = regs.regs[EF_SIZE/8+19];
130             context->FltF20 = regs.regs[EF_SIZE/8+20];
131             context->FltF21 = regs.regs[EF_SIZE/8+21];
132             context->FltF22 = regs.regs[EF_SIZE/8+22];
133             context->FltF23 = regs.regs[EF_SIZE/8+23];
134             context->FltF24 = regs.regs[EF_SIZE/8+24];
135             context->FltF25 = regs.regs[EF_SIZE/8+25];
136             context->FltF26 = regs.regs[EF_SIZE/8+26];
137             context->FltF27 = regs.regs[EF_SIZE/8+27];
138             context->FltF28 = regs.regs[EF_SIZE/8+28];
139             context->FltF29 = regs.regs[EF_SIZE/8+29];
140             context->FltF30 = regs.regs[EF_SIZE/8+30];
141             context->FltF31 = 0;
142             context->Fpcr = regs.regs[EF_SIZE/8+31];
143             context->SoftFpcr = 0; /* FIXME */
144         }
145         if (ptrace( PTRACE_SETREGS, pid, 0, &regs ) == -1) goto error;
146     }
147     return;
148  error:
149     file_set_error();
150 }
151
152 /* set a thread context */
153 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
154 {
155     int pid = get_ptrace_pid(thread);
156     if (flags & CONTEXT_FULL)
157     {
158         struct kernel_user_struct regs;
159         if (ptrace( PTRACE_GETREGS, pid, 0, &regs ) == -1) goto error;
160         if (flags & CONTEXT_INTEGER)
161         {
162             regs.regs[EF_V0] = context->IntV0;
163             regs.regs[EF_T0] = context->IntT0;
164             regs.regs[EF_T1] = context->IntT1;
165             regs.regs[EF_T2] = context->IntT2;
166             regs.regs[EF_T3] = context->IntT3;
167             regs.regs[EF_T4] = context->IntT4;
168             regs.regs[EF_T5] = context->IntT5;
169             regs.regs[EF_T6] = context->IntT6;
170             regs.regs[EF_T7] = context->IntT7;
171             regs.regs[EF_S0] = context->IntS0;
172             regs.regs[EF_S1] = context->IntS1;
173             regs.regs[EF_S2] = context->IntS2;
174             regs.regs[EF_S3] = context->IntS3;
175             regs.regs[EF_S4] = context->IntS4;
176             regs.regs[EF_S5] = context->IntS5;
177             regs.regs[EF_S6] = context->IntFp;
178             regs.regs[EF_A0] = context->IntA0;
179             regs.regs[EF_A1] = context->IntA1;
180             regs.regs[EF_A2] = context->IntA2;
181             regs.regs[EF_A3] = context->IntA3;
182             regs.regs[EF_A4] = context->IntA4;
183             regs.regs[EF_A5] = context->IntA5;
184             regs.regs[EF_T8] = context->IntT8;
185             regs.regs[EF_T9] = context->IntT9;
186             regs.regs[EF_T10] = context->IntT10;
187             regs.regs[EF_T11] = context->IntT11;
188             regs.regs[EF_T12] = context->IntT12;
189             regs.regs[EF_AT] = context->IntAt;
190         }
191         if (flags & CONTEXT_CONTROL)
192         {
193             regs.regs[EF_RA] = context->IntRa;
194             regs.regs[EF_GP] = context->IntGp;
195             regs.regs[EF_SP] = context->IntSp;
196             regs.regs[EF_PC] = context->Fir;
197             regs.regs[EF_PS] = context->Psr;
198         }
199         if (flags & CONTEXT_FLOATING_POINT)
200         {
201             regs.regs[EF_SIZE/8+0] = context->FltF0;
202             regs.regs[EF_SIZE/8+1] = context->FltF1;
203             regs.regs[EF_SIZE/8+2] = context->FltF2;
204             regs.regs[EF_SIZE/8+3] = context->FltF3;
205             regs.regs[EF_SIZE/8+4] = context->FltF4;
206             regs.regs[EF_SIZE/8+5] = context->FltF5;
207             regs.regs[EF_SIZE/8+6] = context->FltF6;
208             regs.regs[EF_SIZE/8+7] = context->FltF7;
209             regs.regs[EF_SIZE/8+8] = context->FltF8;
210             regs.regs[EF_SIZE/8+9] = context->FltF9;
211             regs.regs[EF_SIZE/8+10] = context->FltF10;
212             regs.regs[EF_SIZE/8+11] = context->FltF11;
213             regs.regs[EF_SIZE/8+12] = context->FltF12;
214             regs.regs[EF_SIZE/8+13] = context->FltF13;
215             regs.regs[EF_SIZE/8+14] = context->FltF14;
216             regs.regs[EF_SIZE/8+15] = context->FltF15;
217             regs.regs[EF_SIZE/8+16] = context->FltF16;
218             regs.regs[EF_SIZE/8+17] = context->FltF17;
219             regs.regs[EF_SIZE/8+18] = context->FltF18;
220             regs.regs[EF_SIZE/8+19] = context->FltF19;
221             regs.regs[EF_SIZE/8+20] = context->FltF20;
222             regs.regs[EF_SIZE/8+21] = context->FltF21;
223             regs.regs[EF_SIZE/8+22] = context->FltF22;
224             regs.regs[EF_SIZE/8+23] = context->FltF23;
225             regs.regs[EF_SIZE/8+24] = context->FltF24;
226             regs.regs[EF_SIZE/8+25] = context->FltF25;
227             regs.regs[EF_SIZE/8+26] = context->FltF26;
228             regs.regs[EF_SIZE/8+27] = context->FltF27;
229             regs.regs[EF_SIZE/8+28] = context->FltF28;
230             regs.regs[EF_SIZE/8+29] = context->FltF29;
231             regs.regs[EF_SIZE/8+30] = context->FltF30;
232             regs.regs[EF_SIZE/8+31] = context->Fpcr;
233         }
234     }
235     return;
236  error:
237     file_set_error();
238 }
239
240 /* copy a context structure according to the flags */
241 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
242 {
243     if (flags & CONTEXT_CONTROL)
244     {
245         to->IntRa = from->IntRa;
246         to->IntGp = from->IntGp;
247         to->IntSp = from->IntSp;
248         to->Fir = from->Fir;
249         to->Psr = from->Psr;
250     }
251     if (flags & CONTEXT_INTEGER)
252     {
253         to->IntV0 = from->IntV0;
254         to->IntT0 = from->IntT0;
255         to->IntT1 = from->IntT1;
256         to->IntT2 = from->IntT2;
257         to->IntT3 = from->IntT3;
258         to->IntT4 = from->IntT4;
259         to->IntT5 = from->IntT5;
260         to->IntT6 = from->IntT6;
261         to->IntT7 = from->IntT7;
262         to->IntS0 = from->IntS0;
263         to->IntS1 = from->IntS1;
264         to->IntS2 = from->IntS2;
265         to->IntS3 = from->IntS3;
266         to->IntS4 = from->IntS4;
267         to->IntS5 = from->IntS5;
268         to->IntFp = from->IntFp;
269         to->IntA0 = from->IntA0;
270         to->IntA1 = from->IntA1;
271         to->IntA2 = from->IntA2;
272         to->IntA3 = from->IntA3;
273         to->IntA4 = from->IntA4;
274         to->IntA5 = from->IntA5;
275         to->IntT8 = from->IntT8;
276         to->IntT9 = from->IntT9;
277         to->IntT10 = from->IntT10;
278         to->IntT11 = from->IntT11;
279         to->IntT12 = from->IntT12;
280         to->IntAt = from->IntAt;
281         to->IntZero = from->IntZero;
282     }
283     if (flags & CONTEXT_FLOATING_POINT)
284     {
285         to->FltF0 = from->FltF0;
286         to->FltF1 = from->FltF1;
287         to->FltF2 = from->FltF2;
288         to->FltF3 = from->FltF3;
289         to->FltF4 = from->FltF4;
290         to->FltF5 = from->FltF5;
291         to->FltF6 = from->FltF6;
292         to->FltF7 = from->FltF7;
293         to->FltF8 = from->FltF8;
294         to->FltF9 = from->FltF9;
295         to->FltF10 = from->FltF10;
296         to->FltF11 = from->FltF11;
297         to->FltF12 = from->FltF12;
298         to->FltF13 = from->FltF13;
299         to->FltF14 = from->FltF14;
300         to->FltF15 = from->FltF15;
301         to->FltF16 = from->FltF16;
302         to->FltF17 = from->FltF17;
303         to->FltF18 = from->FltF18;
304         to->FltF19 = from->FltF19;
305         to->FltF20 = from->FltF20;
306         to->FltF21 = from->FltF21;
307         to->FltF22 = from->FltF22;
308         to->FltF23 = from->FltF23;
309         to->FltF24 = from->FltF24;
310         to->FltF25 = from->FltF25;
311         to->FltF26 = from->FltF26;
312         to->FltF27 = from->FltF27;
313         to->FltF28 = from->FltF28;
314         to->FltF29 = from->FltF29;
315         to->FltF30 = from->FltF30;
316         to->FltF31 = from->FltF31;
317         to->Fpcr = from->Fpcr;
318         to->SoftFpcr = from->SoftFpcr;
319     }
320 }
321
322 /* retrieve the current instruction pointer of a thread */
323 void *get_thread_ip( struct thread *thread )
324 {
325     CONTEXT context;
326     context.Fir = 0;
327     if (suspend_for_ptrace( thread ))
328     {
329         get_thread_context( thread, CONTEXT_CONTROL, &context );
330         resume_after_ptrace( thread );
331     }
332     return (void *)context.Fir;
333 }
334
335 /* determine if we should continue the thread in single-step mode */
336 int get_thread_single_step( struct thread *thread )
337 {
338     return 0;  /* FIXME */
339 }
340
341 /* send a signal to a specific thread */
342 int tkill( int pid, int sig )
343 {
344     /* FIXME: should do something here */
345     errno = ENOSYS;
346     return -1;
347 }
348
349 /* retrieve the current context of a thread */
350 DECL_HANDLER(get_thread_context)
351 {
352     struct thread *thread;
353     void *data;
354     int flags = req->flags & ~CONTEXT_ALPHA;  /* get rid of CPU id */
355
356     if (get_reply_max_size() < sizeof(CONTEXT))
357     {
358         set_error( STATUS_INVALID_PARAMETER );
359         return;
360     }
361     if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
362
363     if ((data = set_reply_data_size( sizeof(CONTEXT) )))
364     {
365         if (thread->context)  /* thread is inside an exception event */
366         {
367             copy_context( data, thread->context, flags );
368             flags = 0;
369         }
370         if (flags && suspend_for_ptrace( thread ))
371         {
372             get_thread_context( thread, flags, data );
373             resume_after_ptrace( thread );
374         }
375     }
376     release_object( thread );
377 }
378
379 /* set the current context of a thread */
380 DECL_HANDLER(set_thread_context)
381 {
382     struct thread *thread;
383     int flags = req->flags & ~CONTEXT_ALPHA;  /* get rid of CPU id */
384
385     if (get_req_data_size() < sizeof(CONTEXT))
386     {
387         set_error( STATUS_INVALID_PARAMETER );
388         return;
389     }
390     if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
391     {
392         if (thread->context)  /* thread is inside an exception event */
393         {
394             copy_context( thread->context, get_req_data(), flags );
395             flags = 0;
396         }
397         if (flags && suspend_for_ptrace( thread ))
398         {
399             set_thread_context( thread, flags, get_req_data() );
400             resume_after_ptrace( thread );
401         }
402         release_object( thread );
403     }
404 }
405
406 #endif  /* __ALPHA__ */