i387: Split up <asm/i387.h> into exported and internal interfaces
[linux-2.6-block.git] / arch / x86 / ia32 / ia32_signal.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/x86_64/ia32/ia32_signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
1da177e4
LT
9 */
10
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
1da177e4
LT
14#include <linux/kernel.h>
15#include <linux/signal.h>
16#include <linux/errno.h>
17#include <linux/wait.h>
18#include <linux/ptrace.h>
19#include <linux/unistd.h>
20#include <linux/stddef.h>
21#include <linux/personality.h>
22#include <linux/compat.h>
9fbbd4dd 23#include <linux/binfmts.h>
1da177e4
LT
24#include <asm/ucontext.h>
25#include <asm/uaccess.h>
26#include <asm/i387.h>
1361b83a 27#include <asm/fpu-internal.h>
1da177e4
LT
28#include <asm/ptrace.h>
29#include <asm/ia32_unistd.h>
30#include <asm/user32.h>
31#include <asm/sigcontext32.h>
1da177e4 32#include <asm/proto.h>
af65d648 33#include <asm/vdso.h>
d98f9d84 34#include <asm/sigframe.h>
2f06de06 35#include <asm/sys_ia32.h>
d98f9d84 36
1da177e4
LT
37#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
38
fbdb7da9
HS
39#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
40 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
41 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
42 X86_EFLAGS_CF)
43
1da177e4
LT
44void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
45
46int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
47{
3b4b7570 48 int err = 0;
99b9cdf7
TG
49
50 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
1da177e4
LT
51 return -EFAULT;
52
3b4b7570
HS
53 put_user_try {
54 /* If you change siginfo_t structure, please make sure that
55 this code is fixed accordingly.
56 It should never copy any pad contained in the structure
57 to avoid security leaks, but must copy the generic
58 3 ints plus the relevant union member. */
59 put_user_ex(from->si_signo, &to->si_signo);
60 put_user_ex(from->si_errno, &to->si_errno);
61 put_user_ex((short)from->si_code, &to->si_code);
62
63 if (from->si_code < 0) {
64 put_user_ex(from->si_pid, &to->si_pid);
65 put_user_ex(from->si_uid, &to->si_uid);
66 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
67 } else {
68 /*
69 * First 32bits of unions are always present:
70 * si_pid === si_band === si_tid === si_addr(LS half)
71 */
72 put_user_ex(from->_sifields._pad[0],
73 &to->_sifields._pad[0]);
74 switch (from->si_code >> 16) {
75 case __SI_FAULT >> 16:
76 break;
77 case __SI_CHLD >> 16:
78 put_user_ex(from->si_utime, &to->si_utime);
79 put_user_ex(from->si_stime, &to->si_stime);
80 put_user_ex(from->si_status, &to->si_status);
81 /* FALL THROUGH */
82 default:
83 case __SI_KILL >> 16:
84 put_user_ex(from->si_uid, &to->si_uid);
85 break;
86 case __SI_POLL >> 16:
87 put_user_ex(from->si_fd, &to->si_fd);
88 break;
89 case __SI_TIMER >> 16:
90 put_user_ex(from->si_overrun, &to->si_overrun);
91 put_user_ex(ptr_to_compat(from->si_ptr),
92 &to->si_ptr);
93 break;
94 /* This is not generated by the kernel as of now. */
95 case __SI_RT >> 16:
96 case __SI_MESGQ >> 16:
97 put_user_ex(from->si_uid, &to->si_uid);
98 put_user_ex(from->si_int, &to->si_int);
99 break;
100 }
1da177e4 101 }
3b4b7570
HS
102 } put_user_catch(err);
103
1da177e4
LT
104 return err;
105}
106
107int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
108{
3b4b7570 109 int err = 0;
1da177e4 110 u32 ptr32;
99b9cdf7
TG
111
112 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
1da177e4
LT
113 return -EFAULT;
114
3b4b7570
HS
115 get_user_try {
116 get_user_ex(to->si_signo, &from->si_signo);
117 get_user_ex(to->si_errno, &from->si_errno);
118 get_user_ex(to->si_code, &from->si_code);
1da177e4 119
3b4b7570
HS
120 get_user_ex(to->si_pid, &from->si_pid);
121 get_user_ex(to->si_uid, &from->si_uid);
122 get_user_ex(ptr32, &from->si_ptr);
123 to->si_ptr = compat_ptr(ptr32);
124 } get_user_catch(err);
1da177e4
LT
125
126 return err;
127}
128
99b9cdf7 129asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
1da177e4 130{
905f29e2
ON
131 sigset_t blocked;
132
1d001df1 133 current->saved_sigmask = current->blocked;
905f29e2
ON
134
135 mask &= _BLOCKABLE;
136 siginitset(&blocked, mask);
137 set_current_blocked(&blocked);
1da177e4 138
1d001df1
AK
139 current->state = TASK_INTERRUPTIBLE;
140 schedule();
905f29e2 141
5a8da0ea 142 set_restore_sigmask();
1d001df1 143 return -ERESTARTNOHAND;
1da177e4
LT
144}
145
99b9cdf7
TG
146asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
147 stack_ia32_t __user *uoss_ptr,
148 struct pt_regs *regs)
1da177e4 149{
99b9cdf7 150 stack_t uss, uoss;
3b4b7570 151 int ret, err = 0;
99b9cdf7
TG
152 mm_segment_t seg;
153
154 if (uss_ptr) {
1da177e4 155 u32 ptr;
99b9cdf7
TG
156
157 memset(&uss, 0, sizeof(stack_t));
3b4b7570
HS
158 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
159 return -EFAULT;
160
161 get_user_try {
162 get_user_ex(ptr, &uss_ptr->ss_sp);
163 get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
164 get_user_ex(uss.ss_size, &uss_ptr->ss_size);
165 } get_user_catch(err);
166
167 if (err)
1da177e4
LT
168 return -EFAULT;
169 uss.ss_sp = compat_ptr(ptr);
170 }
99b9cdf7
TG
171 seg = get_fs();
172 set_fs(KERNEL_DS);
65ea5b03 173 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
99b9cdf7 174 set_fs(seg);
1da177e4 175 if (ret >= 0 && uoss_ptr) {
3b4b7570
HS
176 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
177 return -EFAULT;
178
179 put_user_try {
180 put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
181 put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
182 put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
183 } put_user_catch(err);
184
185 if (err)
1da177e4 186 ret = -EFAULT;
99b9cdf7
TG
187 }
188 return ret;
1da177e4
LT
189}
190
191/*
192 * Do a signal return; undo the signal stack.
193 */
a967bb3f
HS
194#define loadsegment_gs(v) load_gs_index(v)
195#define loadsegment_fs(v) loadsegment(fs, v)
196#define loadsegment_ds(v) loadsegment(ds, v)
197#define loadsegment_es(v) loadsegment(es, v)
198
199#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
200#define set_user_seg(seg, v) loadsegment_##seg(v)
201
b78a5b52 202#define COPY(x) { \
3b4b7570 203 get_user_ex(regs->x, &sc->x); \
1da177e4 204}
1da177e4 205
8801ead4
HS
206#define GET_SEG(seg) ({ \
207 unsigned short tmp; \
208 get_user_ex(tmp, &sc->seg); \
209 tmp; \
210})
211
212#define COPY_SEG_CPL3(seg) do { \
213 regs->seg = GET_SEG(seg) | 3; \
214} while (0)
1da177e4 215
8c6e5ce0 216#define RELOAD_SEG(seg) { \
a967bb3f
HS
217 unsigned int pre = GET_SEG(seg); \
218 unsigned int cur = get_user_seg(seg); \
8c6e5ce0
HS
219 pre |= 3; \
220 if (pre != cur) \
a967bb3f 221 set_user_seg(seg, pre); \
8c6e5ce0 222}
99b9cdf7
TG
223
224static int ia32_restore_sigcontext(struct pt_regs *regs,
225 struct sigcontext_ia32 __user *sc,
047ce935 226 unsigned int *pax)
99b9cdf7 227{
a967bb3f 228 unsigned int tmpflags, err = 0;
ab513701 229 void __user *buf;
99b9cdf7
TG
230 u32 tmp;
231
232 /* Always make any pending restarted system calls return -EINTR */
233 current_thread_info()->restart_block.fn = do_no_restart_syscall;
234
3b4b7570
HS
235 get_user_try {
236 /*
237 * Reload fs and gs if they have changed in the signal
238 * handler. This does not handle long fs/gs base changes in
239 * the handler, but does not clobber them at least in the
240 * normal case.
241 */
a967bb3f 242 RELOAD_SEG(gs);
3b4b7570
HS
243 RELOAD_SEG(fs);
244 RELOAD_SEG(ds);
245 RELOAD_SEG(es);
246
247 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
248 COPY(dx); COPY(cx); COPY(ip);
249 /* Don't touch extended registers */
250
251 COPY_SEG_CPL3(cs);
252 COPY_SEG_CPL3(ss);
253
254 get_user_ex(tmpflags, &sc->flags);
255 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
256 /* disable syscall checks */
257 regs->orig_ax = -1;
258
259 get_user_ex(tmp, &sc->fpstate);
260 buf = compat_ptr(tmp);
261 err |= restore_i387_xstate_ia32(buf);
262
263 get_user_ex(*pax, &sc->ax);
264 } get_user_catch(err);
265
1da177e4 266 return err;
1da177e4
LT
267}
268
269asmlinkage long sys32_sigreturn(struct pt_regs *regs)
270{
3b0d29ee 271 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
1da177e4 272 sigset_t set;
65ea5b03 273 unsigned int ax;
1da177e4
LT
274
275 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
276 goto badframe;
277 if (__get_user(set.sig[0], &frame->sc.oldmask)
278 || (_COMPAT_NSIG_WORDS > 1
99b9cdf7
TG
279 && __copy_from_user((((char *) &set.sig) + 4),
280 &frame->extramask,
1da177e4
LT
281 sizeof(frame->extramask))))
282 goto badframe;
283
284 sigdelsetmask(&set, ~_BLOCKABLE);
905f29e2 285 set_current_blocked(&set);
99b9cdf7 286
65ea5b03 287 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
1da177e4 288 goto badframe;
65ea5b03 289 return ax;
1da177e4
LT
290
291badframe:
292 signal_fault(regs, frame, "32bit sigreturn");
293 return 0;
99b9cdf7 294}
1da177e4
LT
295
296asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
297{
3b0d29ee 298 struct rt_sigframe_ia32 __user *frame;
1da177e4 299 sigset_t set;
65ea5b03 300 unsigned int ax;
1da177e4
LT
301 struct pt_regs tregs;
302
3b0d29ee 303 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
1da177e4
LT
304
305 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
306 goto badframe;
307 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
308 goto badframe;
309
310 sigdelsetmask(&set, ~_BLOCKABLE);
905f29e2 311 set_current_blocked(&set);
99b9cdf7 312
65ea5b03 313 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
1da177e4
LT
314 goto badframe;
315
316 tregs = *regs;
317 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
318 goto badframe;
319
65ea5b03 320 return ax;
1da177e4
LT
321
322badframe:
99b9cdf7 323 signal_fault(regs, frame, "32bit rt sigreturn");
1da177e4 324 return 0;
99b9cdf7 325}
1da177e4
LT
326
327/*
328 * Set up a signal frame.
329 */
330
99b9cdf7 331static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
ab513701 332 void __user *fpstate,
99b9cdf7 333 struct pt_regs *regs, unsigned int mask)
1da177e4 334{
a967bb3f 335 int err = 0;
1da177e4 336
3b4b7570 337 put_user_try {
a967bb3f
HS
338 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
339 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
340 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
341 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
3b4b7570
HS
342
343 put_user_ex(regs->di, &sc->di);
344 put_user_ex(regs->si, &sc->si);
345 put_user_ex(regs->bp, &sc->bp);
346 put_user_ex(regs->sp, &sc->sp);
347 put_user_ex(regs->bx, &sc->bx);
348 put_user_ex(regs->dx, &sc->dx);
349 put_user_ex(regs->cx, &sc->cx);
350 put_user_ex(regs->ax, &sc->ax);
351 put_user_ex(current->thread.trap_no, &sc->trapno);
352 put_user_ex(current->thread.error_code, &sc->err);
353 put_user_ex(regs->ip, &sc->ip);
354 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
355 put_user_ex(regs->flags, &sc->flags);
356 put_user_ex(regs->sp, &sc->sp_at_signal);
357 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
358
359 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
360
361 /* non-iBCS2 extensions.. */
362 put_user_ex(mask, &sc->oldmask);
363 put_user_ex(current->thread.cr2, &sc->cr2);
364 } put_user_catch(err);
1da177e4
LT
365
366 return err;
367}
368
369/*
370 * Determine which stack to use..
371 */
99b9cdf7 372static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
3c1c7f10 373 size_t frame_size,
ab513701 374 void **fpstate)
1da177e4 375{
65ea5b03 376 unsigned long sp;
1da177e4
LT
377
378 /* Default to using normal stack */
65ea5b03 379 sp = regs->sp;
1da177e4
LT
380
381 /* This is the X/Open sanctioned signal stack switching. */
382 if (ka->sa.sa_flags & SA_ONSTACK) {
65ea5b03
PA
383 if (sas_ss_flags(sp) == 0)
384 sp = current->sas_ss_sp + current->sas_ss_size;
1da177e4
LT
385 }
386
387 /* This is the legacy signal stack switching. */
8bee3f0a 388 else if ((regs->ss & 0xffff) != __USER32_DS &&
1da177e4 389 !(ka->sa.sa_flags & SA_RESTORER) &&
99b9cdf7 390 ka->sa.sa_restorer)
65ea5b03 391 sp = (unsigned long) ka->sa.sa_restorer;
1da177e4 392
3c1c7f10
SS
393 if (used_math()) {
394 sp = sp - sig_xstate_ia32_size;
395 *fpstate = (struct _fpstate_ia32 *) sp;
99ea1b93
HS
396 if (save_i387_xstate_ia32(*fpstate) < 0)
397 return (void __user *) -1L;
3c1c7f10
SS
398 }
399
65ea5b03 400 sp -= frame_size;
d347f372
MO
401 /* Align the stack pointer according to the i386 ABI,
402 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
403 sp = ((sp + 4) & -16ul) - 4;
404 return (void __user *) sp;
1da177e4
LT
405}
406
0928d6ef 407int ia32_setup_frame(int sig, struct k_sigaction *ka,
99b9cdf7 408 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 409{
3b0d29ee 410 struct sigframe_ia32 __user *frame;
99b9cdf7 411 void __user *restorer;
1da177e4 412 int err = 0;
ab513701 413 void __user *fpstate = NULL;
1da177e4 414
99b9cdf7
TG
415 /* copy_to_user optimizes that into a single 8 byte store */
416 static const struct {
417 u16 poplmovl;
418 u32 val;
419 u16 int80;
99b9cdf7
TG
420 } __attribute__((packed)) code = {
421 0xb858, /* popl %eax ; movl $...,%eax */
422 __NR_ia32_sigreturn,
423 0x80cd, /* int $0x80 */
99b9cdf7
TG
424 };
425
3c1c7f10 426 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
427
428 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 429 return -EFAULT;
1da177e4 430
2ba48e16 431 if (__put_user(sig, &frame->sig))
3d0aedd9 432 return -EFAULT;
1da177e4 433
2ba48e16 434 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd9 435 return -EFAULT;
1da177e4
LT
436
437 if (_COMPAT_NSIG_WORDS > 1) {
2ba48e16
HS
438 if (__copy_to_user(frame->extramask, &set->sig[1],
439 sizeof(frame->extramask)))
3d0aedd9 440 return -EFAULT;
1da177e4 441 }
1da177e4 442
af65d648 443 if (ka->sa.sa_flags & SA_RESTORER) {
99b9cdf7 444 restorer = ka->sa.sa_restorer;
af65d648
RM
445 } else {
446 /* Return stub is in 32bit vsyscall page */
1a3e4ca4 447 if (current->mm->context.vdso)
af65d648
RM
448 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
449 sigreturn);
450 else
ade1af77 451 restorer = &frame->retcode;
af65d648 452 }
99b9cdf7 453
3b4b7570
HS
454 put_user_try {
455 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
456
457 /*
458 * These are actually not used anymore, but left because some
459 * gdb versions depend on them as a marker.
460 */
461 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
462 } put_user_catch(err);
463
1da177e4 464 if (err)
3d0aedd9 465 return -EFAULT;
1da177e4
LT
466
467 /* Set up registers for signal handler */
65ea5b03
PA
468 regs->sp = (unsigned long) frame;
469 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 470
536e3ee4 471 /* Make -mregparm=3 work */
65ea5b03
PA
472 regs->ax = sig;
473 regs->dx = 0;
474 regs->cx = 0;
536e3ee4 475
b6edbb1e
JF
476 loadsegment(ds, __USER32_DS);
477 loadsegment(es, __USER32_DS);
1da177e4 478
99b9cdf7
TG
479 regs->cs = __USER32_CS;
480 regs->ss = __USER32_DS;
1da177e4 481
1d001df1 482 return 0;
1da177e4
LT
483}
484
0928d6ef 485int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
99b9cdf7 486 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 487{
3b0d29ee 488 struct rt_sigframe_ia32 __user *frame;
af65d648 489 void __user *restorer;
1da177e4 490 int err = 0;
ab513701 491 void __user *fpstate = NULL;
1da177e4 492
99b9cdf7
TG
493 /* __copy_to_user optimizes that into a single 8 byte store */
494 static const struct {
495 u8 movl;
496 u32 val;
497 u16 int80;
9cc3c49e 498 u8 pad;
99b9cdf7
TG
499 } __attribute__((packed)) code = {
500 0xb8,
501 __NR_ia32_rt_sigreturn,
502 0x80cd,
503 0,
504 };
505
3c1c7f10 506 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
507
508 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 509 return -EFAULT;
1da177e4 510
3b4b7570
HS
511 put_user_try {
512 put_user_ex(sig, &frame->sig);
513 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
514 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
515 err |= copy_siginfo_to_user32(&frame->info, info);
1da177e4 516
3b4b7570
HS
517 /* Create the ucontext. */
518 if (cpu_has_xsave)
519 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
520 else
521 put_user_ex(0, &frame->uc.uc_flags);
522 put_user_ex(0, &frame->uc.uc_link);
523 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
524 put_user_ex(sas_ss_flags(regs->sp),
525 &frame->uc.uc_stack.ss_flags);
526 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
527 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
528 regs, set->sig[0]);
529 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
530
531 if (ka->sa.sa_flags & SA_RESTORER)
532 restorer = ka->sa.sa_restorer;
533 else
534 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
535 rt_sigreturn);
536 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
537
538 /*
539 * Not actually used anymore, but left because some gdb
540 * versions need it.
541 */
542 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
543 } put_user_catch(err);
1da177e4 544
1da177e4 545 if (err)
3d0aedd9 546 return -EFAULT;
1da177e4
LT
547
548 /* Set up registers for signal handler */
65ea5b03
PA
549 regs->sp = (unsigned long) frame;
550 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 551
a7aacdf9 552 /* Make -mregparm=3 work */
65ea5b03
PA
553 regs->ax = sig;
554 regs->dx = (unsigned long) &frame->info;
555 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 556
b6edbb1e
JF
557 loadsegment(ds, __USER32_DS);
558 loadsegment(es, __USER32_DS);
99b9cdf7
TG
559
560 regs->cs = __USER32_CS;
561 regs->ss = __USER32_DS;
1da177e4 562
1d001df1 563 return 0;
1da177e4 564}