mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
[PATCH] x86: compress the stack layout of do_page_fault()
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.) argument bugfix from "Guillaume C." <guichaz@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
7e06066b87
commit
869f96a00e
1 changed files with 17 additions and 14 deletions
|
@ -199,6 +199,18 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static noinline 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);
|
||||
|
||||
/*
|
||||
|
@ -218,8 +230,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
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));
|
||||
|
@ -233,7 +244,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
|
||||
tsk = current;
|
||||
|
||||
info.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
|
@ -313,7 +324,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
* 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 */
|
||||
|
@ -387,11 +398,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
/* 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 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
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:
|
||||
|
|
Loading…
Reference in a new issue