diff options
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 11 | ||||
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 138 | ||||
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 26 | ||||
-rw-r--r-- | arch/x86/ia32/sys_ia32.c | 9 |
4 files changed, 77 insertions, 107 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index a0e1dbe67dc1..127ec3f07214 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -85,8 +85,10 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump) | |||
85 | dump->regs.ax = regs->ax; | 85 | dump->regs.ax = regs->ax; |
86 | dump->regs.ds = current->thread.ds; | 86 | dump->regs.ds = current->thread.ds; |
87 | dump->regs.es = current->thread.es; | 87 | dump->regs.es = current->thread.es; |
88 | asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; | 88 | savesegment(fs, fs); |
89 | asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; | 89 | dump->regs.fs = fs; |
90 | savesegment(gs, gs); | ||
91 | dump->regs.gs = gs; | ||
90 | dump->regs.orig_ax = regs->orig_ax; | 92 | dump->regs.orig_ax = regs->orig_ax; |
91 | dump->regs.ip = regs->ip; | 93 | dump->regs.ip = regs->ip; |
92 | dump->regs.cs = regs->cs; | 94 | dump->regs.cs = regs->cs; |
@@ -430,8 +432,9 @@ beyond_if: | |||
430 | current->mm->start_stack = | 432 | current->mm->start_stack = |
431 | (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); | 433 | (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); |
432 | /* start thread */ | 434 | /* start thread */ |
433 | asm volatile("movl %0,%%fs" :: "r" (0)); \ | 435 | loadsegment(fs, 0); |
434 | asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); | 436 | loadsegment(ds, __USER32_DS); |
437 | loadsegment(es, __USER32_DS); | ||
435 | load_gs_index(0); | 438 | load_gs_index(0); |
436 | (regs)->ip = ex.a_entry; | 439 | (regs)->ip = ex.a_entry; |
437 | (regs)->sp = current->mm->start_stack; | 440 | (regs)->sp = current->mm->start_stack; |
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579a..4bc02b23674b 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -179,9 +179,10 @@ struct sigframe | |||
179 | u32 pretcode; | 179 | u32 pretcode; |
180 | int sig; | 180 | int sig; |
181 | struct sigcontext_ia32 sc; | 181 | struct sigcontext_ia32 sc; |
182 | struct _fpstate_ia32 fpstate; | 182 | struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */ |
183 | unsigned int extramask[_COMPAT_NSIG_WORDS-1]; | 183 | unsigned int extramask[_COMPAT_NSIG_WORDS-1]; |
184 | char retcode[8]; | 184 | char retcode[8]; |
185 | /* fp state follows here */ | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | struct rt_sigframe | 188 | struct rt_sigframe |
@@ -192,8 +193,8 @@ struct rt_sigframe | |||
192 | u32 puc; | 193 | u32 puc; |
193 | compat_siginfo_t info; | 194 | compat_siginfo_t info; |
194 | struct ucontext_ia32 uc; | 195 | struct ucontext_ia32 uc; |
195 | struct _fpstate_ia32 fpstate; | ||
196 | char retcode[8]; | 196 | char retcode[8]; |
197 | /* fp state follows here */ | ||
197 | }; | 198 | }; |
198 | 199 | ||
199 | #define COPY(x) { \ | 200 | #define COPY(x) { \ |
@@ -206,7 +207,7 @@ struct rt_sigframe | |||
206 | { unsigned int cur; \ | 207 | { unsigned int cur; \ |
207 | unsigned short pre; \ | 208 | unsigned short pre; \ |
208 | err |= __get_user(pre, &sc->seg); \ | 209 | err |= __get_user(pre, &sc->seg); \ |
209 | asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ | 210 | savesegment(seg, cur); \ |
210 | pre |= mask; \ | 211 | pre |= mask; \ |
211 | if (pre != cur) loadsegment(seg, pre); } | 212 | if (pre != cur) loadsegment(seg, pre); } |
212 | 213 | ||
@@ -215,7 +216,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
215 | unsigned int *peax) | 216 | unsigned int *peax) |
216 | { | 217 | { |
217 | unsigned int tmpflags, gs, oldgs, err = 0; | 218 | unsigned int tmpflags, gs, oldgs, err = 0; |
218 | struct _fpstate_ia32 __user *buf; | 219 | void __user *buf; |
219 | u32 tmp; | 220 | u32 tmp; |
220 | 221 | ||
221 | /* Always make any pending restarted system calls return -EINTR */ | 222 | /* Always make any pending restarted system calls return -EINTR */ |
@@ -235,7 +236,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
235 | */ | 236 | */ |
236 | err |= __get_user(gs, &sc->gs); | 237 | err |= __get_user(gs, &sc->gs); |
237 | gs |= 3; | 238 | gs |= 3; |
238 | asm("movl %%gs,%0" : "=r" (oldgs)); | 239 | savesegment(gs, oldgs); |
239 | if (gs != oldgs) | 240 | if (gs != oldgs) |
240 | load_gs_index(gs); | 241 | load_gs_index(gs); |
241 | 242 | ||
@@ -259,26 +260,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
259 | 260 | ||
260 | err |= __get_user(tmp, &sc->fpstate); | 261 | err |= __get_user(tmp, &sc->fpstate); |
261 | buf = compat_ptr(tmp); | 262 | buf = compat_ptr(tmp); |
262 | if (buf) { | 263 | err |= restore_i387_xstate_ia32(buf); |
263 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) | ||
264 | goto badframe; | ||
265 | err |= restore_i387_ia32(buf); | ||
266 | } else { | ||
267 | struct task_struct *me = current; | ||
268 | |||
269 | if (used_math()) { | ||
270 | clear_fpu(me); | ||
271 | clear_used_math(); | ||
272 | } | ||
273 | } | ||
274 | 264 | ||
275 | err |= __get_user(tmp, &sc->ax); | 265 | err |= __get_user(tmp, &sc->ax); |
276 | *peax = tmp; | 266 | *peax = tmp; |
277 | 267 | ||
278 | return err; | 268 | return err; |
279 | |||
280 | badframe: | ||
281 | return 1; | ||
282 | } | 269 | } |
283 | 270 | ||
284 | asmlinkage long sys32_sigreturn(struct pt_regs *regs) | 271 | asmlinkage long sys32_sigreturn(struct pt_regs *regs) |
@@ -350,46 +337,42 @@ badframe: | |||
350 | */ | 337 | */ |
351 | 338 | ||
352 | static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | 339 | static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, |
353 | struct _fpstate_ia32 __user *fpstate, | 340 | void __user *fpstate, |
354 | struct pt_regs *regs, unsigned int mask) | 341 | struct pt_regs *regs, unsigned int mask) |
355 | { | 342 | { |
356 | int tmp, err = 0; | 343 | int tmp, err = 0; |
357 | 344 | ||
358 | tmp = 0; | 345 | savesegment(gs, tmp); |
359 | __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); | ||
360 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); | 346 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); |
361 | __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); | 347 | savesegment(fs, tmp); |
362 | err |= __put_user(tmp, (unsigned int __user *)&sc->fs); | 348 | err |= __put_user(tmp, (unsigned int __user *)&sc->fs); |
363 | __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp)); | 349 | savesegment(ds, tmp); |
364 | err |= __put_user(tmp, (unsigned int __user *)&sc->ds); | 350 | err |= __put_user(tmp, (unsigned int __user *)&sc->ds); |
365 | __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp)); | 351 | savesegment(es, tmp); |
366 | err |= __put_user(tmp, (unsigned int __user *)&sc->es); | 352 | err |= __put_user(tmp, (unsigned int __user *)&sc->es); |
367 | 353 | ||
368 | err |= __put_user((u32)regs->di, &sc->di); | 354 | err |= __put_user(regs->di, &sc->di); |
369 | err |= __put_user((u32)regs->si, &sc->si); | 355 | err |= __put_user(regs->si, &sc->si); |
370 | err |= __put_user((u32)regs->bp, &sc->bp); | 356 | err |= __put_user(regs->bp, &sc->bp); |
371 | err |= __put_user((u32)regs->sp, &sc->sp); | 357 | err |= __put_user(regs->sp, &sc->sp); |
372 | err |= __put_user((u32)regs->bx, &sc->bx); | 358 | err |= __put_user(regs->bx, &sc->bx); |
373 | err |= __put_user((u32)regs->dx, &sc->dx); | 359 | err |= __put_user(regs->dx, &sc->dx); |
374 | err |= __put_user((u32)regs->cx, &sc->cx); | 360 | err |= __put_user(regs->cx, &sc->cx); |
375 | err |= __put_user((u32)regs->ax, &sc->ax); | 361 | err |= __put_user(regs->ax, &sc->ax); |
376 | err |= __put_user((u32)regs->cs, &sc->cs); | 362 | err |= __put_user(regs->cs, &sc->cs); |
377 | err |= __put_user((u32)regs->ss, &sc->ss); | 363 | err |= __put_user(regs->ss, &sc->ss); |
378 | err |= __put_user(current->thread.trap_no, &sc->trapno); | 364 | err |= __put_user(current->thread.trap_no, &sc->trapno); |
379 | err |= __put_user(current->thread.error_code, &sc->err); | 365 | err |= __put_user(current->thread.error_code, &sc->err); |
380 | err |= __put_user((u32)regs->ip, &sc->ip); | 366 | err |= __put_user(regs->ip, &sc->ip); |
381 | err |= __put_user((u32)regs->flags, &sc->flags); | 367 | err |= __put_user(regs->flags, &sc->flags); |
382 | err |= __put_user((u32)regs->sp, &sc->sp_at_signal); | 368 | err |= __put_user(regs->sp, &sc->sp_at_signal); |
383 | 369 | ||
384 | tmp = save_i387_ia32(fpstate); | 370 | tmp = save_i387_xstate_ia32(fpstate); |
385 | if (tmp < 0) | 371 | if (tmp < 0) |
386 | err = -EFAULT; | 372 | err = -EFAULT; |
387 | else { | 373 | else |
388 | clear_used_math(); | ||
389 | stts(); | ||
390 | err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), | 374 | err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), |
391 | &sc->fpstate); | 375 | &sc->fpstate); |
392 | } | ||
393 | 376 | ||
394 | /* non-iBCS2 extensions.. */ | 377 | /* non-iBCS2 extensions.. */ |
395 | err |= __put_user(mask, &sc->oldmask); | 378 | err |= __put_user(mask, &sc->oldmask); |
@@ -402,7 +385,8 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
402 | * Determine which stack to use.. | 385 | * Determine which stack to use.. |
403 | */ | 386 | */ |
404 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 387 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
405 | size_t frame_size) | 388 | size_t frame_size, |
389 | void **fpstate) | ||
406 | { | 390 | { |
407 | unsigned long sp; | 391 | unsigned long sp; |
408 | 392 | ||
@@ -421,6 +405,11 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
421 | ka->sa.sa_restorer) | 405 | ka->sa.sa_restorer) |
422 | sp = (unsigned long) ka->sa.sa_restorer; | 406 | sp = (unsigned long) ka->sa.sa_restorer; |
423 | 407 | ||
408 | if (used_math()) { | ||
409 | sp = sp - sig_xstate_ia32_size; | ||
410 | *fpstate = (struct _fpstate_ia32 *) sp; | ||
411 | } | ||
412 | |||
424 | sp -= frame_size; | 413 | sp -= frame_size; |
425 | /* Align the stack pointer according to the i386 ABI, | 414 | /* Align the stack pointer according to the i386 ABI, |
426 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ | 415 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ |
@@ -434,6 +423,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
434 | struct sigframe __user *frame; | 423 | struct sigframe __user *frame; |
435 | void __user *restorer; | 424 | void __user *restorer; |
436 | int err = 0; | 425 | int err = 0; |
426 | void __user *fpstate = NULL; | ||
437 | 427 | ||
438 | /* copy_to_user optimizes that into a single 8 byte store */ | 428 | /* copy_to_user optimizes that into a single 8 byte store */ |
439 | static const struct { | 429 | static const struct { |
@@ -448,25 +438,21 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
448 | 0, | 438 | 0, |
449 | }; | 439 | }; |
450 | 440 | ||
451 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 441 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
452 | 442 | ||
453 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 443 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
454 | goto give_sigsegv; | 444 | return -EFAULT; |
455 | 445 | ||
456 | err |= __put_user(sig, &frame->sig); | 446 | if (__put_user(sig, &frame->sig)) |
457 | if (err) | 447 | return -EFAULT; |
458 | goto give_sigsegv; | ||
459 | 448 | ||
460 | err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, | 449 | if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
461 | set->sig[0]); | 450 | return -EFAULT; |
462 | if (err) | ||
463 | goto give_sigsegv; | ||
464 | 451 | ||
465 | if (_COMPAT_NSIG_WORDS > 1) { | 452 | if (_COMPAT_NSIG_WORDS > 1) { |
466 | err |= __copy_to_user(frame->extramask, &set->sig[1], | 453 | if (__copy_to_user(frame->extramask, &set->sig[1], |
467 | sizeof(frame->extramask)); | 454 | sizeof(frame->extramask))) |
468 | if (err) | 455 | return -EFAULT; |
469 | goto give_sigsegv; | ||
470 | } | 456 | } |
471 | 457 | ||
472 | if (ka->sa.sa_flags & SA_RESTORER) { | 458 | if (ka->sa.sa_flags & SA_RESTORER) { |
@@ -487,7 +473,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
487 | */ | 473 | */ |
488 | err |= __copy_to_user(frame->retcode, &code, 8); | 474 | err |= __copy_to_user(frame->retcode, &code, 8); |
489 | if (err) | 475 | if (err) |
490 | goto give_sigsegv; | 476 | return -EFAULT; |
491 | 477 | ||
492 | /* Set up registers for signal handler */ | 478 | /* Set up registers for signal handler */ |
493 | regs->sp = (unsigned long) frame; | 479 | regs->sp = (unsigned long) frame; |
@@ -498,8 +484,8 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
498 | regs->dx = 0; | 484 | regs->dx = 0; |
499 | regs->cx = 0; | 485 | regs->cx = 0; |
500 | 486 | ||
501 | asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); | 487 | loadsegment(ds, __USER32_DS); |
502 | asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); | 488 | loadsegment(es, __USER32_DS); |
503 | 489 | ||
504 | regs->cs = __USER32_CS; | 490 | regs->cs = __USER32_CS; |
505 | regs->ss = __USER32_DS; | 491 | regs->ss = __USER32_DS; |
@@ -510,10 +496,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
510 | #endif | 496 | #endif |
511 | 497 | ||
512 | return 0; | 498 | return 0; |
513 | |||
514 | give_sigsegv: | ||
515 | force_sigsegv(sig, current); | ||
516 | return -EFAULT; | ||
517 | } | 499 | } |
518 | 500 | ||
519 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 501 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
@@ -522,6 +504,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
522 | struct rt_sigframe __user *frame; | 504 | struct rt_sigframe __user *frame; |
523 | void __user *restorer; | 505 | void __user *restorer; |
524 | int err = 0; | 506 | int err = 0; |
507 | void __user *fpstate = NULL; | ||
525 | 508 | ||
526 | /* __copy_to_user optimizes that into a single 8 byte store */ | 509 | /* __copy_to_user optimizes that into a single 8 byte store */ |
527 | static const struct { | 510 | static const struct { |
@@ -537,30 +520,33 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
537 | 0, | 520 | 0, |
538 | }; | 521 | }; |
539 | 522 | ||
540 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 523 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
541 | 524 | ||
542 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 525 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
543 | goto give_sigsegv; | 526 | return -EFAULT; |
544 | 527 | ||
545 | err |= __put_user(sig, &frame->sig); | 528 | err |= __put_user(sig, &frame->sig); |
546 | err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); | 529 | err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); |
547 | err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); | 530 | err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); |
548 | err |= copy_siginfo_to_user32(&frame->info, info); | 531 | err |= copy_siginfo_to_user32(&frame->info, info); |
549 | if (err) | 532 | if (err) |
550 | goto give_sigsegv; | 533 | return -EFAULT; |
551 | 534 | ||
552 | /* Create the ucontext. */ | 535 | /* Create the ucontext. */ |
553 | err |= __put_user(0, &frame->uc.uc_flags); | 536 | if (cpu_has_xsave) |
537 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
538 | else | ||
539 | err |= __put_user(0, &frame->uc.uc_flags); | ||
554 | err |= __put_user(0, &frame->uc.uc_link); | 540 | err |= __put_user(0, &frame->uc.uc_link); |
555 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 541 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
556 | err |= __put_user(sas_ss_flags(regs->sp), | 542 | err |= __put_user(sas_ss_flags(regs->sp), |
557 | &frame->uc.uc_stack.ss_flags); | 543 | &frame->uc.uc_stack.ss_flags); |
558 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 544 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
559 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 545 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
560 | regs, set->sig[0]); | 546 | regs, set->sig[0]); |
561 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 547 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
562 | if (err) | 548 | if (err) |
563 | goto give_sigsegv; | 549 | return -EFAULT; |
564 | 550 | ||
565 | if (ka->sa.sa_flags & SA_RESTORER) | 551 | if (ka->sa.sa_flags & SA_RESTORER) |
566 | restorer = ka->sa.sa_restorer; | 552 | restorer = ka->sa.sa_restorer; |
@@ -575,7 +561,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
575 | */ | 561 | */ |
576 | err |= __copy_to_user(frame->retcode, &code, 8); | 562 | err |= __copy_to_user(frame->retcode, &code, 8); |
577 | if (err) | 563 | if (err) |
578 | goto give_sigsegv; | 564 | return -EFAULT; |
579 | 565 | ||
580 | /* Set up registers for signal handler */ | 566 | /* Set up registers for signal handler */ |
581 | regs->sp = (unsigned long) frame; | 567 | regs->sp = (unsigned long) frame; |
@@ -591,8 +577,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
591 | regs->dx = (unsigned long) &frame->info; | 577 | regs->dx = (unsigned long) &frame->info; |
592 | regs->cx = (unsigned long) &frame->uc; | 578 | regs->cx = (unsigned long) &frame->uc; |
593 | 579 | ||
594 | asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); | 580 | loadsegment(ds, __USER32_DS); |
595 | asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); | 581 | loadsegment(es, __USER32_DS); |
596 | 582 | ||
597 | regs->cs = __USER32_CS; | 583 | regs->cs = __USER32_CS; |
598 | regs->ss = __USER32_DS; | 584 | regs->ss = __USER32_DS; |
@@ -603,8 +589,4 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
603 | #endif | 589 | #endif |
604 | 590 | ||
605 | return 0; | 591 | return 0; |
606 | |||
607 | give_sigsegv: | ||
608 | force_sigsegv(sig, current); | ||
609 | return -EFAULT; | ||
610 | } | 592 | } |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index ffc1bb4fed7d..eb4314768bf7 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -39,11 +39,11 @@ | |||
39 | .endm | 39 | .endm |
40 | 40 | ||
41 | /* clobbers %eax */ | 41 | /* clobbers %eax */ |
42 | .macro CLEAR_RREGS | 42 | .macro CLEAR_RREGS _r9=rax |
43 | xorl %eax,%eax | 43 | xorl %eax,%eax |
44 | movq %rax,R11(%rsp) | 44 | movq %rax,R11(%rsp) |
45 | movq %rax,R10(%rsp) | 45 | movq %rax,R10(%rsp) |
46 | movq %rax,R9(%rsp) | 46 | movq %\_r9,R9(%rsp) |
47 | movq %rax,R8(%rsp) | 47 | movq %rax,R8(%rsp) |
48 | .endm | 48 | .endm |
49 | 49 | ||
@@ -52,11 +52,10 @@ | |||
52 | * We don't reload %eax because syscall_trace_enter() returned | 52 | * We don't reload %eax because syscall_trace_enter() returned |
53 | * the value it wants us to use in the table lookup. | 53 | * the value it wants us to use in the table lookup. |
54 | */ | 54 | */ |
55 | .macro LOAD_ARGS32 offset | 55 | .macro LOAD_ARGS32 offset, _r9=0 |
56 | movl \offset(%rsp),%r11d | 56 | .if \_r9 |
57 | movl \offset+8(%rsp),%r10d | ||
58 | movl \offset+16(%rsp),%r9d | 57 | movl \offset+16(%rsp),%r9d |
59 | movl \offset+24(%rsp),%r8d | 58 | .endif |
60 | movl \offset+40(%rsp),%ecx | 59 | movl \offset+40(%rsp),%ecx |
61 | movl \offset+48(%rsp),%edx | 60 | movl \offset+48(%rsp),%edx |
62 | movl \offset+56(%rsp),%esi | 61 | movl \offset+56(%rsp),%esi |
@@ -145,7 +144,7 @@ ENTRY(ia32_sysenter_target) | |||
145 | SAVE_ARGS 0,0,1 | 144 | SAVE_ARGS 0,0,1 |
146 | /* no need to do an access_ok check here because rbp has been | 145 | /* no need to do an access_ok check here because rbp has been |
147 | 32bit zero extended */ | 146 | 32bit zero extended */ |
148 | 1: movl (%rbp),%r9d | 147 | 1: movl (%rbp),%ebp |
149 | .section __ex_table,"a" | 148 | .section __ex_table,"a" |
150 | .quad 1b,ia32_badarg | 149 | .quad 1b,ia32_badarg |
151 | .previous | 150 | .previous |
@@ -157,7 +156,7 @@ ENTRY(ia32_sysenter_target) | |||
157 | cmpl $(IA32_NR_syscalls-1),%eax | 156 | cmpl $(IA32_NR_syscalls-1),%eax |
158 | ja ia32_badsys | 157 | ja ia32_badsys |
159 | sysenter_do_call: | 158 | sysenter_do_call: |
160 | IA32_ARG_FIXUP 1 | 159 | IA32_ARG_FIXUP |
161 | sysenter_dispatch: | 160 | sysenter_dispatch: |
162 | call *ia32_sys_call_table(,%rax,8) | 161 | call *ia32_sys_call_table(,%rax,8) |
163 | movq %rax,RAX-ARGOFFSET(%rsp) | 162 | movq %rax,RAX-ARGOFFSET(%rsp) |
@@ -234,20 +233,17 @@ sysexit_audit: | |||
234 | #endif | 233 | #endif |
235 | 234 | ||
236 | sysenter_tracesys: | 235 | sysenter_tracesys: |
237 | xchgl %r9d,%ebp | ||
238 | #ifdef CONFIG_AUDITSYSCALL | 236 | #ifdef CONFIG_AUDITSYSCALL |
239 | testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) | 237 | testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) |
240 | jz sysenter_auditsys | 238 | jz sysenter_auditsys |
241 | #endif | 239 | #endif |
242 | SAVE_REST | 240 | SAVE_REST |
243 | CLEAR_RREGS | 241 | CLEAR_RREGS |
244 | movq %r9,R9(%rsp) | ||
245 | movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ | 242 | movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ |
246 | movq %rsp,%rdi /* &pt_regs -> arg1 */ | 243 | movq %rsp,%rdi /* &pt_regs -> arg1 */ |
247 | call syscall_trace_enter | 244 | call syscall_trace_enter |
248 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 245 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
249 | RESTORE_REST | 246 | RESTORE_REST |
250 | xchgl %ebp,%r9d | ||
251 | cmpl $(IA32_NR_syscalls-1),%eax | 247 | cmpl $(IA32_NR_syscalls-1),%eax |
252 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ | 248 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ |
253 | jmp sysenter_do_call | 249 | jmp sysenter_do_call |
@@ -314,9 +310,9 @@ ENTRY(ia32_cstar_target) | |||
314 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 310 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
315 | CFI_REMEMBER_STATE | 311 | CFI_REMEMBER_STATE |
316 | jnz cstar_tracesys | 312 | jnz cstar_tracesys |
317 | cstar_do_call: | ||
318 | cmpl $IA32_NR_syscalls-1,%eax | 313 | cmpl $IA32_NR_syscalls-1,%eax |
319 | ja ia32_badsys | 314 | ja ia32_badsys |
315 | cstar_do_call: | ||
320 | IA32_ARG_FIXUP 1 | 316 | IA32_ARG_FIXUP 1 |
321 | cstar_dispatch: | 317 | cstar_dispatch: |
322 | call *ia32_sys_call_table(,%rax,8) | 318 | call *ia32_sys_call_table(,%rax,8) |
@@ -357,15 +353,13 @@ cstar_tracesys: | |||
357 | #endif | 353 | #endif |
358 | xchgl %r9d,%ebp | 354 | xchgl %r9d,%ebp |
359 | SAVE_REST | 355 | SAVE_REST |
360 | CLEAR_RREGS | 356 | CLEAR_RREGS r9 |
361 | movq %r9,R9(%rsp) | ||
362 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ | 357 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ |
363 | movq %rsp,%rdi /* &pt_regs -> arg1 */ | 358 | movq %rsp,%rdi /* &pt_regs -> arg1 */ |
364 | call syscall_trace_enter | 359 | call syscall_trace_enter |
365 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 360 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ |
366 | RESTORE_REST | 361 | RESTORE_REST |
367 | xchgl %ebp,%r9d | 362 | xchgl %ebp,%r9d |
368 | movl RSP-ARGOFFSET(%rsp), %r8d | ||
369 | cmpl $(IA32_NR_syscalls-1),%eax | 363 | cmpl $(IA32_NR_syscalls-1),%eax |
370 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ | 364 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ |
371 | jmp cstar_do_call | 365 | jmp cstar_do_call |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index d3c64088b981..beda4232ce69 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -556,15 +556,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, | |||
556 | return ret; | 556 | return ret; |
557 | } | 557 | } |
558 | 558 | ||
559 | /* These are here just in case some old ia32 binary calls it. */ | ||
560 | asmlinkage long sys32_pause(void) | ||
561 | { | ||
562 | current->state = TASK_INTERRUPTIBLE; | ||
563 | schedule(); | ||
564 | return -ERESTARTNOHAND; | ||
565 | } | ||
566 | |||
567 | |||
568 | #ifdef CONFIG_SYSCTL_SYSCALL | 559 | #ifdef CONFIG_SYSCTL_SYSCALL |
569 | struct sysctl_ia32 { | 560 | struct sysctl_ia32 { |
570 | unsigned int name; | 561 | unsigned int name; |