Skip to contentSkip to conversation

rmap for ARMV.

PATCH David Woodhouse 2 participants 3 messages Feb 19, 2002

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

ARM was fun because it has a slab cache with 2KiB objects for page tables, rather than allocating them a page at a time - so we couldn't just use page->{mapping,index} for each page as we do on other architectures.

I solve this by allocating a 16-byte structure to go with each page in the pte_cache slab, which holds {mm,index} for each of the two page tables in that page.

This means a second kmem_cache_alloc in the constructor for the pte_cache slab, which I'm a bit dubious about. The only alternative I could see was to allocate/free them individually for each page table in pte_alloc_one() and pte_free_slow(). The only way I'd be able to keep track of them then, though, would be to use page->mapping for the first and page->index as a pointer to the second, and I was even less happy with that than this version.

arch/arm/mm/mm-armv.c +39 -1
@@ -19,6 +19,7 @@
 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/setup.h>
+#include <asm/rmap.h>
 
 #include <asm/mach/map.h>
 
@@ -457,6 +458,7 @@
  * cache implementation.
  */
 kmem_cache_t *pte_cache;
+kmem_cache_t *pte_rmap_cache;
 
 /*
  * The constructor gets called for each object within the cache when the
@@ -467,6 +471,22 @@
 {
 	unsigned long block = (unsigned long)pte;
 
+	if (!(block & 2048)) {
+		/* First object of two in a page - allocate the 
+		   pte_rmap_info to go with them */
+
+		struct page * page = virt_to_page(pte);
+
+		if (flags & SLAB_CTOR_ATOMIC)
+			BUG();
+
+		page->mapping = kmem_cache_alloc(pte_rmap_cache, GFP_KERNEL);
+		if (!page->mapping) {
+			printk(KERN_CRIT "pte_rmap_cache alloc failed. Oops. Slab constructors need to be allowed to fail\n");
+			/* return -ENOMEM; */
+			BUG();
+		}
+	}
 	if (block & 2047)
 		BUG();
 
@@ -475,11 +495,31 @@
 			PTRS_PER_PTE * sizeof(pte_t), 0);
 }
 
+static void pte_cache_dtor(void *pte, kmem_cache_t *cache, unsigned long flags)
+{
+	unsigned long block = (unsigned long)pte;
+
+	if (!(block & 2048)) {
+		/* First object of two in a page - free the 
+		   pte_rmap_info that was associated with them */
+
+		struct page * page = virt_to_page(pte);
+
+		kmem_cache_free(pte_rmap_cache, page->mapping);
+	}
+}
+
 void __init pgtable_cache_init(void)
 {
+	pte_rmap_cache = kmem_cache_create("pte-rmap-cache",
+				2 * sizeof(struct arm_rmap_info), 0, 0,
+				NULL, NULL);
+	if (!pte_rmap_cache)
+		BUG();
+
 	pte_cache = kmem_cache_create("pte-cache",
 				2 * PTRS_PER_PTE * sizeof(pte_t), 0, 0,
-				pte_cache_ctor, NULL);
+				pte_cache_ctor, pte_cache_dtor);
 	if (!pte_cache)
 		BUG();
 }
include/asm-arm/proc-armv/rmap.h +72 -0

72 lines not on this page · raw message

include/asm-arm/rmap.h +6 -0
diff -uNr --exclude *.o --exclude *.o.flags --exclude *.a --exclude *.a.flags --exclude *~ --exclude .version --exclude compile.h linux-clean/include/asm-arm/rmap.h linux/include/asm-arm/rmap.h
@@ -0,0 +1,6 @@
+#ifndef _ARM_RMAP_H
+#define _ARM_RMAP_H
+
+#include <asm/proc/rmap.h>
+
+#endif /* _ARM_RMAP_H */

--
dwmw2

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/

#1 lore raw
Quoted 3 lines · David Woodhouse

ARM was fun because it has a slab cache with 2KiB objects for page tables, rather than allocating them a page at a time - so we couldn't just use page->{mapping,index} for each page as we do on other architectures.

When rmap gets merged into the 2.5 kernel series, I'll look at what can be done to sort out the pte situation - we could re-jig the page tables so a 'pgd' is 8 bytes per entry (made up of two hardware PTE pointers), the second level page tables end up being 2K hardware + 2K for Linux, which nicely maps to a page per PTE as viewed by Linux.

This should simplify this patch, as well as getting rid of the pte slab.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/

#2 lore raw
Quoted 5 lines · [email protected] said:

When rmap gets merged into the 2.5 kernel series, I'll look at what
can be done to sort out the pte situation - we could re-jig the page tables so a 'pgd' is 8 bytes per entry (made up of two hardware PTE pointers), the second level page tables end up being 2K hardware + 2K for Linux, which nicely maps to a page per PTE as viewed by Linux.

That would probably make sense - I didn't really want to do something that intrusive myself. In the meantime, this is also required:

linux-2.4.17-arm-rmap.patch +2 -1
@@ -39,7 +39,7 @@
  	if (block & 2047)
  		BUG();
  
-@@ -475,11 +495,31 @@
+@@ -475,11 +495,32 @@
  			PTRS_PER_PTE * sizeof(pte_t), 0);
  }
  
@@ -54,6 +54,7 @@
 +		struct page * page = virt_to_page(pte);
 +
 +		kmem_cache_free(pte_rmap_cache, page->mapping);
++		page->mapping = NULL;
 +	}
 +}
 +

--
dwmw2

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/