compress the stack layout of do_page_fault(), x86
PATCH 1/1 compress the stack layout of do_page_fault(), x86
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.
Ingo
arch/i386/mm/fault.c +18 -15
@@ -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 =SIGSEGV ; + info.si_errno =0 ; + info.si_code = si_code; + info.si_addr = (void __user *)address; +force_sig_info (SIGSEGV , &info, tsk); +} + fastcall void do_invalid_op(struct pt_regs *, unsigned long);/*
@@ -220,9 +232,8 @@ fastcall notrace void do_page_fault(strustruct 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:
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.
argument bugfix from "Guillaume C." <[email protected]>
arch/i386/mm/fault.c +18 -15
@@ -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(strustruct 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:
On Sat, 9 Jul 2005 17:29:24 +0200 Ingo Molnar wrote:
| | 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.
Hi Ingo-
Just to clarify this, "boot tested" does not mean that this changed code was tested, right?
or do you have a test case that was tested?
Thanks,
---
~Randy
Quoted 2 lines · randy_dunlap
Just to clarify this, "boot tested" does not mean that this changed code was tested, right? or do you have a test case that was tested?
i tested segfaults, but not bus-faults. The bug would have resulted in sigsegv being delivered not a sigbus.
Ingo
Quoted 5 lines · Ingo Molnar
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 typicaldo_page_fault()invocation - resulting in a denser cache-layout.
does the benefit actually show up anywhere?