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