Re: [patch] compress the stack layout of do_page_fault(), x86

From: Ingo Molnar
Date: Sat Jul 09 2005 - 10:32:46 EST



Guillaume noticed a bug in the patch, si_signo should be used instead of
SIGSEGV. (doh) New patch below.

Ingo

-----

this patch pushes the creation of a rare signal frame (SIGBUS or
SIGSEGV) into a separate function, thus saving stackspace in the main
do_page_fault() stackframe. The effect is 132 bytes less of stack used
by the typical do_page_fault() invocation - resulting in a denser
cache-layout.

(another minor effect is that in case of kernel crashes that come from a
pagefault, we add less space to the already existing frame, giving the
crash functions a slightly higher chance to do their stuff without
overflowing the stack.)

(the changes also result in slightly cleaner code.)

build and boot tested.

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>

argument bugfix from "Guillaume C." <guichaz@xxxxxxxxx>

Index: linux/arch/i386/mm/fault.c
===================================================================
--- linux.orig/arch/i386/mm/fault.c
+++ linux/arch/i386/mm/fault.c
@@ -201,6 +201,18 @@ static inline int is_prefetch(struct pt_
return 0;
}

+static void force_sig_info_fault(int si_signo, int si_code,
+ unsigned long address, struct task_struct *tsk)
+{
+ siginfo_t info;
+
+ info.si_signo = si_signo;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void __user *)address;
+ force_sig_info(si_signo, &info, tsk);
+}
+
fastcall void do_invalid_op(struct pt_regs *, unsigned long);

/*
@@ -220,9 +232,8 @@ fastcall notrace void do_page_fault(stru
struct vm_area_struct * vma;
unsigned long address;
unsigned long page;
- int write;
- siginfo_t info;
-
+ int write, si_code;
+
/* get the address */
__asm__("movl %%cr2,%0":"=r" (address));
trace_special(regs->eip, error_code, address);
@@ -236,7 +247,7 @@ fastcall notrace void do_page_fault(stru

tsk = current;

- info.si_code = SEGV_MAPERR;
+ si_code = SEGV_MAPERR;

/*
* We fault-in kernel-space virtual memory on-demand. The
@@ -316,7 +327,7 @@ fastcall notrace void do_page_fault(stru
* we can handle it..
*/
good_area:
- info.si_code = SEGV_ACCERR;
+ si_code = SEGV_ACCERR;
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
@@ -390,11 +401,7 @@ bad_area_nosemaphore:
/* Kernel addresses are always protection faults */
tsk->thread.error_code = error_code | (address >= TASK_SIZE);
tsk->thread.trap_no = 14;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- /* info.si_code has been set above */
- info.si_addr = (void __user *)address;
- force_sig_info(SIGSEGV, &info, tsk);
+ force_sig_info_fault(SIGSEGV, si_code, address, tsk);
return;
}

@@ -500,11 +507,7 @@ do_sigbus:
tsk->thread.cr2 = address;
tsk->thread.error_code = error_code;
tsk->thread.trap_no = 14;
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRERR;
- info.si_addr = (void __user *)address;
- force_sig_info(SIGBUS, &info, tsk);
+ force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
return;

vmalloc_fault:
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/