linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
@ 2007-08-23 21:07 akpm, Andrew Morton
  2007-08-27 20:13 ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: akpm, Andrew Morton @ 2007-08-23 21:07 UTC (permalink / raw)
  To: linux-mm; +Cc: akpm, thomas.jarosch

See http://bugzilla.kernel.org/show_bug.cgi?id=8928

I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
from interrupt context.

We could fix this in several places, but I do think we want to keep the sanity
checks in kmap_atomic() even for non-highmem pages, so that people who are
testing new code on non-highmem machines get their bugs detected earlier.

Cc: Thomas Jarosch <thomas.jarosch@intra2net.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 mm/page_alloc.c |   26 +++++++++++++++++++-------
 1 files changed, 19 insertions(+), 7 deletions(-)

diff -puN mm/page_alloc.c~alloc_pages-permit-get_zeroed_pagegfp_atomic-from-interrupt-context mm/page_alloc.c
--- a/mm/page_alloc.c~alloc_pages-permit-get_zeroed_pagegfp_atomic-from-interrupt-context
+++ a/mm/page_alloc.c
@@ -284,13 +284,25 @@ static inline void prep_zero_page(struct
 	int i;
 
 	VM_BUG_ON((gfp_flags & (__GFP_WAIT | __GFP_HIGHMEM)) == __GFP_HIGHMEM);
-	/*
-	 * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
-	 * and __GFP_HIGHMEM from hard or soft interrupt context.
-	 */
-	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
-	for (i = 0; i < (1 << order); i++)
-		clear_highpage(page + i);
+	if (gfp_flags & __GFP_HIGHMEM) {
+		/*
+		 * clear_highpage() will use KM_USER0, so it's a bug to use
+		 * __GFP_ZERO and __GFP_HIGHMEM from hard or soft interrupt
+		 * context.
+		 */
+		VM_BUG_ON(in_interrupt());
+		for (i = 0; i < (1 << order); i++)
+			clear_highpage(page + i);
+	} else {
+		/*
+		 * Go direct to clear_page(), because the caller might be
+		 * performing a non-highmem GFP_ZERO allocation from interrupt
+		 * context.  kmap_atomic() will go BUG when that happens, but it
+		 * is a legitimate thing to do
+		 */
+		for (i = 0; i < (1 << order); i++)
+			clear_page(page + i);
+	}
 }
 
 /*
_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-23 21:07 [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context akpm, Andrew Morton
@ 2007-08-27 20:13 ` Christoph Lameter
  2007-08-27 20:33   ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 20:13 UTC (permalink / raw)
  To: akpm; +Cc: linux-mm, thomas.jarosch

On Thu, 23 Aug 2007, akpm@linux-foundation.org wrote:

> See http://bugzilla.kernel.org/show_bug.cgi?id=8928
> 
> I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
> from interrupt context.

AFAIK this works now. GFP_ATOMIC does not set __GFP_HIGHMEM and thus the 
check

	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());

does not trigger

Any use of get_zeroed_page(  | __GFP_HIGHMEM) will cause a bug in

fastcall unsigned long get_zeroed_page(gfp_t gfp_mask)
{
        struct page * page;

        /*
         * get_zeroed_page() returns a 32-bit address, which cannot represent
         * a highmem page
         */
        VM_BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);

        page = alloc_pages(gfp_mask | __GFP_ZERO, 0);
        if (page)
                return (unsigned long) page_address(page);
        return 0;
}


And the patch does not change anything. We currently BUG_ON(GFP_HIGHMEM && 
in_interrupt) and after this patch we will still BUG(). The check was 
reordered but checks the same things. We could clear __GFP_HIGHMEM in 
__alloc_pages() if we are in an interrupt?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 20:13 ` Christoph Lameter
@ 2007-08-27 20:33   ` Andrew Morton
  2007-08-27 21:00     ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 20:33 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, thomas.jarosch

On Mon, 27 Aug 2007 13:13:16 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Thu, 23 Aug 2007, akpm@linux-foundation.org wrote:
> 
> > See http://bugzilla.kernel.org/show_bug.cgi?id=8928
> > 
> > I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
> > from interrupt context.
> 
> AFAIK this works now. GFP_ATOMIC does not set __GFP_HIGHMEM and thus the 
> check
> 
> 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> 
> does not trigger

The crash happens in

	clear_highpage
	->kmap_atomic
	  ->kmap_atomic_prot
	    ->BUG_ON(!pte_none(*(kmap_pte-idx)));

ie: this CPU held a kmap slot when the interrupt happened.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 20:33   ` Andrew Morton
@ 2007-08-27 21:00     ` Christoph Lameter
  2007-08-27 21:04       ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 21:00 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> > > I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
> > > from interrupt context.
> > 
> > AFAIK this works now. GFP_ATOMIC does not set __GFP_HIGHMEM and thus the 
> > check
> > 
> > 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> > 
> > does not trigger
> 
> The crash happens in
> 
> 	clear_highpage
> 	->kmap_atomic
> 	  ->kmap_atomic_prot
> 	    ->BUG_ON(!pte_none(*(kmap_pte-idx)));
> 
> ie: this CPU held a kmap slot when the interrupt happened.

I guess I do not get what the problem is then. AFAIK: You cannot get there 
if you do a get_zeroed_page(GFP_ATOMIC). We should have bugged in 
get_zeroed_page() before we even got to clear_highpage.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:00     ` Christoph Lameter
@ 2007-08-27 21:04       ` Andrew Morton
  2007-08-27 21:20         ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 21:04 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, thomas.jarosch

On Mon, 27 Aug 2007 14:00:04 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
> 
> > > > I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
> > > > from interrupt context.
> > > 
> > > AFAIK this works now. GFP_ATOMIC does not set __GFP_HIGHMEM and thus the 
> > > check
> > > 
> > > 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> > > 
> > > does not trigger
> > 
> > The crash happens in
> > 
> > 	clear_highpage
> > 	->kmap_atomic
> > 	  ->kmap_atomic_prot
> > 	    ->BUG_ON(!pte_none(*(kmap_pte-idx)));
> > 
> > ie: this CPU held a kmap slot when the interrupt happened.
> 
> I guess I do not get what the problem is then. AFAIK: You cannot get there 
> if you do a get_zeroed_page(GFP_ATOMIC). We should have bugged in 
> get_zeroed_page() before we even got to clear_highpage.
> 

: static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
: {
: 	int i;
: 
: 	VM_BUG_ON((gfp_flags & (__GFP_WAIT | __GFP_HIGHMEM)) == __GFP_HIGHMEM);

__GFP_HIGHMEM is not set.

: 	/*
: 	 * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
: 	 * and __GFP_HIGHMEM from hard or soft interrupt context.
: 	 */
: 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());

__GFP_HIGHMEM is not set

: 	for (i = 0; i < (1 << order); i++)
: 		clear_highpage(page + i);

kmap_atomic() goes boom.

: }


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:04       ` Andrew Morton
@ 2007-08-27 21:20         ` Christoph Lameter
  2007-08-27 21:32           ` Christoph Lameter
  2007-08-27 21:34           ` Andrew Morton
  0 siblings, 2 replies; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 21:20 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> __GFP_HIGHMEM is not set.
> 
> : 	/*
> : 	 * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
> : 	 * and __GFP_HIGHMEM from hard or soft interrupt context.
> : 	 */
> : 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> 
> __GFP_HIGHMEM is not set
> 
> : 	for (i = 0; i < (1 << order); i++)
> : 		clear_highpage(page + i);
> 
> kmap_atomic() goes boom.

So the page is not a highmem page. kmap does:

void *kmap(struct page *page)
{
        might_sleep();
        if (!PageHighMem(page))
                return page_address(page);
        return kmap_high(page);
}

-> kmap is fine.

kmap_atomic() does:

void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
{
        enum fixed_addresses idx;
        unsigned long vaddr;

        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();

        idx = type + KM_TYPE_NR*smp_processor_id();
        BUG_ON(!pte_none(*(kmap_pte-idx)));

        if (!PageHighMem(page))
                return page_address(page);

        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        set_pte(kmap_pte-idx, mk_pte(page, prot));
        arch_flush_lazy_mmu_mode();

        return (void*) vaddr;
}

Move the check for highmem to the beginning of the function? Why 
should kmap_atomic fail for a non highmem page?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:20         ` Christoph Lameter
@ 2007-08-27 21:32           ` Christoph Lameter
  2007-08-27 21:34           ` Andrew Morton
  1 sibling, 0 replies; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 21:32 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-mm, thomas.jarosch, Andrew Morton

This issue is a result of commit 656dad312fb41ed95ef08325e9df9bece3aacbbb. 
The intend of moving tests before the check for the highpage was to catch 
some additional errors.

On Mon, 27 Aug 2007, Christoph Lameter wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
> 
> > __GFP_HIGHMEM is not set.
> > 
> > : 	/*
> > : 	 * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
> > : 	 * and __GFP_HIGHMEM from hard or soft interrupt context.
> > : 	 */
> > : 	VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> > 
> > __GFP_HIGHMEM is not set
> > 
> > : 	for (i = 0; i < (1 << order); i++)
> > : 		clear_highpage(page + i);
> > 
> > kmap_atomic() goes boom.
> 
> So the page is not a highmem page. kmap does:
> 
> void *kmap(struct page *page)
> {
>         might_sleep();
>         if (!PageHighMem(page))
>                 return page_address(page);
>         return kmap_high(page);
> }
> 
> -> kmap is fine.
> 
> kmap_atomic() does:
> 
> void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
> {
>         enum fixed_addresses idx;
>         unsigned long vaddr;
> 
>         /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
>         pagefault_disable();
> 
>         idx = type + KM_TYPE_NR*smp_processor_id();
>         BUG_ON(!pte_none(*(kmap_pte-idx)));
> 
>         if (!PageHighMem(page))
>                 return page_address(page);
> 
>         vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
>         set_pte(kmap_pte-idx, mk_pte(page, prot));
>         arch_flush_lazy_mmu_mode();
> 
>         return (void*) vaddr;
> }
> 
> Move the check for highmem to the beginning of the function? Why 
> should kmap_atomic fail for a non highmem page?
> 
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:20         ` Christoph Lameter
  2007-08-27 21:32           ` Christoph Lameter
@ 2007-08-27 21:34           ` Andrew Morton
  2007-08-27 21:43             ` Christoph Lameter
  1 sibling, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 21:34 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, thomas.jarosch

On Mon, 27 Aug 2007 14:20:57 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> kmap_atomic() does:
> 
> void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
> {
>         enum fixed_addresses idx;
>         unsigned long vaddr;
> 
>         /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
>         pagefault_disable();
> 
>         idx = type + KM_TYPE_NR*smp_processor_id();
>         BUG_ON(!pte_none(*(kmap_pte-idx)));
> 
>         if (!PageHighMem(page))
>                 return page_address(page);
> 
>         vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
>         set_pte(kmap_pte-idx, mk_pte(page, prot));
>         arch_flush_lazy_mmu_mode();
> 
>         return (void*) vaddr;
> }
> 
> Move the check for highmem to the beginning of the function? Why 
> should kmap_atomic fail for a non highmem page?

For test coverage, mainly.  If someone is testing highmem-enabled code on
a 512MB machine, we want them to get told about any highmem-handling bugs,
even though they don't have highmem.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:34           ` Andrew Morton
@ 2007-08-27 21:43             ` Christoph Lameter
  2007-08-27 22:11               ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 21:43 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> > Move the check for highmem to the beginning of the function? Why 
> > should kmap_atomic fail for a non highmem page?
> 
> For test coverage, mainly.  If someone is testing highmem-enabled code on
> a 512MB machine, we want them to get told about any highmem-handling bugs,
> even though they don't have highmem.

But the test is for nested kmap_atomics. Nesting (at least allocate a 
regular page while highmem page is being mapped) needs to work in order to 
be able to allocate a page from an interrupt contexts.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 21:43             ` Christoph Lameter
@ 2007-08-27 22:11               ` Andrew Morton
  2007-08-27 22:12                 ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 22:11 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007 14:43:46 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
> 
> > > Move the check for highmem to the beginning of the function? Why 
> > > should kmap_atomic fail for a non highmem page?
> > 
> > For test coverage, mainly.  If someone is testing highmem-enabled code on
> > a 512MB machine, we want them to get told about any highmem-handling bugs,
> > even though they don't have highmem.
> 
> But the test is for nested kmap_atomics.

Sure.  If process-context code uses KM_USER0 and then an interrupt occurs
and interrupt-level code uses KM_USER0, Ingo's test will go boom.

> Nesting (at least allocate a 
> regular page while highmem page is being mapped) needs to work in order to 
> be able to allocate a page from an interrupt contexts.

yup, but interrupt-level code should use the reserved-for-interrupt kmap
slots (KM_IRQ0, etc).

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 22:11               ` Andrew Morton
@ 2007-08-27 22:12                 ` Christoph Lameter
  2007-08-27 22:45                   ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 22:12 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> > Nesting (at least allocate a 
> > regular page while highmem page is being mapped) needs to work in order to 
> > be able to allocate a page from an interrupt contexts.
> 
> yup, but interrupt-level code should use the reserved-for-interrupt kmap
> slots (KM_IRQ0, etc).

We are not using any kmap slot since we are allocating a non highmem page!

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 22:12                 ` Christoph Lameter
@ 2007-08-27 22:45                   ` Andrew Morton
  2007-08-27 23:01                     ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 22:45 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007 15:12:58 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
> 
> > > Nesting (at least allocate a 
> > > regular page while highmem page is being mapped) needs to work in order to 
> > > be able to allocate a page from an interrupt contexts.
> > 
> > yup, but interrupt-level code should use the reserved-for-interrupt kmap
> > slots (KM_IRQ0, etc).
> 
> We are not using any kmap slot since we are allocating a non highmem page!

Right.  So a get_zeroed_page() from IRQ context happens to be not buggy,
even though it goes BUG.

So what do we do?

a) don't call clear_highpage() for non-highmem pages (my fix)

b) don't do the is-the-pte-zero check in kmap_atomic_prot() if the page
   isn't highmem

   This is bad because it'll disable the check completely if the machine
   doesn't physically have highmem, or if the page happened to be a lowmem
   one.

c) don't do the is-the-pte-zero check if __GFP_HIGHMEM wasn't set.

   OK, but we don't pass the gfp_t into kmap_atomic.  So we need to do
   this at the caller site.  That's what a) does.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 22:45                   ` Andrew Morton
@ 2007-08-27 23:01                     ` Christoph Lameter
  2007-08-27 23:40                       ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 23:01 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> So what do we do?
> 
> a) don't call clear_highpage() for non-highmem pages (my fix)

Then we need to be sure that this is the only case where we call 
clear_highpage() from an interrupt. This solves an i386 arch problem in 
core code. Other arches are not broken like that. See f.e. sparc:

void *kmap_atomic(struct page *page, enum km_type type)
{
        unsigned long idx;
        unsigned long vaddr;

        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);

        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);


> b) don't do the is-the-pte-zero check in kmap_atomic_prot() if the page
>    isn't highmem
> 
>    This is bad because it'll disable the check completely if the machine
>    doesn't physically have highmem, or if the page happened to be a lowmem
>    one.

The check is meaningless if we do not have highmem. kmap_atomic is a 
function to be used in atomic context. I.e. interrupts. Nested by 
definition. It is broken as is since it BUG()s on a legitimate nested 
call.

> c) don't do the is-the-pte-zero check if __GFP_HIGHMEM wasn't set.
> 
>    OK, but we don't pass the gfp_t into kmap_atomic.  So we need to do
>    this at the caller site.  That's what a) does.

Would that not mean leaving kmap_atomic broken on i386? Before Ingo's 
commit things were fine. Revert the commit and there is no need 
to change core code.

What exactly is the point of checking that a kmap_atomic of a non highmem 
page cannot occur during the kmap_atomic of a highmem page? AFAICT this is 
fine.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 23:01                     ` Christoph Lameter
@ 2007-08-27 23:40                       ` Andrew Morton
  2007-08-27 23:48                         ` Christoph Lameter
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2007-08-27 23:40 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007 16:01:28 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
> 
> > So what do we do?
> > 
> > a) don't call clear_highpage() for non-highmem pages (my fix)
> 
> Then we need to be sure that this is the only case where we call 
> clear_highpage() from an interrupt. This solves an i386 arch problem in 
> core code. Other arches are not broken like that. See f.e. sparc:
> 
> void *kmap_atomic(struct page *page, enum km_type type)
> {
>         unsigned long idx;
>         unsigned long vaddr;
> 
>         /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
>         pagefault_disable();
>         if (!PageHighMem(page))
>                 return page_address(page);
> 
>         idx = type + KM_TYPE_NR*smp_processor_id();
>         vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
> 
> 
> > b) don't do the is-the-pte-zero check in kmap_atomic_prot() if the page
> >    isn't highmem
> > 
> >    This is bad because it'll disable the check completely if the machine
> >    doesn't physically have highmem, or if the page happened to be a lowmem
> >    one.
> 
> The check is meaningless if we do not have highmem.

