diff options
-rw-r--r-- | arch/x86/include/asm/linkage.h | 7 | ||||
-rw-r--r-- | arch/x86/include/asm/syscalls.h | 25 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 20 | ||||
-rw-r--r-- | arch/x86/kernel/ioport.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 35 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 35 | ||||
-rw-r--r-- | arch/x86/kernel/syscall_table_32.S | 20 | ||||
-rw-r--r-- | arch/x86/kernel/vm86_32.c | 15 |
8 files changed, 81 insertions, 80 deletions
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h index 5d98d0b68ff..2fd5926fb97 100644 --- a/arch/x86/include/asm/linkage.h +++ b/arch/x86/include/asm/linkage.h | |||
@@ -18,6 +18,13 @@ | |||
18 | #define asmregparm __attribute__((regparm(3))) | 18 | #define asmregparm __attribute__((regparm(3))) |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * For syscalls that need a pointer to the pt_regs struct (ie. fork). | ||
22 | * The regs pointer is passed in %eax as the first argument. The | ||
23 | * remaining function arguments remain on the stack. | ||
24 | */ | ||
25 | #define ptregscall __attribute__((regparm(1))) | ||
26 | |||
27 | /* | ||
21 | * Make sure the compiler doesn't do anything stupid with the | 28 | * Make sure the compiler doesn't do anything stupid with the |
22 | * arguments on the stack - they are owned by the *caller*, not | 29 | * arguments on the stack - they are owned by the *caller*, not |
23 | * the callee. This just fools gcc into not spilling into them, | 30 | * the callee. This just fools gcc into not spilling into them, |
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index c0b0bda754e..617295255a1 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -29,21 +29,26 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *); | |||
29 | /* X86_32 only */ | 29 | /* X86_32 only */ |
30 | #ifdef CONFIG_X86_32 | 30 | #ifdef CONFIG_X86_32 |
31 | /* kernel/process_32.c */ | 31 | /* kernel/process_32.c */ |
32 | asmlinkage int sys_fork(struct pt_regs); | 32 | ptregscall int sys_fork(struct pt_regs *); |
33 | asmlinkage int sys_clone(struct pt_regs); | 33 | ptregscall int sys_clone(struct pt_regs *, unsigned long, |
34 | asmlinkage int sys_vfork(struct pt_regs); | 34 | unsigned long, int __user *, |
35 | asmlinkage int sys_execve(struct pt_regs); | 35 | unsigned long, int __user *); |
36 | ptregscall int sys_vfork(struct pt_regs *); | ||
37 | ptregscall int sys_execve(struct pt_regs *, char __user *, | ||
38 | char __user * __user *, | ||
39 | char __user * __user *); | ||
36 | 40 | ||
37 | /* kernel/signal_32.c */ | 41 | /* kernel/signal_32.c */ |
38 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); | 42 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); |
39 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, | 43 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, |
40 | struct old_sigaction __user *); | 44 | struct old_sigaction __user *); |
41 | asmlinkage int sys_sigaltstack(unsigned long); | 45 | ptregscall int sys_sigaltstack(struct pt_regs *, const stack_t __user *, |
42 | asmlinkage unsigned long sys_sigreturn(unsigned long); | 46 | stack_t __user *); |
43 | asmlinkage int sys_rt_sigreturn(unsigned long); | 47 | ptregscall unsigned long sys_sigreturn(struct pt_regs *); |
48 | ptregscall int sys_rt_sigreturn(struct pt_regs *); | ||
44 | 49 | ||
45 | /* kernel/ioport.c */ | 50 | /* kernel/ioport.c */ |
46 | asmlinkage long sys_iopl(unsigned long); | 51 | ptregscall long sys_iopl(struct pt_regs *, unsigned int); |
47 | 52 | ||
48 | /* kernel/sys_i386_32.c */ | 53 | /* kernel/sys_i386_32.c */ |
49 | asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, | 54 | asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, |
@@ -59,8 +64,8 @@ struct oldold_utsname; | |||
59 | asmlinkage int sys_olduname(struct oldold_utsname __user *); | 64 | asmlinkage int sys_olduname(struct oldold_utsname __user *); |
60 | 65 | ||
61 | /* kernel/vm86_32.c */ | 66 | /* kernel/vm86_32.c */ |
62 | asmlinkage int sys_vm86old(struct pt_regs); | 67 | ptregscall int sys_vm86old(struct pt_regs *, struct vm86_struct __user *); |
63 | asmlinkage int sys_vm86(struct pt_regs); | 68 | ptregscall int sys_vm86(struct pt_regs *, unsigned long, unsigned long); |
64 | 69 | ||
65 | #else /* CONFIG_X86_32 */ | 70 | #else /* CONFIG_X86_32 */ |
66 | 71 | ||
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 5f5bd22adcd..3de7b5710dc 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -697,6 +697,26 @@ syscall_badsys: | |||
697 | END(syscall_badsys) | 697 | END(syscall_badsys) |
698 | CFI_ENDPROC | 698 | CFI_ENDPROC |
699 | 699 | ||
700 | /* | ||
701 | * System calls that need a pt_regs pointer. | ||
702 | */ | ||
703 | #define PTREGSCALL(name) \ | ||
704 | ALIGN; \ | ||
705 | ptregs_##name: \ | ||
706 | leal 4(%esp),%eax; \ | ||
707 | jmp sys_##name; | ||
708 | |||
709 | PTREGSCALL(iopl) | ||
710 | PTREGSCALL(fork) | ||
711 | PTREGSCALL(clone) | ||
712 | PTREGSCALL(vfork) | ||
713 | PTREGSCALL(execve) | ||
714 | PTREGSCALL(sigaltstack) | ||
715 | PTREGSCALL(sigreturn) | ||
716 | PTREGSCALL(rt_sigreturn) | ||
717 | PTREGSCALL(vm86) | ||
718 | PTREGSCALL(vm86old) | ||
719 | |||
700 | .macro FIXUP_ESPFIX_STACK | 720 | .macro FIXUP_ESPFIX_STACK |
701 | /* since we are on a wrong stack, we cant make it a C code :( */ | 721 | /* since we are on a wrong stack, we cant make it a C code :( */ |
702 | PER_CPU(gdt_page, %ebx) | 722 | PER_CPU(gdt_page, %ebx) |
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index b12208f4dfe..7ec14864631 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c | |||
@@ -131,10 +131,8 @@ static int do_iopl(unsigned int level, struct pt_regs *regs) | |||
131 | } | 131 | } |
132 | 132 | ||
133 | #ifdef CONFIG_X86_32 | 133 | #ifdef CONFIG_X86_32 |
134 | asmlinkage long sys_iopl(unsigned long regsp) | 134 | ptregscall long sys_iopl(struct pt_regs *regs, unsigned int level) |
135 | { | 135 | { |
136 | struct pt_regs *regs = (struct pt_regs *)®sp; | ||
137 | unsigned int level = regs->bx; | ||
138 | struct thread_struct *t = ¤t->thread; | 136 | struct thread_struct *t = ¤t->thread; |
139 | int rc; | 137 | int rc; |
140 | 138 | ||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index b50604bb1e4..5a9dcfb01f7 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -603,24 +603,18 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
603 | return prev_p; | 603 | return prev_p; |
604 | } | 604 | } |
605 | 605 | ||
606 | asmlinkage int sys_fork(struct pt_regs regs) | 606 | ptregscall int sys_fork(struct pt_regs *regs) |
607 | { | 607 | { |
608 | return do_fork(SIGCHLD, regs.sp, ®s, 0, NULL, NULL); | 608 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); |
609 | } | 609 | } |
610 | 610 | ||
611 | asmlinkage int sys_clone(struct pt_regs regs) | 611 | ptregscall int sys_clone(struct pt_regs *regs, unsigned long clone_flags, |
612 | unsigned long newsp, int __user *parent_tidptr, | ||
613 | unsigned long unused, int __user *child_tidptr) | ||
612 | { | 614 | { |
613 | unsigned long clone_flags; | ||
614 | unsigned long newsp; | ||
615 | int __user *parent_tidptr, *child_tidptr; | ||
616 | |||
617 | clone_flags = regs.bx; | ||
618 | newsp = regs.cx; | ||
619 | parent_tidptr = (int __user *)regs.dx; | ||
620 | child_tidptr = (int __user *)regs.di; | ||
621 | if (!newsp) | 615 | if (!newsp) |
622 | newsp = regs.sp; | 616 | newsp = regs->sp; |
623 | return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); | 617 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); |
624 | } | 618 | } |
625 | 619 | ||
626 | /* | 620 | /* |
@@ -633,27 +627,26 @@ asmlinkage int sys_clone(struct pt_regs regs) | |||
633 | * do not have enough call-clobbered registers to hold all | 627 | * do not have enough call-clobbered registers to hold all |
634 | * the information you need. | 628 | * the information you need. |
635 | */ | 629 | */ |
636 | asmlinkage int sys_vfork(struct pt_regs regs) | 630 | ptregscall int sys_vfork(struct pt_regs *regs) |
637 | { | 631 | { |
638 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, ®s, 0, NULL, NULL); | 632 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL); |
639 | } | 633 | } |
640 | 634 | ||
641 | /* | 635 | /* |
642 | * sys_execve() executes a new program. | 636 | * sys_execve() executes a new program. |
643 | */ | 637 | */ |
644 | asmlinkage int sys_execve(struct pt_regs regs) | 638 | ptregscall int sys_execve(struct pt_regs *regs, char __user *u_filename, |
639 | char __user * __user *argv, | ||
640 | char __user * __user *envp) | ||
645 | { | 641 | { |
646 | int error; | 642 | int error; |
647 | char *filename; | 643 | char *filename; |
648 | 644 | ||
649 | filename = getname((char __user *) regs.bx); | 645 | filename = getname(u_filename); |
650 | error = PTR_ERR(filename); | 646 | error = PTR_ERR(filename); |
651 | if (IS_ERR(filename)) | 647 | if (IS_ERR(filename)) |
652 | goto out; | 648 | goto out; |
653 | error = do_execve(filename, | 649 | error = do_execve(filename, argv, envp, regs); |
654 | (char __user * __user *) regs.cx, | ||
655 | (char __user * __user *) regs.dx, | ||
656 | ®s); | ||
657 | if (error == 0) { | 650 | if (error == 0) { |
658 | /* Make sure we don't return using sysenter.. */ | 651 | /* Make sure we don't return using sysenter.. */ |
659 | set_thread_flag(TIF_IRET); | 652 | set_thread_flag(TIF_IRET); |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 8562387c75a..d7a158367e3 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -549,39 +549,28 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
549 | #endif /* CONFIG_X86_32 */ | 549 | #endif /* CONFIG_X86_32 */ |
550 | 550 | ||
551 | #ifdef CONFIG_X86_32 | 551 | #ifdef CONFIG_X86_32 |
552 | asmlinkage int sys_sigaltstack(unsigned long bx) | 552 | ptregscall int |
553 | { | 553 | sys_sigaltstack(struct pt_regs *regs, const stack_t __user *uss, |
554 | /* | 554 | stack_t __user *uoss) |
555 | * This is needed to make gcc realize it doesn't own the | ||
556 | * "struct pt_regs" | ||
557 | */ | ||
558 | struct pt_regs *regs = (struct pt_regs *)&bx; | ||
559 | const stack_t __user *uss = (const stack_t __user *)bx; | ||
560 | stack_t __user *uoss = (stack_t __user *)regs->cx; | ||
561 | |||
562 | return do_sigaltstack(uss, uoss, regs->sp); | ||
563 | } | ||
564 | #else /* !CONFIG_X86_32 */ | 555 | #else /* !CONFIG_X86_32 */ |
565 | asmlinkage long | 556 | asmlinkage long |
566 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 557 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
567 | struct pt_regs *regs) | 558 | struct pt_regs *regs) |
559 | #endif /* CONFIG_X86_32 */ | ||
568 | { | 560 | { |
569 | return do_sigaltstack(uss, uoss, regs->sp); | 561 | return do_sigaltstack(uss, uoss, regs->sp); |
570 | } | 562 | } |
571 | #endif /* CONFIG_X86_32 */ | ||
572 | 563 | ||
573 | /* | 564 | /* |
574 | * Do a signal return; undo the signal stack. | 565 | * Do a signal return; undo the signal stack. |
575 | */ | 566 | */ |
576 | #ifdef CONFIG_X86_32 | 567 | #ifdef CONFIG_X86_32 |
577 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) | 568 | ptregscall unsigned long sys_sigreturn(struct pt_regs *regs) |
578 | { | 569 | { |
579 | struct sigframe __user *frame; | 570 | struct sigframe __user *frame; |
580 | struct pt_regs *regs; | ||
581 | unsigned long ax; | 571 | unsigned long ax; |
582 | sigset_t set; | 572 | sigset_t set; |
583 | 573 | ||
584 | regs = (struct pt_regs *) &__unused; | ||
585 | frame = (struct sigframe __user *)(regs->sp - 8); | 574 | frame = (struct sigframe __user *)(regs->sp - 8); |
586 | 575 | ||
587 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 576 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -640,23 +629,13 @@ badframe: | |||
640 | } | 629 | } |
641 | 630 | ||
642 | #ifdef CONFIG_X86_32 | 631 | #ifdef CONFIG_X86_32 |
643 | /* | 632 | ptregscall int sys_rt_sigreturn(struct pt_regs *regs) |
644 | * Note: do not pass in pt_regs directly as with tail-call optimization | ||
645 | * GCC will incorrectly stomp on the caller's frame and corrupt user-space | ||
646 | * register state: | ||
647 | */ | ||
648 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
649 | { | ||
650 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
651 | |||
652 | return do_rt_sigreturn(regs); | ||
653 | } | ||
654 | #else /* !CONFIG_X86_32 */ | 633 | #else /* !CONFIG_X86_32 */ |
655 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 634 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) |
635 | #endif /* CONFIG_X86_32 */ | ||
656 | { | 636 | { |
657 | return do_rt_sigreturn(regs); | 637 | return do_rt_sigreturn(regs); |
658 | } | 638 | } |
659 | #endif /* CONFIG_X86_32 */ | ||
660 | 639 | ||
661 | /* | 640 | /* |
662 | * OK, we're invoking a handler: | 641 | * OK, we're invoking a handler: |
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index e2e86a08f31..3bdb64829b8 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S | |||
@@ -1,7 +1,7 @@ | |||
1 | ENTRY(sys_call_table) | 1 | ENTRY(sys_call_table) |
2 | .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ | 2 | .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ |
3 | .long sys_exit | 3 | .long sys_exit |
4 | .long sys_fork | 4 | .long ptregs_fork |
5 | .long sys_read | 5 | .long sys_read |
6 | .long sys_write | 6 | .long sys_write |
7 | .long sys_open /* 5 */ | 7 | .long sys_open /* 5 */ |
@@ -10,7 +10,7 @@ ENTRY(sys_call_table) | |||
10 | .long sys_creat | 10 | .long sys_creat |
11 | .long sys_link | 11 | .long sys_link |
12 | .long sys_unlink /* 10 */ | 12 | .long sys_unlink /* 10 */ |
13 | .long sys_execve | 13 | .long ptregs_execve |
14 | .long sys_chdir | 14 | .long sys_chdir |
15 | .long sys_time | 15 | .long sys_time |
16 | .long sys_mknod | 16 | .long sys_mknod |
@@ -109,17 +109,17 @@ ENTRY(sys_call_table) | |||
109 | .long sys_newlstat | 109 | .long sys_newlstat |
110 | .long sys_newfstat | 110 | .long sys_newfstat |
111 | .long sys_uname | 111 | .long sys_uname |
112 | .long sys_iopl /* 110 */ | 112 | .long ptregs_iopl /* 110 */ |
113 | .long sys_vhangup | 113 | .long sys_vhangup |
114 | .long sys_ni_syscall /* old "idle" system call */ | 114 | .long sys_ni_syscall /* old "idle" system call */ |
115 | .long sys_vm86old | 115 | .long ptregs_vm86old |
116 | .long sys_wait4 | 116 | .long sys_wait4 |
117 | .long sys_swapoff /* 115 */ | 117 | .long sys_swapoff /* 115 */ |
118 | .long sys_sysinfo | 118 | .long sys_sysinfo |
119 | .long sys_ipc | 119 | .long sys_ipc |
120 | .long sys_fsync | 120 | .long sys_fsync |
121 | .long sys_sigreturn | 121 | .long ptregs_sigreturn |
122 | .long sys_clone /* 120 */ | 122 | .long ptregs_clone /* 120 */ |
123 | .long sys_setdomainname | 123 | .long sys_setdomainname |
124 | .long sys_newuname | 124 | .long sys_newuname |
125 | .long sys_modify_ldt | 125 | .long sys_modify_ldt |
@@ -165,14 +165,14 @@ ENTRY(sys_call_table) | |||
165 | .long sys_mremap | 165 | .long sys_mremap |
166 | .long sys_setresuid16 | 166 | .long sys_setresuid16 |
167 | .long sys_getresuid16 /* 165 */ | 167 | .long sys_getresuid16 /* 165 */ |
168 | .long sys_vm86 | 168 | .long ptregs_vm86 |
169 | .long sys_ni_syscall /* Old sys_query_module */ | 169 | .long sys_ni_syscall /* Old sys_query_module */ |
170 | .long sys_poll | 170 | .long sys_poll |
171 | .long sys_nfsservctl | 171 | .long sys_nfsservctl |
172 | .long sys_setresgid16 /* 170 */ | 172 | .long sys_setresgid16 /* 170 */ |
173 | .long sys_getresgid16 | 173 | .long sys_getresgid16 |
174 | .long sys_prctl | 174 | .long sys_prctl |
175 | .long sys_rt_sigreturn | 175 | .long ptregs_rt_sigreturn |
176 | .long sys_rt_sigaction | 176 | .long sys_rt_sigaction |
177 | .long sys_rt_sigprocmask /* 175 */ | 177 | .long sys_rt_sigprocmask /* 175 */ |
178 | .long sys_rt_sigpending | 178 | .long sys_rt_sigpending |
@@ -185,11 +185,11 @@ ENTRY(sys_call_table) | |||
185 | .long sys_getcwd | 185 | .long sys_getcwd |
186 | .long sys_capget | 186 | .long sys_capget |
187 | .long sys_capset /* 185 */ | 187 | .long sys_capset /* 185 */ |
188 | .long sys_sigaltstack | 188 | .long ptregs_sigaltstack |
189 | .long sys_sendfile | 189 | .long sys_sendfile |
190 | .long sys_ni_syscall /* reserved for streams1 */ | 190 | .long sys_ni_syscall /* reserved for streams1 */ |
191 | .long sys_ni_syscall /* reserved for streams2 */ | 191 | .long sys_ni_syscall /* reserved for streams2 */ |
192 | .long sys_vfork /* 190 */ | 192 | .long ptregs_vfork /* 190 */ |
193 | .long sys_getrlimit | 193 | .long sys_getrlimit |
194 | .long sys_mmap2 | 194 | .long sys_mmap2 |
195 | .long sys_truncate64 | 195 | .long sys_truncate64 |
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 55ea30d2a3d..8fa6ba7c923 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
@@ -197,9 +197,8 @@ out: | |||
197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); | 197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); |
198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); | 198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); |
199 | 199 | ||
200 | asmlinkage int sys_vm86old(struct pt_regs regs) | 200 | ptregscall int sys_vm86old(struct pt_regs *regs, struct vm86_struct __user *v86) |
201 | { | 201 | { |
202 | struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs.bx; | ||
203 | struct kernel_vm86_struct info; /* declare this _on top_, | 202 | struct kernel_vm86_struct info; /* declare this _on top_, |
204 | * this avoids wasting of stack space. | 203 | * this avoids wasting of stack space. |
205 | * This remains on the stack until we | 204 | * This remains on the stack until we |
@@ -218,7 +217,7 @@ asmlinkage int sys_vm86old(struct pt_regs regs) | |||
218 | if (tmp) | 217 | if (tmp) |
219 | goto out; | 218 | goto out; |
220 | memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); | 219 | memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); |
221 | info.regs32 = ®s; | 220 | info.regs32 = regs; |
222 | tsk->thread.vm86_info = v86; | 221 | tsk->thread.vm86_info = v86; |
223 | do_sys_vm86(&info, tsk); | 222 | do_sys_vm86(&info, tsk); |
224 | ret = 0; /* we never return here */ | 223 | ret = 0; /* we never return here */ |
@@ -227,7 +226,7 @@ out: | |||
227 | } | 226 | } |
228 | 227 | ||
229 | 228 | ||
230 | asmlinkage int sys_vm86(struct pt_regs regs) | 229 | ptregscall int sys_vm86(struct pt_regs *regs, unsigned long cmd, unsigned long arg) |
231 | { | 230 | { |
232 | struct kernel_vm86_struct info; /* declare this _on top_, | 231 | struct kernel_vm86_struct info; /* declare this _on top_, |
233 | * this avoids wasting of stack space. | 232 | * this avoids wasting of stack space. |
@@ -239,12 +238,12 @@ asmlinkage int sys_vm86(struct pt_regs regs) | |||
239 | struct vm86plus_struct __user *v86; | 238 | struct vm86plus_struct __user *v86; |
240 | 239 | ||
241 | tsk = current; | 240 | tsk = current; |
242 | switch (regs.bx) { | 241 | switch (cmd) { |
243 | case VM86_REQUEST_IRQ: | 242 | case VM86_REQUEST_IRQ: |
244 | case VM86_FREE_IRQ: | 243 | case VM86_FREE_IRQ: |
245 | case VM86_GET_IRQ_BITS: | 244 | case VM86_GET_IRQ_BITS: |
246 | case VM86_GET_AND_RESET_IRQ: | 245 | case VM86_GET_AND_RESET_IRQ: |
247 | ret = do_vm86_irq_handling(regs.bx, (int)regs.cx); | 246 | ret = do_vm86_irq_handling(cmd, (int)arg); |
248 | goto out; | 247 | goto out; |
249 | case VM86_PLUS_INSTALL_CHECK: | 248 | case VM86_PLUS_INSTALL_CHECK: |
250 | /* | 249 | /* |
@@ -261,14 +260,14 @@ asmlinkage int sys_vm86(struct pt_regs regs) | |||
261 | ret = -EPERM; | 260 | ret = -EPERM; |
262 | if (tsk->thread.saved_sp0) | 261 | if (tsk->thread.saved_sp0) |
263 | goto out; | 262 | goto out; |
264 | v86 = (struct vm86plus_struct __user *)regs.cx; | 263 | v86 = (struct vm86plus_struct __user *)arg; |
265 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, | 264 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, |
266 | offsetof(struct kernel_vm86_struct, regs32) - | 265 | offsetof(struct kernel_vm86_struct, regs32) - |
267 | sizeof(info.regs)); | 266 | sizeof(info.regs)); |
268 | ret = -EFAULT; | 267 | ret = -EFAULT; |
269 | if (tmp) | 268 | if (tmp) |
270 | goto out; | 269 | goto out; |
271 | info.regs32 = ®s; | 270 | info.regs32 = regs; |
272 | info.vm86plus.is_vm86pus = 1; | 271 | info.vm86plus.is_vm86pus = 1; |
273 | tsk->thread.vm86_info = (struct vm86_struct __user *)v86; | 272 | tsk->thread.vm86_info = (struct vm86_struct __user *)v86; |
274 | do_sys_vm86(&info, tsk); | 273 | do_sys_vm86(&info, tsk); |