public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* page table page->index
@ 2002-07-29  5:00 Paul Mackerras
  2002-07-30 12:11 ` Russell King
  0 siblings, 1 reply; 2+ messages in thread
From: Paul Mackerras @ 2002-07-29  5:00 UTC (permalink / raw)
  To: Andrew Morton, torvalds; +Cc: linux-kernel

I found a situation where page->index for a pagetable page can be set
to 0 instead of the correct value.  This means that ptep_to_address
will return the wrong answer.  The problem occurs when remap_pmd_range
calls pte_alloc_map and pte_alloc_map needs to allocate a new pte
page, because remap_pmd_range has masked off the top bits of the
address (to avoid overflow in the computation of `end'), and it passes
the masked address to pte_alloc_map.

Now we presumably don't need to get from the physical pages mapped by
remap_page_range back to the ptes mapping them.  But we could easily
map some normal pages using ptes in that pagetable page subsequently,
and when we call ptep_to_address on their ptes it will give the wrong
answer.

The patch below fixes the problem.

There is a more general question this brings up - some of the
procedures which iterate over ranges of ptes will do the wrong thing
if the end of the address range is too close to ~0UL, while others are
OK.  Is this a problem in practice?  On i386, ppc, and the 64-bit
architectures it isn't since user addresses can't go anywhere near
~0UL, but what about arm or m68k for instance?

And BTW, being able to go from a pte pointer to the mm and virtual
address that that pte maps is an extremely useful thing on ppc, since
it will enable me to do MMU hash-table management at set_pte (and
ptep_*) time and thus avoid the extra traversal of the pagetables that
I am currently doing in flush_tlb_*.  So if you do decide to back out
rmap, please leave in the hooks for setting page->mapping and
page->index on pagetable pages.

Paul.

diff -urN linux-2.5/mm/memory.c pmac-2.5/mm/memory.c
--- linux-2.5/mm/memory.c	Thu Jul 18 05:27:58 2002
+++ pmac-2.5/mm/memory.c	Sat Jul 27 15:42:18 2002
@@ -863,18 +863,19 @@
 static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
 	unsigned long phys_addr, pgprot_t prot)
 {
-	unsigned long end;
+	unsigned long base, end;
 
+	base = address & PGDIR_MASK;
 	address &= ~PGDIR_MASK;
 	end = address + size;
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	phys_addr -= address;
 	do {
-		pte_t * pte = pte_alloc_map(mm, pmd, address);
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
 		if (!pte)
 			return -ENOMEM;
-		remap_pte_range(pte, address, end - address, address + phys_addr, prot);
+		remap_pte_range(pte, base + address, end - address, address + phys_addr, prot);
 		pte_unmap(pte);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;


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

* Re: page table page->index
  2002-07-29  5:00 page table page->index Paul Mackerras
@ 2002-07-30 12:11 ` Russell King
  0 siblings, 0 replies; 2+ messages in thread
From: Russell King @ 2002-07-30 12:11 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Andrew Morton, torvalds, linux-kernel

On Mon, Jul 29, 2002 at 03:00:55PM +1000, Paul Mackerras wrote:
> Is this a problem in practice?  On i386, ppc, and the 64-bit
> architectures it isn't since user addresses can't go anywhere near
> ~0UL, but what about arm or m68k for instance?

Ok, let me provide a description of the virtual address space we have for
Linux on ARM CPUs:

 +----------------------+ <=== 4GB
 | "remapped" stuff [2] |
 +----------------------+ <=== 4GB - 64K
 |  static mapped MMIO  |
 +----------------------+ <=== (sub-architecture defined limit [3])
 |       ioremap,       |
 |       modules,       |
 | pci_alloc_consistent |
 |         heap         |
 +----------------------+
 | kernel direct mapped |
 |     ram & kernel     |
 +----------------------+ <=== (normally 3GB, may be as low as 1GB)
 |                      |
 /         User         /
 /                      /
 |                      |
 +----------------------+ <=== 4K
 |   CPU vectors [1]    |
 +----------------------+ <=== 0K

[1] CPU vectors are fixed at virtual address 0 on many CPUs.  However,
    later CPUs support an alternative virtual address of 4GB-64K

[2] This area is split into two areas; the top 32K is available for
    CPU implementation specific optimisations (eg, remapping pages
    for copy_user_page, clear_user_page).  The lower 32K is for
    alternate CPU vectors, and "generic" ARM kernel use (maybe
    remapping page tables for uncached access.)

[3] This is normally around 3.5GB or 3.75GB.

As far as Linux 2.5 is concerned, a pgd entry maps 2MB (the hardware
PGD maps 1MB, but to make rmap and 2nd level page table stuff simple,
we group two hardware pgd entries together to make one Linux pgd entry.)

So, to answer your question, remap_page_range shouldn't go anywhere
near the top-most PGD entry, so wrap around shouldn't be a problem
on ARM.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


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

end of thread, other threads:[~2002-07-30 12:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-07-29  5:00 page table page->index Paul Mackerras
2002-07-30 12:11 ` Russell King

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