umm, yeah, it'll never trigger on a non-highmem machine.

> kmap_atomic is a 
> function to be used in atomic context. I.e. interrupts. Nested by 
> definition. It is broken as is since it BUG()s on a legitimate nested 
> call.

Is it broken?  Dunno.  It's a bit silly to run kmap_atomic() against a page
which the caller *knows* cannot be a highmem page.

The only situation where this is likely to occur is where the caller
received a gfp_t from higher up, like this case.

> > c) don't do the is-the-pte-zero check if __GFP_HIGHMEM wasn't set.
> > 
> >    OK, but we don't pass the gfp_t into kmap_atomic.  So we need to do
> >    this at the caller site.  That's what a) does.
> 
> Would that not mean leaving kmap_atomic broken on i386? Before Ingo's 
> commit things were fine. Revert the commit and there is no need 
> to change core code.

If we revert the commit we lose a bit of debug support.

We could move the assert to after we've checked for PageHighmem, but then
we'd fail to detect a bug if the nested caller happened to get a lowmem
page for a __GFP_HIGHMEM allocation.

> What exactly is the point of checking that a kmap_atomic of a non highmem 
> page cannot occur during the kmap_atomic of a highmem page? AFAICT this is 
> fine.

Just that the non-highmem page _might_ have been a highmem page, only the
caller got lucky.

I dunno, it's all a bit marginal, and tricky.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context
  2007-08-27 23:40                       ` Andrew Morton
@ 2007-08-27 23:48                         ` Christoph Lameter
  0 siblings, 0 replies; 15+ messages in thread
From: Christoph Lameter @ 2007-08-27 23:48 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, Ingo Molnar, thomas.jarosch

On Mon, 27 Aug 2007, Andrew Morton wrote:

> > kmap_atomic is a 
> > function to be used in atomic context. I.e. interrupts. Nested by 
> > definition. It is broken as is since it BUG()s on a legitimate nested 
> > call.
> 
> Is it broken?  Dunno.  It's a bit silly to run kmap_atomic() against a page
> which the caller *knows* cannot be a highmem page.

So far we allow running kmap_atomic against a non-highmem page and 
kmap_atomic contains code to deal with that case.

> > Would that not mean leaving kmap_atomic broken on i386? Before Ingo's 
> > commit things were fine. Revert the commit and there is no need 
> > to change core code.
> 
> If we revert the commit we lose a bit of debug support.
> 
> We could move the assert to after we've checked for PageHighmem, but then
> we'd fail to detect a bug if the nested caller happened to get a lowmem
> page for a __GFP_HIGHMEM allocation.

We will ultimately detect it if he gets that type of page. Like many 
other checks in the code it may only trigger sometimes. Reverting 
656dad312fb41ed95ef08325e9df9bece3aacbbb will get us to a known good 
situation that also triggers the bug.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2007-08-27 23:48 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-23 21:07 [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context akpm, Andrew Morton
2007-08-27 20:13 ` Christoph Lameter
2007-08-27 20:33   ` Andrew Morton
2007-08-27 21:00     ` Christoph Lameter
2007-08-27 21:04       ` Andrew Morton
2007-08-27 21:20         ` Christoph Lameter
2007-08-27 21:32           ` Christoph Lameter
2007-08-27 21:34           ` Andrew Morton
2007-08-27 21:43             ` Christoph Lameter
2007-08-27 22:11               ` Andrew Morton
2007-08-27 22:12                 ` Christoph Lameter
2007-08-27 22:45                   ` Andrew Morton
2007-08-27 23:01                     ` Christoph Lameter
2007-08-27 23:40                       ` Andrew Morton
2007-08-27 23:48                         ` Christoph Lameter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox