From: David Woodhouse <dwmw2@infradead.org>
To: riel@conectiva.com.br, linux-mm@kvack.org
Cc: linux-arm-kernel@lists.arm.linux.org.uk
Subject: rmap for ARMV.
Date: Tue, 19 Feb 2002 16:01:34 +0000 [thread overview]
Message-ID: <22292.1014134494@redhat.com> (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.
--- linux-clean/arch/arm/mm/mm-armv.c Wed Jun 27 22:12:04 2001
+++ linux/arch/arm/mm/mm-armv.c Tue Feb 19 11:37:31 2002
@@ -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();
}
diff -uNr --exclude *.o --exclude *.o.flags --exclude *.a --exclude *.a.flags --exclude *~ --exclude .version --exclude compile.h linux-clean/include/asm-arm/proc-armv/rmap.h linux/include/asm-arm/proc-armv/rmap.h
--- linux-clean/include/asm-arm/proc-armv/rmap.h Thu Jan 1 01:00:00 1970
+++ linux/include/asm-arm/proc-armv/rmap.h Tue Feb 19 11:38:42 2002
@@ -0,0 +1,72 @@
+#ifndef _ARMV_RMAP_H
+#define _ARMV_RMAP_H
+/*
+ * linux/include/asm-arm/proc-armv/rmap.h
+ *
+ * Architecture dependant parts of the reverse mapping code,
+ *
+ * We use the struct page of the page table page to find a pointer
+ * to an array of two 'struct arm_rmap_info's, one for each of the
+ * two page tables in each page.
+ *
+ * - rmi->mm points to the process' mm_struct
+ * - rmi->index has the high bits of the address
+ * - the lower bits of the address are calculated from the
+ * offset of the page table entry within the page table page
+ */
+#include <linux/mm.h>
+
+struct arm_rmap_info {
+ struct mm_struct *mm;
+ unsigned long index;
+};
+
+static inline void pgtable_add_rmap(pte_t * ptep, struct mm_struct * mm, unsigned long address)
+{
+ struct page * page = virt_to_page(ptep);
+ struct arm_rmap_info *rmi = (void *)page->mapping;
+
+ if (((unsigned long)ptep)&2048)
+ rmi++;
+
+ rmi->mm = mm;
+ rmi->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1);
+}
+
+static inline void pgtable_remove_rmap(pte_t * ptep)
+{
+ struct page * page = virt_to_page(ptep);
+ struct arm_rmap_info *rmi = (void *)page->mapping;
+
+ if (((unsigned long)ptep)&2048)
+ rmi++;
+
+ rmi->mm = NULL;
+ rmi->index = 0;
+}
+
+static inline struct mm_struct * ptep_to_mm(pte_t * ptep)
+{
+ struct page * page = virt_to_page(ptep);
+ struct arm_rmap_info *rmi = (void *)page->mapping;
+
+ if (((unsigned long)ptep)&2048)
+ rmi++;
+
+ return rmi->mm;
+}
+
+static inline unsigned long ptep_to_address(pte_t * ptep)
+{
+ struct page * page = virt_to_page(ptep);
+ struct arm_rmap_info *rmi = (void *)page->mapping;
+ unsigned long low_bits;
+
+ if (((unsigned long)ptep)&2048)
+ rmi++;
+
+ low_bits = ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
+ return rmi->index + low_bits;
+}
+
+#endif /* _ARMV_RMAP_H */
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
--- linux-clean/include/asm-arm/rmap.h Thu Jan 1 01:00:00 1970
+++ linux/include/asm-arm/rmap.h Tue Feb 19 11:29:45 2002
@@ -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 majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/
next reply other threads:[~2002-02-19 16:01 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-02-19 16:01 David Woodhouse [this message]
2002-02-19 16:14 ` Russell King - ARM Linux
2002-02-19 16:42 ` David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=22292.1014134494@redhat.com \
--to=dwmw2@infradead.org \
--cc=linux-arm-kernel@lists.arm.linux.org.uk \
--cc=linux-mm@kvack.org \
--cc=riel@conectiva.com.br \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox