On Wed, Jan 02, 2008 at 05:01:02PM -0800, Harvey Harrison wrote:
> Begin to unify do_page_fault(), easy code movement first.
> 
> Signed-off-by: Harvey Harrison <[EMAIL PROTECTED]>
> ---
> Ingo, similar to the kprobes unification patches I did, it gets a bit
> uglier before it gets better ;-)
> 
>  arch/x86/mm/fault_32.c |   38 +++++++++++++++++++++++++++++---------
>  arch/x86/mm/fault_64.c |   23 ++++++++++++++++++-----
>  2 files changed, 47 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
> index b1893eb..051a4ec 100644
> --- a/arch/x86/mm/fault_32.c
> +++ b/arch/x86/mm/fault_32.c
> @@ -375,19 +375,26 @@ void __kprobes do_page_fault(struct pt_regs *regs, 
> unsigned long error_code)
>       struct mm_struct *mm;
>       struct vm_area_struct *vma;
>       unsigned long address;
> -     int write, si_code;
> -     int fault;
> +     int write, fault;
> +#ifdef CONFIG_x86_64

There is no such thing as CONFIG_x86_64 .

Do you seriously think code is getting better and more readable because
of this liberal #ifdef sprinkling in every possible direction?

> +     unsigned long flags;
> +#endif

One.

> +     int si_code;
>  
>       /*
>        * We can fault from pretty much anywhere, with unknown IRQ state.
>        */
>       trace_hardirqs_fixup();
>  
> -     /* get the address */
> -     address = read_cr2();
> -
>       tsk = current;
> +     mm = tsk->mm;
>  
> +#ifdef CONFIG_x86_64
> +     prefetchw(&mm->mmap_sem);
> +#endif

Two.

> +
> +     /* get the address */
> +     address = read_cr2();
>       si_code = SEGV_MAPERR;
>  
>       /*
> @@ -403,9 +410,24 @@ void __kprobes do_page_fault(struct pt_regs *regs, 
> unsigned long error_code)
>        * (error_code & 4) == 0, and that the fault was not a
>        * protection error (error_code & 9) == 0.
>        */
> +#ifdef CONFIG_X86_32
>       if (unlikely(address >= TASK_SIZE)) {
> -             if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
> +             if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
> +                 vmalloc_fault(address) >= 0)
>                       return;
> +#else
> +     if (unlikely(address >= TASK_SIZE64)) {
> +             /*
> +              * Don't check for the module range here: its PML4
> +              * is always initialized because it's shared with the main
> +              * kernel text. Only vmalloc may need PML4 syncups.
> +              */
> +             if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
> +                   ((address >= VMALLOC_START && address < VMALLOC_END))) {
> +                     if (vmalloc_fault(address) >= 0)
> +                             return;
> +             }
> +#endif

Three.

>               if (notify_page_fault(regs))
>                       return;
>               /*
> @@ -423,8 +445,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, 
> unsigned long error_code)
>       if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
>               local_irq_enable();
>  
> -     mm = tsk->mm;
> -
>       /*
>        * If we're in an interrupt, have no user context or are running in an
>        * atomic region then we must not take the fault.
> @@ -495,7 +515,7 @@ good_area:
>                       goto bad_area;
>       }
>  
> - survive:
> +survive:
>       /*
>        * If for any reason at all we couldn't handle the fault,
>        * make sure we exit gracefully rather than endlessly redo
> diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
> index 357a3e0..97b92b6 100644
> --- a/arch/x86/mm/fault_64.c
> +++ b/arch/x86/mm/fault_64.c
> @@ -426,7 +426,9 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>       struct vm_area_struct *vma;
>       unsigned long address;
>       int write, fault;
> +#ifdef CONFIG_x86_64
>       unsigned long flags;
> +#endif

Four.

>       int si_code;
>  
>       /*
> @@ -436,14 +438,15 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>  
>       tsk = current;
>       mm = tsk->mm;
> +
> +#ifdef CONFIG_x86_64
>       prefetchw(&mm->mmap_sem);
> +#endif

Five.

>  
>       /* get the address */
>       address = read_cr2();
> -
>       si_code = SEGV_MAPERR;
>  
> -
>       /*
>        * We fault-in kernel-space virtual memory on-demand. The
>        * 'reference' page table is init_mm.pgd.
> @@ -457,6 +460,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>        * (error_code & 4) == 0, and that the fault was not a
>        * protection error (error_code & 9) == 0.
>        */
> +#ifdef CONFIG_X86_32
> +     if (unlikely(address >= TASK_SIZE)) {
> +             if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
> +                 vmalloc_fault(address) >= 0)
> +                     return;
> +#else
>       if (unlikely(address >= TASK_SIZE64)) {
>               /*
>                * Don't check for the module range here: its PML4
> @@ -468,6 +477,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>                       if (vmalloc_fault(address) >= 0)
>                               return;
>               }
> +#endif

Six.

>               if (notify_page_fault(regs))
>                       return;
>               /*
> @@ -500,7 +510,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>       if (user_mode_vm(regs))
>               error_code |= PF_USER;
>  
> - again:
> +again:
>       /* When running in the kernel we expect faults to occur only to
>        * addresses in user space.  All other faults represent errors in the
>        * kernel and should generate an OOPS.  Unfortunately, in the case of an
> @@ -531,8 +541,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs 
> *regs,
>       if (!(vma->vm_flags & VM_GROWSDOWN))
>               goto bad_area;
>       if (error_code & PF_USER) {
> -             /* Allow userspace just enough access below the stack pointer
> -              * to let the 'enter' instruction work.
> +             /*
> +              * Accessing the stack below %sp is always a bug.
> +              * The large cushion allows instructions like enter
> +              * and pusha to work.  ("enter $65535,$31" pushes
> +              * 32 pointers and then decrements %sp by 65535.)
>                */
>               if (address + 65536 + 32 * sizeof(unsigned long) < regs->sp)
>                       goto bad_area;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to