"Paolo 'Blaisorblade' Giarrusso" <[EMAIL PROTECTED]> wrote:
>
> From: Paolo 'Blaisorblade' Giarrusso <[EMAIL PROTECTED]>
> 
> Following i386, we should maybe refuse trying to fault in pages when we're
> doing atomic operations, because to handle the fault we could need to take
> already taken spinlocks.
> 
> Also, if we're doing an atomic operation (in the sense of in_atomic()) we're
> surely in kernel mode and we're surely going to handle adequately the failed
> fault, so it's safe to behave this way.
> 
> Currently, on UML SMP is rarely used, and we don't support PREEMPT, so this is
> unlikely to create problems right now, but it might in the future.
> 

That's not really an accurate explanation/understanding of what's going on
in there.

There's an extremely special-case in the pagefault handlers where we fail
the fault if in_atomic().  It's unrelated to spinlocks (spinlocks don't
even cause in_atomic() to become true if !CONFIG_PREEMPT).

It has to do with kmap_atomic().  There's tricksy code in mm/filemap.c
which will fault the target page in by hand and will then take an atomic
kmap and will then raise current->preempt_count by hand, so in_atomic()
becomes true even if !COFNIG_PREEMPT.

So at this stage we expect to be able to do a copy_to/from_user to/from
pagecache without taking a fault, because we just faulted the page in by
hand.  And we're not allowed to take a fault, because we're holding an
atomic kmap.  But if we _do_ take a fault (extreme memory pressure, racing
munmap, etc) then we want to fail the pagefault immediately.

The in_atomic() test in x86's do_page_fault() is in fact a message passed
into it from filemap.c's kmap_atomic().  It has accidental side-effects,
such as making copy_to_user() fail if inside spinlocks when
CONFIG_PREEMPT=y.


So I think this change is only needed if UML implements kmap_atomic, as in
arch/i386/mm/highmem.c, which it surely does not do?


> 
> diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
> --- a/arch/um/kernel/trap_kern.c
> +++ b/arch/um/kernel/trap_kern.c
> @@ -40,6 +40,12 @@ int handle_page_fault(unsigned long addr
>       int err = -EFAULT;
>  
>       *code_out = SEGV_MAPERR;
> +
> +     /* If the fault was during atomic operation, don't take the fault, just
> +      * fail. */
> +     if (in_atomic())
> +             goto out_nosemaphore;
> +
>       down_read(&mm->mmap_sem);
>       vma = find_vma(mm, address);
>       if(!vma) 
> @@ -90,6 +96,7 @@ survive:
>       flush_tlb_page(vma, address);
>  out:
>       up_read(&mm->mmap_sem);
> +out_nosemaphore:
>       return(err);
>  
>  /*


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

Reply via email to