[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-arm-kernel
Subject:    Re: On TLB flushing
From:       Russell King - ARM Linux <linux () arm ! linux ! org ! uk>
Date:       2004-04-16 18:04:23
Message-ID: 20040416190423.M29891 () flint ! arm ! linux ! org ! uk
[Download RAW message or body]

On Fri, Apr 16, 2004 at 10:37:05AM -0700, Marc Singer wrote:
> On Fri, Apr 16, 2004 at 05:51:09PM +0100, Russell King - ARM Linux wrote:
> > > Let me understand this.  
> > > 
> > > The kernel has knowingly removed the PTE without flushing the TLB.
> > 
> > No.  You're looking at it from too low a level.  Take a moment to stand
> > back and look at what's happening from a higher level.
> 
> Thanks a lot for your comments.  It's difficult to see how this works
> without explanation.
> 
> Now, I think I know more about what's going on.  I'd have liked to
> come to you with a solution, but I'm not sure where to look.
> 
> It turns out that try_to_unmap_one () is correctly calling the TLB
> flush function...with the wrong virtual address.  The trouble is, I
> don't know how this address should be formed.
> 
> The call ptep_to_address () looks into the node data and composes an
> address.  
> 
>     unmap: breakin ptep c0341820 address 00104000
>     kmap_atomic_to_page c0235228
>     low_bits 00104000
>     page->index 00000000
> 
> The address value needs to be 0x00008000 for a correct cache and TLB
> flush.  I know this is a big question: how is this supposed to work?

The answer is it obviously doesn't; the calculation of low_bits is
most definitely wrong - PTRS_PER_PTE is not the right definition to
describe the ratio of bytes in a page to PTE entries.

Working from your data above, this means ptep was 0x820.  Using the
new calculation below, PTRS_PER_PTE is 512, and sizeof(pte_t) is 4.
This gives (0x820 & 0x7ff) * 0x400 which gives: 0x8000 - the right
answer!

This bug will affect _all_ ARM platforms, so it should be reproducable
here...

Could you try this patch?

Index: pgcl-2.6.5-mm6/include/asm-generic/rmap.h
===================================================================
--- pgcl-2.6.5-mm6.orig/include/asm-generic/rmap.h	2004-04-03 19:37:24.000000000 -0800
+++ pgcl-2.6.5-mm6/include/asm-generic/rmap.h	2004-04-16 10:57:07.000000000 -0700
@@ -57,7 +57,8 @@
 {
 	struct page * page = kmap_atomic_to_page(ptep);
 	unsigned long low_bits;
-	low_bits = ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
+	low_bits = ((unsigned long)ptep & (PTRS_PER_PTE*sizeof(pte_t) - 1))
+			* (PAGE_SIZE/sizeof(pte_t));
 	return page->index + low_bits;
 }
 


-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:       http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic