aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/linkage.h7
-rw-r--r--arch/x86/include/asm/syscalls.h25
-rw-r--r--arch/x86/kernel/entry_32.S20
-rw-r--r--arch/x86/kernel/ioport.c4
-rw-r--r--arch/x86/kernel/process_32.c35
-rw-r--r--arch/x86/kernel/signal.c35
-rw-r--r--arch/x86/kernel/syscall_table_32.S20
-rw-r--r--arch/x86/kernel/vm86_32.c15
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 */
32asmlinkage int sys_fork(struct pt_regs); 32ptregscall int sys_fork(struct pt_regs *);
33asmlinkage int sys_clone(struct pt_regs); 33ptregscall int sys_clone(struct pt_regs *, unsigned long,
34asmlinkage int sys_vfork(struct pt_regs); 34 unsigned long, int __user *,
35asmlinkage int sys_execve(struct pt_regs); 35 unsigned long, int __user *);
36ptregscall int sys_vfork(struct pt_regs *);
37ptregscall 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 */
38asmlinkage int sys_sigsuspend(int, int, old_sigset_t); 42asmlinkage int sys_sigsuspend(int, int, old_sigset_t);
39asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, 43asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
40 struct old_sigaction __user *); 44 struct old_sigaction __user *);
41asmlinkage int sys_sigaltstack(unsigned long); 45ptregscall int sys_sigaltstack(struct pt_regs *, const stack_t __user *,
42asmlinkage unsigned long sys_sigreturn(unsigned long); 46 stack_t __user *);
43asmlinkage int sys_rt_sigreturn(unsigned long); 47ptregscall unsigned long sys_sigreturn(struct pt_regs *);
48ptregscall int sys_rt_sigreturn(struct pt_regs *);
44 49
45/* kernel/ioport.c */ 50/* kernel/ioport.c */
46asmlinkage long sys_iopl(unsigned long); 51ptregscall long sys_iopl(struct pt_regs *, unsigned int);
47 52
48/* kernel/sys_i386_32.c */ 53/* kernel/sys_i386_32.c */
49asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, 54asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
@@ -59,8 +64,8 @@ struct oldold_utsname;
59asmlinkage int sys_olduname(struct oldold_utsname __user *); 64asmlinkage int sys_olduname(struct oldold_utsname __user *);
60 65
61/* kernel/vm86_32.c */ 66/* kernel/vm86_32.c */
62asmlinkage int sys_vm86old(struct pt_regs); 67ptregscall int sys_vm86old(struct pt_regs *, struct vm86_struct __user *);
63asmlinkage int sys_vm86(struct pt_regs); 68ptregscall 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:
697END(syscall_badsys) 697END(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; \
705ptregs_##name: \
706 leal 4(%esp),%eax; \
707 jmp sys_##name;
708
709PTREGSCALL(iopl)
710PTREGSCALL(fork)
711PTREGSCALL(clone)
712PTREGSCALL(vfork)
713PTREGSCALL(execve)
714PTREGSCALL(sigaltstack)
715PTREGSCALL(sigreturn)
716PTREGSCALL(rt_sigreturn)
717PTREGSCALL(vm86)
718PTREGSCALL(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
134asmlinkage long sys_iopl(unsigned long regsp) 134ptregscall long sys_iopl(struct pt_regs *regs, unsigned int level)
135{ 135{
136 struct pt_regs *regs = (struct pt_regs *)&regsp;
137 unsigned int level = regs->bx;
138 struct thread_struct *t = &current->thread; 136 struct thread_struct *t = &current->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
606asmlinkage int sys_fork(struct pt_regs regs) 606ptregscall int sys_fork(struct pt_regs *regs)
607{ 607{
608 return do_fork(SIGCHLD, regs.sp, &regs, 0, NULL, NULL); 608 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
609} 609}
610 610
611asmlinkage int sys_clone(struct pt_regs regs) 611ptregscall 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, &regs, 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 */
636asmlinkage int sys_vfork(struct pt_regs regs) 630ptregscall int sys_vfork(struct pt_regs *regs)
637{ 631{
638 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs, 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 */
644asmlinkage int sys_execve(struct pt_regs regs) 638ptregscall 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 &regs);
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
552asmlinkage int sys_sigaltstack(unsigned long bx) 552ptregscall int
553{ 553sys_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 */
565asmlinkage long 556asmlinkage long
566sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 557sys_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
577asmlinkage unsigned long sys_sigreturn(unsigned long __unused) 568ptregscall 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/* 632ptregscall 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 */
648asmlinkage 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 */
655asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) 634asmlinkage 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 @@
1ENTRY(sys_call_table) 1ENTRY(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:
197static int do_vm86_irq_handling(int subfunction, int irqnumber); 197static int do_vm86_irq_handling(int subfunction, int irqnumber);
198static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); 198static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
199 199
200asmlinkage int sys_vm86old(struct pt_regs regs) 200ptregscall 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 = &regs; 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
230asmlinkage int sys_vm86(struct pt_regs regs) 229ptregscall 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 = &regs; 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);