aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/process_32.c
diff options
context:
space:
mode:
authorBrian Gerst <brgerst@gmail.com>2009-02-11 16:43:58 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2009-02-11 17:00:56 -0500
commitb12bdaf11f935d7be030207e3c77faeaeab8ded3 (patch)
treee41f325f01614f7cf2eb78350fbd7440afe39cf8 /arch/x86/kernel/process_32.c
parent1c0040047d5499599cc231ca3f105be3ceff8562 (diff)
x86: use regparm(3) for passed-in pt_regs pointer
Some syscalls need to access the pt_regs structure, either to copy user register state or to modifiy it. This patch adds stubs to load the address of the pt_regs struct into the %eax register, and changes the syscalls to take the pointer as an argument instead of relying on the assumption that the pt_regs structure overlaps the function arguments. Drop the use of regparm(1) due to concern about gcc bugs, and to move in the direction of the eventual removal of regparm(0) for asmlinkage. Signed-off-by: Brian Gerst <brgerst@gmail.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r--arch/x86/kernel/process_32.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 5a9dcfb01f71..fec79ad85dc6 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -603,15 +603,21 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
603 return prev_p; 603 return prev_p;
604} 604}
605 605
606ptregscall int sys_fork(struct pt_regs *regs) 606int 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
611ptregscall int sys_clone(struct pt_regs *regs, unsigned long clone_flags, 611int sys_clone(struct pt_regs *regs)
612 unsigned long newsp, int __user *parent_tidptr,
613 unsigned long unused, int __user *child_tidptr)
614{ 612{
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;
615 if (!newsp) 621 if (!newsp)
616 newsp = regs->sp; 622 newsp = regs->sp;
617 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 623 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
@@ -627,7 +633,7 @@ ptregscall int sys_clone(struct pt_regs *regs, unsigned long clone_flags,
627 * do not have enough call-clobbered registers to hold all 633 * do not have enough call-clobbered registers to hold all
628 * the information you need. 634 * the information you need.
629 */ 635 */
630ptregscall int sys_vfork(struct pt_regs *regs) 636int sys_vfork(struct pt_regs *regs)
631{ 637{
632 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL); 638 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL);
633} 639}
@@ -635,18 +641,19 @@ ptregscall int sys_vfork(struct pt_regs *regs)
635/* 641/*
636 * sys_execve() executes a new program. 642 * sys_execve() executes a new program.
637 */ 643 */
638ptregscall int sys_execve(struct pt_regs *regs, char __user *u_filename, 644int sys_execve(struct pt_regs *regs)
639 char __user * __user *argv,
640 char __user * __user *envp)
641{ 645{
642 int error; 646 int error;
643 char *filename; 647 char *filename;
644 648
645 filename = getname(u_filename); 649 filename = getname((char __user *) regs->bx);
646 error = PTR_ERR(filename); 650 error = PTR_ERR(filename);
647 if (IS_ERR(filename)) 651 if (IS_ERR(filename))
648 goto out; 652 goto out;
649 error = do_execve(filename, argv, envp, regs); 653 error = do_execve(filename,
654 (char __user * __user *) regs->cx,
655 (char __user * __user *) regs->dx,
656 regs);
650 if (error == 0) { 657 if (error == 0) {
651 /* Make sure we don't return using sysenter.. */ 658 /* Make sure we don't return using sysenter.. */
652 set_thread_flag(TIF_IRET); 659 set_thread_flag(TIF_IRET);