* [patch 1/7] mm: introduce VM_MIXEDMAP
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
@ 2008-03-11 10:46 ` npiggin, Jared Hulbert
2008-03-11 10:46 ` [patch 2/7] mm: introduce pte_special pte bit npiggin
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: npiggin, Jared Hulbert @ 2008-03-11 10:46 UTC (permalink / raw)
To: Linus Torvalds
Cc: akpm, Jared Hulbert, Carsten Otte, Martin Schwidefsky,
Heiko Carstens, linux-mm
[-- Attachment #1: vm-mixedmap.patch --]
[-- Type: text/plain, Size: 7101 bytes --]
Introduce a new type of mapping, VM_MIXEDMAP. This is unlike VM_PFNMAP in
that it can support COW mappings of arbitrary ranges including ranges without
struct page *and* ranges with a struct page that we actually want to refcount
(PFNMAP can only support COW in those cases where the un-COW-ed translations
are mapped linearly in the virtual address, and can only support non
refcounted ranges).
VM_MIXEDMAP achieves this by refcounting all pfn_valid pages, and not
refcounting !pfn_valid pages (which is not an option for VM_PFNMAP, because
it needs to avoid refcounting pfn_valid pages eg. for /dev/mem mappings).
Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Carsten Otte <cotte@de.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jared Hulbert <jaredeh@gmail.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-mm@kvack.org
---
include/linux/mm.h | 1
mm/memory.c | 79 ++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 59 insertions(+), 21 deletions(-)
Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h
+++ linux-2.6/include/linux/mm.h
@@ -107,6 +107,7 @@ extern unsigned int kobjsize(const void
#define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */
#define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
+#define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
Index: linux-2.6/mm/memory.c
===================================================================
--- linux-2.6.orig/mm/memory.c
+++ linux-2.6/mm/memory.c
@@ -371,35 +371,65 @@ static inline int is_cow_mapping(unsigne
}
/*
- * This function gets the "struct page" associated with a pte.
+ * This function gets the "struct page" associated with a pte or returns
+ * NULL if no "struct page" is associated with the pte.
*
- * NOTE! Some mappings do not have "struct pages". A raw PFN mapping
- * will have each page table entry just pointing to a raw page frame
- * number, and as far as the VM layer is concerned, those do not have
- * pages associated with them - even if the PFN might point to memory
+ * A raw VM_PFNMAP mapping (ie. one that is not COWed) may not have any "struct
+ * page" backing, and even if they do, they are not refcounted. COWed pages of
+ * a VM_PFNMAP do always have a struct page, and they are normally refcounted
+ * (they are _normal_ pages).
+ *
+ * So a raw PFNMAP mapping will have each page table entry just pointing
+ * to a page frame number, and as far as the VM layer is concerned, those do
+ * not have pages associated with them - even if the PFN might point to memory
* that otherwise is perfectly fine and has a "struct page".
*
- * The way we recognize those mappings is through the rules set up
- * by "remap_pfn_range()": the vma will have the VM_PFNMAP bit set,
- * and the vm_pgoff will point to the first PFN mapped: thus every
+ * The way we recognize COWed pages within VM_PFNMAP mappings is through the
+ * rules set up by "remap_pfn_range()": the vma will have the VM_PFNMAP bit
+ * set, and the vm_pgoff will point to the first PFN mapped: thus every
* page that is a raw mapping will always honor the rule
*
* pfn_of_page == vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT)
*
- * and if that isn't true, the page has been COW'ed (in which case it
- * _does_ have a "struct page" associated with it even if it is in a
- * VM_PFNMAP range).
+ * A call to vm_normal_page() will return NULL for such a page.
+ *
+ * If the page doesn't follow the "remap_pfn_range()" rule in a VM_PFNMAP
+ * then the page has been COW'ed. A COW'ed page _does_ have a "struct page"
+ * associated with it even if it is in a VM_PFNMAP range. Calling
+ * vm_normal_page() on such a page will therefore return the "struct page".
+ *
+ *
+ * VM_MIXEDMAP mappings can likewise contain memory with or without "struct
+ * page" backing, however the difference is that _all_ pages with a struct
+ * page (that is, those where pfn_valid is true) are refcounted and considered
+ * normal pages by the VM. The disadvantage is that pages are refcounted
+ * (which can be slower and simply not an option for some PFNMAP users). The
+ * advantage is that we don't have to follow the strict linearity rule of
+ * PFNMAP mappings in order to support COWable mappings.
+ *
+ * A call to vm_normal_page() with a VM_MIXEDMAP mapping will return the
+ * associated "struct page" or NULL for memory not backed by a "struct page".
+ *
+ *
+ * All other mappings should have a valid struct page, which will be
+ * returned by a call to vm_normal_page().
*/
struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
- if (unlikely(vma->vm_flags & VM_PFNMAP)) {
- unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT;
- if (pfn == vma->vm_pgoff + off)
- return NULL;
- if (!is_cow_mapping(vma->vm_flags))
- return NULL;
+ if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
+ if (vma->vm_flags & VM_MIXEDMAP) {
+ if (!pfn_valid(pfn))
+ return NULL;
+ goto out;
+ } else {
+ unsigned long off = (addr-vma->vm_start) >> PAGE_SHIFT;
+ if (pfn == vma->vm_pgoff + off)
+ return NULL;
+ if (!is_cow_mapping(vma->vm_flags))
+ return NULL;
+ }
}
#ifdef CONFIG_DEBUG_VM
@@ -422,6 +452,7 @@ struct page *vm_normal_page(struct vm_ar
* The PAGE_ZERO() pages and various VDSO mappings can
* cause them to exist.
*/
+out:
return pfn_to_page(pfn);
}
@@ -1233,8 +1264,11 @@ int vm_insert_pfn(struct vm_area_struct
pte_t *pte, entry;
spinlock_t *ptl;
- BUG_ON(!(vma->vm_flags & VM_PFNMAP));
- BUG_ON(is_cow_mapping(vma->vm_flags));
+ BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
+ BUG_ON((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) ==
+ (VM_PFNMAP|VM_MIXEDMAP));
+ BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
+ BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
retval = -ENOMEM;
pte = get_locked_pte(mm, addr, &ptl);
@@ -2380,10 +2414,13 @@ static noinline int do_no_pfn(struct mm_
unsigned long pfn;
pte_unmap(page_table);
- BUG_ON(!(vma->vm_flags & VM_PFNMAP));
- BUG_ON(is_cow_mapping(vma->vm_flags));
+ BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
+ BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
+
+ BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
+
if (unlikely(pfn == NOPFN_OOM))
return VM_FAULT_OOM;
else if (unlikely(pfn == NOPFN_SIGBUS))
--
--
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] 14+ messages in thread* [patch 2/7] mm: introduce pte_special pte bit
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
2008-03-11 10:46 ` [patch 1/7] mm: introduce VM_MIXEDMAP npiggin, Jared Hulbert
@ 2008-03-11 10:46 ` npiggin
2008-03-11 10:46 ` [patch 3/7] mm: add vm_insert_mixed npiggin
` (4 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: npiggin @ 2008-03-11 10:46 UTC (permalink / raw)
To: Linus Torvalds
Cc: akpm, Carsten Otte, Jared Hulbert, Martin Schwidefsky,
Heiko Carstens, linux-arch, linux-mm
[-- Attachment #1: mm-normal-pte-bit.patch --]
[-- Type: text/plain, Size: 33862 bytes --]
s390 for one, cannot implement VM_MIXEDMAP with pfn_valid, due to their
memory model (which is more dynamic than most). Instead, they had proposed
to implement it with an additional path through vm_normal_page(), using a
bit in the pte to determine whether or not the page should be refcounted:
vm_normal_page()
{
...
if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
if (vma->vm_flags & VM_MIXEDMAP) {
#ifdef s390
if (!mixedmap_refcount_pte(pte))
return NULL;
#else
if (!pfn_valid(pfn))
return NULL;
#endif
goto out;
}
...
}
This is fine, however if we are allowed to use a bit in the pte to
determine refcountedness, we can use that to _completely_ replace all the
vma based schemes. So instead of adding more cases to the already complex
vma-based scheme, we can have a clearly seperate and simple pte-based scheme
(and get slightly better code generation in the process):
vm_normal_page()
{
#ifdef s390
if (!mixedmap_refcount_pte(pte))
return NULL;
return pte_page(pte);
#else
...
#endif
}
And finally, we may rather make this concept usable by any architecture
rather than making it s390 only, so implement a new type of pte state
for this. Unfortunately the old vma based code must stay, because some
architectures may not be able to spare pte bits. This makes vm_normal_page
a little bit more ugly than we would like, but the 2 cases are clearly
seperate.
So introduce a pte_special pte state, and use it in mm/memory.c. It is
currently a noop for all architectures, so this doesn't actually result
in any compiled code changes to mm/memory.o.
BTW:
I haven't put vm_normal_page() into arch code as-per an earlier suggestion.
The reason is that, regardless of where vm_normal_page is actually
implemented, the *abstraction* is still exactly the same. Also, while it
depends on whether the architecture has pte_special or not, that is the
only two possible cases, and it really isn't an arch specific function --
the role of the arch code should be to provide primitive functions and
accessors with which to build the core code; pte_special does that. We do
not want architectures to know or care about vm_normal_page itself, and
we definitely don't want them being able to invent something new there
out of sight of mm/ code. If we made vm_normal_page an arch function, then
we have to make vm_insert_mixed (next patch) an arch function too. So I
don't think moving it to arch code fundamentally improves any abstractions,
while it does practically make the code more difficult to follow.
I hope this isn't going to be a big problem. I don't think it is...
Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Carsten Otte <cotte@de.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jared Hulbert <jaredeh@gmail.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-mm@kvack.org
---
include/asm-alpha/pgtable.h | 2
include/asm-avr32/pgtable.h | 8 ++
include/asm-cris/pgtable.h | 2
include/asm-frv/pgtable.h | 2
include/asm-ia64/pgtable.h | 3 +
include/asm-m32r/pgtable.h | 10 +++
include/asm-m68k/motorola_pgtable.h | 2
include/asm-m68k/sun3_pgtable.h | 2
include/asm-mips/pgtable.h | 2
include/asm-parisc/pgtable.h | 2
include/asm-powerpc/pgtable-ppc32.h | 3 +
include/asm-powerpc/pgtable-ppc64.h | 3 +
include/asm-ppc/pgtable.h | 3 +
include/asm-s390/pgtable.h | 10 +++
include/asm-sh64/pgtable.h | 2
include/asm-sparc/pgtable.h | 7 ++
include/asm-sparc64/pgtable.h | 10 +++
include/asm-um/pgtable.h | 10 +++
include/asm-x86/pgtable_32.h | 2
include/asm-x86/pgtable_64.h | 2
include/asm-xtensa/pgtable.h | 4 +
include/linux/mm.h | 3 -
mm/memory.c | 98 +++++++++++++++++++-----------------
23 files changed, 147 insertions(+), 45 deletions(-)
Index: linux-2.6/include/asm-um/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-um/pgtable.h
+++ linux-2.6/include/asm-um/pgtable.h
@@ -173,6 +173,11 @@ static inline int pte_newprot(pte_t pte)
return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
+
/*
* =================================
* Flags setting section.
@@ -241,6 +246,11 @@ static inline pte_t pte_mknewpage(pte_t
return(pte);
}
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ return(pte);
+}
+
static inline void set_pte(pte_t *pteptr, pte_t pteval)
{
pte_copy(*pteptr, pteval);
Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h
+++ linux-2.6/include/linux/mm.h
@@ -714,7 +714,8 @@ struct zap_details {
unsigned long truncate_count; /* Compare vm_truncate_count */
};
-struct page *vm_normal_page(struct vm_area_struct *, unsigned long, pte_t);
+struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
+
unsigned long zap_page_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size, struct zap_details *);
unsigned long unmap_vmas(struct mmu_gather **tlb,
Index: linux-2.6/mm/memory.c
===================================================================
--- linux-2.6.orig/mm/memory.c
+++ linux-2.6/mm/memory.c
@@ -371,34 +371,38 @@ static inline int is_cow_mapping(unsigne
}
/*
- * This function gets the "struct page" associated with a pte or returns
- * NULL if no "struct page" is associated with the pte.
+ * vm_normal_page -- This function gets the "struct page" associated with a pte.
*
- * A raw VM_PFNMAP mapping (ie. one that is not COWed) may not have any "struct
- * page" backing, and even if they do, they are not refcounted. COWed pages of
- * a VM_PFNMAP do always have a struct page, and they are normally refcounted
- * (they are _normal_ pages).
- *
- * So a raw PFNMAP mapping will have each page table entry just pointing
- * to a page frame number, and as far as the VM layer is concerned, those do
- * not have pages associated with them - even if the PFN might point to memory
- * that otherwise is perfectly fine and has a "struct page".
+ * "Special" mappings do not wish to be associated with a "struct page" (either
+ * it doesn't exist, or it exists but they don't want to touch it). In this
+ * case, NULL is returned here. "Normal" mappings do have a struct page.
+ *
+ * There are 2 broad cases. Firstly, an architecture may define a pte_special()
+ * pte bit, in which case this function is trivial. Secondly, an architecture
+ * may not have a spare pte bit, which requires a more complicated scheme,
+ * described below.
+ *
+ * A raw VM_PFNMAP mapping (ie. one that is not COWed) is always considered a
+ * special mapping (even if there are underlying and valid "struct pages").
+ * COWed pages of a VM_PFNMAP are always normal.
*
* The way we recognize COWed pages within VM_PFNMAP mappings is through the
* rules set up by "remap_pfn_range()": the vma will have the VM_PFNMAP bit
- * set, and the vm_pgoff will point to the first PFN mapped: thus every
- * page that is a raw mapping will always honor the rule
+ * set, and the vm_pgoff will point to the first PFN mapped: thus every special
+ * mapping will always honor the rule
*
* pfn_of_page == vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT)
*
- * A call to vm_normal_page() will return NULL for such a page.
+ * And for normal mappings this is false.
*
- * If the page doesn't follow the "remap_pfn_range()" rule in a VM_PFNMAP
- * then the page has been COW'ed. A COW'ed page _does_ have a "struct page"
- * associated with it even if it is in a VM_PFNMAP range. Calling
- * vm_normal_page() on such a page will therefore return the "struct page".
+ * This restricts such mappings to be a linear translation from virtual address
+ * to pfn. To get around this restriction, we allow arbitrary mappings so long
+ * as the vma is not a COW mapping; in that case, we know that all ptes are
+ * special (because none can have been COWed).
*
*
+ * In order to support COW of arbitrary special mappings, we have VM_MIXEDMAP.
+ *
* VM_MIXEDMAP mappings can likewise contain memory with or without "struct
* page" backing, however the difference is that _all_ pages with a struct
* page (that is, those where pfn_valid is true) are refcounted and considered
@@ -407,16 +411,28 @@ static inline int is_cow_mapping(unsigne
* advantage is that we don't have to follow the strict linearity rule of
* PFNMAP mappings in order to support COWable mappings.
*
- * A call to vm_normal_page() with a VM_MIXEDMAP mapping will return the
- * associated "struct page" or NULL for memory not backed by a "struct page".
- *
- *
- * All other mappings should have a valid struct page, which will be
- * returned by a call to vm_normal_page().
*/
+#ifdef __HAVE_ARCH_PTE_SPECIAL
+# define HAVE_PTE_SPECIAL 1
+#else
+# define HAVE_PTE_SPECIAL 0
+#endif
struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
- unsigned long pfn = pte_pfn(pte);
+ unsigned long pfn;
+
+ if (HAVE_PTE_SPECIAL) {
+ if (likely(!pte_special(pte))) {
+ VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+ return pte_page(pte);
+ }
+ VM_BUG_ON(!(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)));
+ return NULL;
+ }
+
+ /* !HAVE_PTE_SPECIAL case follows: */
+
+ pfn = pte_pfn(pte);
if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
if (vma->vm_flags & VM_MIXEDMAP) {
@@ -424,7 +440,8 @@ struct page *vm_normal_page(struct vm_ar
return NULL;
goto out;
} else {
- unsigned long off = (addr-vma->vm_start) >> PAGE_SHIFT;
+ unsigned long off;
+ off = (addr - vma->vm_start) >> PAGE_SHIFT;
if (pfn == vma->vm_pgoff + off)
return NULL;
if (!is_cow_mapping(vma->vm_flags))
@@ -432,25 +449,12 @@ struct page *vm_normal_page(struct vm_ar
}
}
-#ifdef CONFIG_DEBUG_VM
- /*
- * Add some anal sanity checks for now. Eventually,
- * we should just do "return pfn_to_page(pfn)", but
- * in the meantime we check that we get a valid pfn,
- * and that the resulting page looks ok.
- */
- if (unlikely(!pfn_valid(pfn))) {
- print_bad_pte(vma, pte, addr);
- return NULL;
- }
-#endif
+ VM_BUG_ON(!pfn_valid(pfn));
/*
- * NOTE! We still have PageReserved() pages in the page
- * tables.
+ * NOTE! We still have PageReserved() pages in the page tables.
*
- * The PAGE_ZERO() pages and various VDSO mappings can
- * cause them to exist.
+ * eg. VDSO mappings can cause them to exist.
*/
out:
return pfn_to_page(pfn);
@@ -1264,6 +1268,12 @@ int vm_insert_pfn(struct vm_area_struct
pte_t *pte, entry;
spinlock_t *ptl;
+ /*
+ * Technically, architectures with pte_special can avoid all these
+ * restrictions (same for remap_pfn_range). However we would like
+ * consistency in testing and feature parity among all, so we should
+ * try to keep these invariants in place for everybody.
+ */
BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
BUG_ON((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) ==
(VM_PFNMAP|VM_MIXEDMAP));
@@ -1279,7 +1289,7 @@ int vm_insert_pfn(struct vm_area_struct
goto out_unlock;
/* Ok, finally just insert the thing.. */
- entry = pfn_pte(pfn, vma->vm_page_prot);
+ entry = pte_mkspecial(pfn_pte(pfn, vma->vm_page_prot));
set_pte_at(mm, addr, pte, entry);
update_mmu_cache(vma, addr, entry);
@@ -1310,7 +1320,7 @@ static int remap_pte_range(struct mm_str
arch_enter_lazy_mmu_mode();
do {
BUG_ON(!pte_none(*pte));
- set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
+ set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot)));
pfn++;
} while (pte++, addr += PAGE_SIZE, addr != end);
arch_leave_lazy_mmu_mode();
Index: linux-2.6/include/asm-alpha/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-alpha/pgtable.h
+++ linux-2.6/include/asm-alpha/pgtable.h
@@ -268,6 +268,7 @@ extern inline int pte_write(pte_t pte)
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+extern inline int pte_special(pte_t pte) { return 0; }
extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
@@ -275,6 +276,7 @@ extern inline pte_t pte_mkold(pte_t pte)
extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_FOW; return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; }
+extern inline pte_t pte_mkspecial(pte_t pte) { return pte; }
#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
Index: linux-2.6/include/asm-avr32/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-avr32/pgtable.h
+++ linux-2.6/include/asm-avr32/pgtable.h
@@ -212,6 +212,10 @@ static inline int pte_young(pte_t pte)
{
return pte_val(pte) & _PAGE_ACCESSED;
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
/*
* The following only work if pte_present() is not true.
@@ -252,6 +256,10 @@ static inline pte_t pte_mkyoung(pte_t pt
set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED));
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ return pte;
+}
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
Index: linux-2.6/include/asm-cris/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-cris/pgtable.h
+++ linux-2.6/include/asm-cris/pgtable.h
@@ -115,6 +115,7 @@ static inline int pte_write(pte_t pte)
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_wrprotect(pte_t pte)
{
@@ -162,6 +163,7 @@ static inline pte_t pte_mkyoung(pte_t pt
}
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
/*
* Conversion functions: convert a page and protection to a page entry,
Index: linux-2.6/include/asm-frv/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-frv/pgtable.h
+++ linux-2.6/include/asm-frv/pgtable.h
@@ -380,6 +380,7 @@ static inline pmd_t *pmd_offset(pud_t *d
static inline int pte_dirty(pte_t pte) { return (pte).pte & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return (pte).pte & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return !((pte).pte & _PAGE_WP); }
+static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_mkclean(pte_t pte) { (pte).pte &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { (pte).pte &= ~_PAGE_ACCESSED; return pte; }
@@ -387,6 +388,7 @@ static inline pte_t pte_wrprotect(pte_t
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
Index: linux-2.6/include/asm-ia64/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/pgtable.h
+++ linux-2.6/include/asm-ia64/pgtable.h
@@ -302,6 +302,8 @@ ia64_phys_addr_valid (unsigned long addr
#define pte_dirty(pte) ((pte_val(pte) & _PAGE_D) != 0)
#define pte_young(pte) ((pte_val(pte) & _PAGE_A) != 0)
#define pte_file(pte) ((pte_val(pte) & _PAGE_FILE) != 0)
+#define pte_special(pte) 0
+
/*
* Note: we convert AR_RWX to AR_RX and AR_RW to AR_R by clearing the 2nd bit in the
* access rights:
@@ -313,6 +315,7 @@ ia64_phys_addr_valid (unsigned long addr
#define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D))
#define pte_mkhuge(pte) (__pte(pte_val(pte)))
+#define pte_mkspecial(pte) (pte)
/*
* Because ia64's Icache and Dcache is not coherent (on a cpu), we need to
Index: linux-2.6/include/asm-m32r/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-m32r/pgtable.h
+++ linux-2.6/include/asm-m32r/pgtable.h
@@ -214,6 +214,11 @@ static inline int pte_file(pte_t pte)
return pte_val(pte) & _PAGE_FILE;
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
+
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~_PAGE_DIRTY;
@@ -250,6 +255,11 @@ static inline pte_t pte_mkwrite(pte_t pt
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ return pte;
+}
+
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
Index: linux-2.6/include/asm-m68k/motorola_pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-m68k/motorola_pgtable.h
+++ linux-2.6/include/asm-m68k/motorola_pgtable.h
@@ -168,6 +168,7 @@ static inline int pte_write(pte_t pte)
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
@@ -185,6 +186,7 @@ static inline pte_t pte_mkcache(pte_t pt
pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode;
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
Index: linux-2.6/include/asm-m68k/sun3_pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-m68k/sun3_pgtable.h
+++ linux-2.6/include/asm-m68k/sun3_pgtable.h
@@ -169,6 +169,7 @@ static inline int pte_write(pte_t pte)
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & SUN3_PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
@@ -181,6 +182,7 @@ static inline pte_t pte_mknocache(pte_t
//static inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) &= SUN3_PAGE_NOCACHE; return pte; }
// until then, use:
static inline pte_t pte_mkcache(pte_t pte) { return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
Index: linux-2.6/include/asm-mips/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-mips/pgtable.h
+++ linux-2.6/include/asm-mips/pgtable.h
@@ -285,6 +285,8 @@ static inline pte_t pte_mkyoung(pte_t pt
return pte;
}
#endif
+static inline int pte_special(pte_t pte) { return 0; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
/*
* Macro to make mark a page protection value as "uncacheable". Note
Index: linux-2.6/include/asm-parisc/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-parisc/pgtable.h
+++ linux-2.6/include/asm-parisc/pgtable.h
@@ -331,6 +331,7 @@ static inline int pte_dirty(pte_t pte)
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
@@ -338,6 +339,7 @@ static inline pte_t pte_wrprotect(pte_t
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
/*
* Conversion functions: convert a page and protection to a page entry,
Index: linux-2.6/include/asm-powerpc/pgtable-ppc32.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/pgtable-ppc32.h
+++ linux-2.6/include/asm-powerpc/pgtable-ppc32.h
@@ -514,6 +514,7 @@ static inline int pte_write(pte_t pte)
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -531,6 +532,8 @@ static inline pte_t pte_mkdirty(pte_t pt
pte_val(pte) |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) {
pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) {
+ return pte; }
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
Index: linux-2.6/include/asm-powerpc/pgtable-ppc64.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/pgtable-ppc64.h
+++ linux-2.6/include/asm-powerpc/pgtable-ppc64.h
@@ -239,6 +239,7 @@ static inline int pte_write(pte_t pte) {
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
+static inline int pte_special(pte_t pte) { return 0; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -257,6 +258,8 @@ static inline pte_t pte_mkyoung(pte_t pt
pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkhuge(pte_t pte) {
return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) {
+ return pte; }
/* Atomic PTE updates */
static inline unsigned long pte_update(struct mm_struct *mm,
Index: linux-2.6/include/asm-ppc/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-ppc/pgtable.h
+++ linux-2.6/include/asm-ppc/pgtable.h
@@ -491,6 +491,7 @@ static inline int pte_write(pte_t pte)
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -508,6 +509,8 @@ static inline pte_t pte_mkdirty(pte_t pt
pte_val(pte) |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) {
pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) {
+ return pte; }
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
Index: linux-2.6/include/asm-s390/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-s390/pgtable.h
+++ linux-2.6/include/asm-s390/pgtable.h
@@ -510,6 +510,11 @@ static inline int pte_file(pte_t pte)
return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
+
#define __HAVE_ARCH_PTE_SAME
#define pte_same(a,b) (pte_val(a) == pte_val(b))
@@ -663,6 +668,11 @@ static inline pte_t pte_mkyoung(pte_t pt
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ return pte;
+}
+
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
Index: linux-2.6/include/asm-sparc/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-sparc/pgtable.h
+++ linux-2.6/include/asm-sparc/pgtable.h
@@ -219,6 +219,11 @@ static inline int pte_file(pte_t pte)
return pte_val(pte) & BTFIXUP_HALF(pte_filei);
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
+
/*
*/
BTFIXUPDEF_HALF(pte_wrprotecti)
@@ -251,6 +256,8 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung
#define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
#define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
+#define pte_mkspecial(pte_t pte) (pte)
+
#define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot)
BTFIXUPDEF_CALL(unsigned long, pte_pfn, pte_t)
Index: linux-2.6/include/asm-sparc64/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-sparc64/pgtable.h
+++ linux-2.6/include/asm-sparc64/pgtable.h
@@ -506,6 +506,11 @@ static inline pte_t pte_mkyoung(pte_t pt
return __pte(pte_val(pte) | mask);
}
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ return pte;
+}
+
static inline unsigned long pte_young(pte_t pte)
{
unsigned long mask;
@@ -608,6 +613,11 @@ static inline unsigned long pte_present(
return val;
}
+static inline int pte_special(pte_t pte)
+{
+ return 0;
+}
+
#define pmd_set(pmdp, ptep) \
(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
#define pud_set(pudp, pmdp) \
Index: linux-2.6/include/asm-xtensa/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-xtensa/pgtable.h
+++ linux-2.6/include/asm-xtensa/pgtable.h
@@ -210,6 +210,8 @@ static inline int pte_write(pte_t pte) {
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
+
static inline pte_t pte_wrprotect(pte_t pte)
{ pte_val(pte) &= ~(_PAGE_WRITABLE | _PAGE_HW_WRITE); return pte; }
static inline pte_t pte_mkclean(pte_t pte)
@@ -222,6 +224,8 @@ static inline pte_t pte_mkyoung(pte_t pt
{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte)
{ pte_val(pte) |= _PAGE_WRITABLE; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte)
+ { return pte; }
/*
* Conversion functions: convert a page and protection to a page entry,
Index: linux-2.6/include/asm-x86/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-x86/pgtable.h
+++ linux-2.6/include/asm-x86/pgtable.h
@@ -149,6 +149,7 @@ static inline int pte_file(pte_t pte) {
static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; }
static inline int pte_global(pte_t pte) { return pte_val(pte) & _PAGE_GLOBAL; }
static inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NX); }
+static inline int pte_special(pte_t pte) { return 0; }
static inline int pmd_large(pmd_t pte) {
return (pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
@@ -166,6 +167,7 @@ static inline pte_t pte_mkhuge(pte_t pte
static inline pte_t pte_clrhuge(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); }
static inline pte_t pte_mkglobal(pte_t pte) { return __pte(pte_val(pte) | _PAGE_GLOBAL); }
static inline pte_t pte_clrglobal(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
extern pteval_t __supported_pte_mask;
Index: linux-2.6/include/asm-mn10300/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-mn10300/pgtable.h
+++ linux-2.6/include/asm-mn10300/pgtable.h
@@ -224,6 +224,7 @@ static inline int pte_read(pte_t pte) {
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & __PAGE_PROT_WRITE; }
+static inline int pte_special(pte_t pte){ return 0; }
/*
* The following only works if pte_present() is not true.
@@ -265,6 +266,8 @@ static inline pte_t pte_mkwrite(pte_t pt
return pte;
}
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
#define pte_ERROR(e) \
printk(KERN_ERR "%s:%d: bad pte %08lx.\n", \
__FILE__, __LINE__, pte_val(e))
Index: linux-2.6/include/asm-sh/pgtable_32.h
===================================================================
--- linux-2.6.orig/include/asm-sh/pgtable_32.h
+++ linux-2.6/include/asm-sh/pgtable_32.h
@@ -326,6 +326,7 @@ static inline void set_pte(pte_t *ptep,
#define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY)
#define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED)
#define pte_file(pte) ((pte).pte_low & _PAGE_FILE)
+#define pte_special(pte) (0)
#ifdef CONFIG_X2TLB
#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE)
@@ -356,6 +357,8 @@ PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRT
PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED);
PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
/*
* Macro and implementation to make a page protection as uncachable.
*/
Index: linux-2.6/include/asm-sh/pgtable_64.h
===================================================================
--- linux-2.6.orig/include/asm-sh/pgtable_64.h
+++ linux-2.6/include/asm-sh/pgtable_64.h
@@ -254,10 +254,11 @@ extern void __handle_bad_pmd_kernel(pmd_
/*
* The following have defined behavior only work if pte_present() is true.
*/
-static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
-static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
-static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_special(pte_t pte){ return 0; }
static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
@@ -266,6 +267,7 @@ static inline pte_t pte_mkwrite(pte_t pt
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
/*
Index: linux-2.6/include/asm-arm/pgtable.h
===================================================================
--- linux-2.6.orig/include/asm-arm/pgtable.h
+++ linux-2.6/include/asm-arm/pgtable.h
@@ -260,6 +260,7 @@ extern struct page *empty_zero_page;
#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+#define pte_special(pte) (0)
/*
* The following only works if pte_present() is not true.
@@ -280,6 +281,8 @@ PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY);
PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG);
PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
/*
* Mark the prot value as uncacheable and unbufferable.
*/
--
--
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] 14+ messages in thread* [patch 3/7] mm: add vm_insert_mixed
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
2008-03-11 10:46 ` [patch 1/7] mm: introduce VM_MIXEDMAP npiggin, Jared Hulbert
2008-03-11 10:46 ` [patch 2/7] mm: introduce pte_special pte bit npiggin
@ 2008-03-11 10:46 ` npiggin
2008-03-11 10:46 ` [patch 4/7] Alter the block device ->direct_access() API to work with the new get_xip_mem() API (that requires both kaddr and pfn are returned) npiggin
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: npiggin @ 2008-03-11 10:46 UTC (permalink / raw)
To: Linus Torvalds
Cc: akpm, Jared Hulbert, Carsten Otte, Martin Schwidefsky,
Heiko Carstens, linux-mm
[-- Attachment #1: mm-insert_mixed.patch --]
[-- Type: text/plain, Size: 5169 bytes --]
vm_insert_mixed will insert either a raw pfn or a refcounted struct page
into the page tables, depending on whether vm_normal_page() will return
the page or not. With the introduction of the new pte bit, this is now
a too tricky for drivers to be doing themselves.
filemap_xip uses this in a subsequent patch.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Jared Hulbert <jaredeh@gmail.com>
Cc: Carsten Otte <cotte@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-mm@kvack.org
---
include/linux/mm.h | 2 +
mm/memory.c | 79 ++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 57 insertions(+), 24 deletions(-)
Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h
+++ linux-2.6/include/linux/mm.h
@@ -1144,6 +1144,8 @@ int remap_pfn_range(struct vm_area_struc
int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn);
+int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long pfn);
struct page *follow_page(struct vm_area_struct *, unsigned long address,
unsigned int foll_flags);
Index: linux-2.6/mm/memory.c
===================================================================
--- linux-2.6.orig/mm/memory.c
+++ linux-2.6/mm/memory.c
@@ -1176,8 +1176,9 @@ pte_t *get_locked_pte(struct mm_struct *
* old drivers should use this, and they needed to mark their
* pages reserved for the old functions anyway.
*/
-static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *page, pgprot_t prot)
+static int insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot)
{
+ struct mm_struct *mm = vma->vm_mm;
int retval;
pte_t *pte;
spinlock_t *ptl;
@@ -1244,10 +1245,37 @@ int vm_insert_page(struct vm_area_struct
if (!page_count(page))
return -EINVAL;
vma->vm_flags |= VM_INSERTPAGE;
- return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot);
+ return insert_page(vma, addr, page, vma->vm_page_prot);
}
EXPORT_SYMBOL(vm_insert_page);
+static int insert_pfn(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t prot)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int retval;
+ pte_t *pte, entry;
+ spinlock_t *ptl;
+
+ retval = -ENOMEM;
+ pte = get_locked_pte(mm, addr, &ptl);
+ if (!pte)
+ goto out;
+ retval = -EBUSY;
+ if (!pte_none(*pte))
+ goto out_unlock;
+
+ /* Ok, finally just insert the thing.. */
+ entry = pte_mkspecial(pfn_pte(pfn, prot));
+ set_pte_at(mm, addr, pte, entry);
+ update_mmu_cache(vma, addr, entry); /* XXX: why not for insert_page? */
+
+ retval = 0;
+out_unlock:
+ pte_unmap_unlock(pte, ptl);
+out:
+ return retval;
+}
+
/**
* vm_insert_pfn - insert single pfn into user vma
* @vma: user vma to map to
@@ -1263,11 +1291,6 @@ EXPORT_SYMBOL(vm_insert_page);
int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn)
{
- struct mm_struct *mm = vma->vm_mm;
- int retval;
- pte_t *pte, entry;
- spinlock_t *ptl;
-
/*
* Technically, architectures with pte_special can avoid all these
* restrictions (same for remap_pfn_range). However we would like
@@ -1280,27 +1303,35 @@ int vm_insert_pfn(struct vm_area_struct
BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
- retval = -ENOMEM;
- pte = get_locked_pte(mm, addr, &ptl);
- if (!pte)
- goto out;
- retval = -EBUSY;
- if (!pte_none(*pte))
- goto out_unlock;
+ if (addr < vma->vm_start || addr >= vma->vm_end)
+ return -EFAULT;
+ return insert_pfn(vma, addr, pfn, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_insert_pfn);
- /* Ok, finally just insert the thing.. */
- entry = pte_mkspecial(pfn_pte(pfn, vma->vm_page_prot));
- set_pte_at(mm, addr, pte, entry);
- update_mmu_cache(vma, addr, entry);
+int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long pfn)
+{
+ BUG_ON(!(vma->vm_flags & VM_MIXEDMAP));
- retval = 0;
-out_unlock:
- pte_unmap_unlock(pte, ptl);
+ if (addr < vma->vm_start || addr >= vma->vm_end)
+ return -EFAULT;
-out:
- return retval;
+ /*
+ * If we don't have pte special, then we have to use the pfn_valid()
+ * based VM_MIXEDMAP scheme (see vm_normal_page), and thus we *must*
+ * refcount the page if pfn_valid is true (hence insert_page rather
+ * than insert_pfn).
+ */
+ if (!HAVE_PTE_SPECIAL && pfn_valid(pfn)) {
+ struct page *page;
+
+ page = pfn_to_page(pfn);
+ return insert_page(vma, addr, page, vma->vm_page_prot);
+ }
+ return insert_pfn(vma, addr, pfn, vma->vm_page_prot);
}
-EXPORT_SYMBOL(vm_insert_pfn);
+EXPORT_SYMBOL(vm_insert_mixed);
/*
* maps a range of physical memory into the requested pages. the old
--
--
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] 14+ messages in thread* [patch 4/7] Alter the block device ->direct_access() API to work with the new get_xip_mem() API (that requires both kaddr and pfn are returned).
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
` (2 preceding siblings ...)
2008-03-11 10:46 ` [patch 3/7] mm: add vm_insert_mixed npiggin
@ 2008-03-11 10:46 ` npiggin
2008-03-11 10:46 ` [patch 5/7] xip: support non-struct page backed memory npiggin
` (2 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: npiggin @ 2008-03-11 10:46 UTC (permalink / raw)
To: Linus Torvalds
Cc: akpm, Jared Hulbert, Carsten Otte, Heiko Carstens, linux-mm
[-- Attachment #1: xip-direct_access-pfn.patch --]
[-- Type: text/plain, Size: 5168 bytes --]
---
Index: linux-2.6/arch/powerpc/sysdev/axonram.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/axonram.c
+++ linux-2.6/arch/powerpc/sysdev/axonram.c
@@ -143,7 +143,7 @@ axon_ram_make_request(struct request_que
*/
static int
axon_ram_direct_access(struct block_device *device, sector_t sector,
- unsigned long *data)
+ void **kaddr, unsigned long *pfn)
{
struct axon_ram_bank *bank = device->bd_disk->private_data;
loff_t offset;
@@ -154,7 +154,8 @@ axon_ram_direct_access(struct block_devi
return -ERANGE;
}
- *data = bank->ph_addr + offset;
+ *kaddr = (void *)(bank->ph_addr + offset);
+ *pfn = virt_to_phys(kaddr) >> PAGE_SHIFT;
return 0;
}
Index: linux-2.6/drivers/block/brd.c
===================================================================
--- linux-2.6.orig/drivers/block/brd.c
+++ linux-2.6/drivers/block/brd.c
@@ -319,7 +319,7 @@ out:
#ifdef CONFIG_BLK_DEV_XIP
static int brd_direct_access (struct block_device *bdev, sector_t sector,
- unsigned long *data)
+ void **kaddr, unsigned long *pfn)
{
struct brd_device *brd = bdev->bd_disk->private_data;
struct page *page;
@@ -333,7 +333,8 @@ static int brd_direct_access (struct blo
page = brd_insert_page(brd, sector);
if (!page)
return -ENOMEM;
- *data = (unsigned long)page_address(page);
+ *kaddr = page_address(page);
+ *pfn = page_to_pfn(page);
return 0;
}
Index: linux-2.6/drivers/s390/block/dcssblk.c
===================================================================
--- linux-2.6.orig/drivers/s390/block/dcssblk.c
+++ linux-2.6/drivers/s390/block/dcssblk.c
@@ -36,7 +36,7 @@ static int dcssblk_open(struct inode *in
static int dcssblk_release(struct inode *inode, struct file *filp);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
- unsigned long *data);
+ void **kaddr, unsigned long *pfn);
static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
@@ -687,7 +687,7 @@ fail:
static int
dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
- unsigned long *data)
+ void **kaddr, unsigned long *pfn)
{
struct dcssblk_dev_info *dev_info;
unsigned long pgoff;
@@ -700,7 +700,9 @@ dcssblk_direct_access (struct block_devi
pgoff = secnum / (PAGE_SIZE / 512);
if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
return -ERANGE;
- *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
+ *kaddr = (void *) (dev_info->start+pgoff*PAGE_SIZE);
+ *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT;
+
return 0;
}
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1129,7 +1129,8 @@ struct block_device_operations {
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
- int (*direct_access) (struct block_device *, sector_t, unsigned long *);
+ int (*direct_access) (struct block_device *, sector_t,
+ void **, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
Index: linux-2.6/fs/ext2/xip.c
===================================================================
--- linux-2.6.orig/fs/ext2/xip.c
+++ linux-2.6/fs/ext2/xip.c
@@ -16,11 +16,11 @@
static inline int
__inode_direct_access(struct inode *inode, sector_t sector,
- unsigned long *data)
+ void **kaddr, unsigned long *pfn)
{
BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
return inode->i_sb->s_bdev->bd_disk->fops
- ->direct_access(inode->i_sb->s_bdev,sector,data);
+ ->direct_access(inode->i_sb->s_bdev, sector, kaddr, pfn);
}
static inline int
@@ -48,12 +48,13 @@ int
ext2_clear_xip_target(struct inode *inode, int block)
{
sector_t sector = block * (PAGE_SIZE/512);
- unsigned long data;
+ void *kaddr;
+ unsigned long pfn;
int rc;
- rc = __inode_direct_access(inode, sector, &data);
+ rc = __inode_direct_access(inode, sector, &kaddr, &pfn);
if (!rc)
- clear_page((void*)data);
+ clear_page(kaddr);
return rc;
}
@@ -74,7 +75,8 @@ ext2_get_xip_page(struct address_space *
int create)
{
int rc;
- unsigned long data;
+ void *kaddr;
+ unsigned long pfn;
sector_t sector;
/* first, retrieve the sector number */
@@ -84,9 +86,9 @@ ext2_get_xip_page(struct address_space *
/* retrieve address of the target data */
rc = __inode_direct_access
- (mapping->host, sector * (PAGE_SIZE/512), &data);
+ (mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn);
if (!rc)
- return virt_to_page(data);
+ return pfn_to_page(pfn);
error:
return ERR_PTR(rc);
--
--
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] 14+ messages in thread* [patch 5/7] xip: support non-struct page backed memory
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
` (3 preceding siblings ...)
2008-03-11 10:46 ` [patch 4/7] Alter the block device ->direct_access() API to work with the new get_xip_mem() API (that requires both kaddr and pfn are returned) npiggin
@ 2008-03-11 10:46 ` npiggin
2008-03-11 11:44 ` [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work Nick Piggin
2008-03-12 4:35 ` Andrew Morton
6 siblings, 0 replies; 14+ messages in thread
From: npiggin @ 2008-03-11 10:46 UTC (permalink / raw)
To: Linus Torvalds
Cc: akpm, Carsten Otte, Jared Hulbert, Martin Schwidefsky,
Heiko Carstens, linux-mm, linux-fsdevel
[-- Attachment #1: xip-get_xip_addr.patch --]
[-- Type: text/plain, Size: 17732 bytes --]
Convert XIP to support non-struct page backed memory, using VM_MIXEDMAP
for the user mappings.
This requires the get_xip_page API to be changed to an address based one.
Improve the API layering a little bit too, while we're here.
(The kaddr->pfn conversion may not be quite right for all architectures or XIP
memory mappings, and the cacheflushing may need to be added for some archs).
This scheme has been tested and works with the new brd driver. It is
recently changed in order to provide a kaddr and user-mappable pfn, so
needs retesting with s390 and Jared's filesystem.
This is required to have XIP filesystems on memory that isn't backed with
struct page.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Carsten Otte <cotte@de.ibm.com>
Cc: Jared Hulbert <jaredeh@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-mm@kvack.org
Cc: linux-fsdevel@vger.kernel.org
---
fs/ext2/inode.c | 2
fs/ext2/xip.c | 36 ++++-----
fs/ext2/xip.h | 8 +-
fs/open.c | 2
include/linux/fs.h | 3
mm/fadvise.c | 2
mm/filemap_xip.c | 191 ++++++++++++++++++++++++++---------------------------
mm/madvise.c | 2
8 files changed, 122 insertions(+), 124 deletions(-)
Index: linux-2.6/fs/ext2/inode.c
===================================================================
--- linux-2.6.orig/fs/ext2/inode.c
+++ linux-2.6/fs/ext2/inode.c
@@ -796,7 +796,7 @@ const struct address_space_operations ex
const struct address_space_operations ext2_aops_xip = {
.bmap = ext2_bmap,
- .get_xip_page = ext2_get_xip_page,
+ .get_xip_mem = ext2_get_xip_mem,
};
const struct address_space_operations ext2_nobh_aops = {
Index: linux-2.6/fs/ext2/xip.c
===================================================================
--- linux-2.6.orig/fs/ext2/xip.c
+++ linux-2.6/fs/ext2/xip.c
@@ -15,24 +15,27 @@
#include "xip.h"
static inline int
-__inode_direct_access(struct inode *inode, sector_t sector,
+__inode_direct_access(struct inode *inode, sector_t block,
void **kaddr, unsigned long *pfn)
{
+ sector_t sector;
+
+ sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */
+
BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
return inode->i_sb->s_bdev->bd_disk->fops
->direct_access(inode->i_sb->s_bdev, sector, kaddr, pfn);
}
static inline int
-__ext2_get_sector(struct inode *inode, sector_t offset, int create,
+__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create,
sector_t *result)
{
struct buffer_head tmp;
int rc;
memset(&tmp, 0, sizeof(struct buffer_head));
- rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp,
- create);
+ rc = ext2_get_block(inode, pgoff, &tmp, create);
*result = tmp.b_blocknr;
/* did we get a sparse block (hole in the file)? */
@@ -45,14 +48,13 @@ __ext2_get_sector(struct inode *inode, s
}
int
-ext2_clear_xip_target(struct inode *inode, int block)
+ext2_clear_xip_target(struct inode *inode, sector_t block)
{
- sector_t sector = block * (PAGE_SIZE/512);
void *kaddr;
unsigned long pfn;
int rc;
- rc = __inode_direct_access(inode, sector, &kaddr, &pfn);
+ rc = __inode_direct_access(inode, block, &kaddr, &pfn);
if (!rc)
clear_page(kaddr);
return rc;
@@ -70,26 +72,18 @@ void ext2_xip_verify_sb(struct super_blo
}
}
-struct page *
-ext2_get_xip_page(struct address_space *mapping, sector_t offset,
- int create)
+int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
+ void **kmem, unsigned long *pfn)
{
int rc;
- void *kaddr;
- unsigned long pfn;
- sector_t sector;
+ sector_t block;
/* first, retrieve the sector number */
- rc = __ext2_get_sector(mapping->host, offset, create, §or);
+ rc = __ext2_get_block(mapping->host, pgoff, create, &block);
if (rc)
- goto error;
+ return rc;
/* retrieve address of the target data */
- rc = __inode_direct_access
- (mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn);
- if (!rc)
- return pfn_to_page(pfn);
-
- error:
- return ERR_PTR(rc);
+ rc = __inode_direct_access(mapping->host, block, kmem, pfn);
+ return rc;
}
Index: linux-2.6/fs/ext2/xip.h
===================================================================
--- linux-2.6.orig/fs/ext2/xip.h
+++ linux-2.6/fs/ext2/xip.h
@@ -7,19 +7,20 @@
#ifdef CONFIG_EXT2_FS_XIP
extern void ext2_xip_verify_sb (struct super_block *);
-extern int ext2_clear_xip_target (struct inode *, int);
+extern int ext2_clear_xip_target (struct inode *, sector_t);
static inline int ext2_use_xip (struct super_block *sb)
{
struct ext2_sb_info *sbi = EXT2_SB(sb);
return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
}
-struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
-#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
+int ext2_get_xip_mem(struct address_space *, pgoff_t, int,
+ void **, unsigned long *);
+#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_mem)
#else
#define mapping_is_xip(map) 0
#define ext2_xip_verify_sb(sb) do { } while (0)
#define ext2_use_xip(sb) 0
#define ext2_clear_xip_target(inode, chain) 0
-#define ext2_get_xip_page NULL
+#define ext2_get_xip_mem do { BUG(); } while (0)
#endif
Index: linux-2.6/fs/open.c
===================================================================
--- linux-2.6.orig/fs/open.c
+++ linux-2.6/fs/open.c
@@ -774,7 +774,7 @@ static struct file *__dentry_open(struct
if (f->f_flags & O_DIRECT) {
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
- (!f->f_mapping->a_ops->get_xip_page))) {
+ (!f->f_mapping->a_ops->get_xip_mem))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -475,8 +475,8 @@ struct address_space_operations {
int (*releasepage) (struct page *, gfp_t);
ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
- struct page* (*get_xip_page)(struct address_space *, sector_t,
- int);
+ int (*get_xip_mem)(struct address_space *, pgoff_t, int,
+ void **, unsigned long *);
/* migrate the contents of a page to the specified target */
int (*migratepage) (struct address_space *,
struct page *, struct page *);
Index: linux-2.6/mm/fadvise.c
===================================================================
--- linux-2.6.orig/mm/fadvise.c
+++ linux-2.6/mm/fadvise.c
@@ -49,7 +49,7 @@ asmlinkage long sys_fadvise64_64(int fd,
goto out;
}
- if (mapping->a_ops->get_xip_page) {
+ if (mapping->a_ops->get_xip_mem) {
switch (advice) {
case POSIX_FADV_NORMAL:
case POSIX_FADV_RANDOM:
Index: linux-2.6/mm/filemap_xip.c
===================================================================
--- linux-2.6.orig/mm/filemap_xip.c
+++ linux-2.6/mm/filemap_xip.c
@@ -15,6 +15,7 @@
#include <linux/rmap.h>
#include <linux/sched.h>
#include <asm/tlbflush.h>
+#include <asm/io.h>
/*
* We do use our own empty page to avoid interference with other users
@@ -42,37 +43,41 @@ static struct page *xip_sparse_page(void
/*
* This is a file read routine for execute in place files, and uses
- * the mapping->a_ops->get_xip_page() function for the actual low-level
+ * the mapping->a_ops->get_xip_mem() function for the actual low-level
* stuff.
*
* Note the struct file* is not used at all. It may be NULL.
*/
-static void
+static ssize_t
do_xip_mapping_read(struct address_space *mapping,
struct file_ra_state *_ra,
struct file *filp,
- loff_t *ppos,
- read_descriptor_t *desc,
- read_actor_t actor)
+ char __user *buf,
+ size_t len,
+ loff_t *ppos)
{
struct inode *inode = mapping->host;
pgoff_t index, end_index;
unsigned long offset;
- loff_t isize;
+ loff_t isize, pos;
+ size_t copied = 0, error = 0;
- BUG_ON(!mapping->a_ops->get_xip_page);
+ BUG_ON(!mapping->a_ops->get_xip_mem);
- index = *ppos >> PAGE_CACHE_SHIFT;
- offset = *ppos & ~PAGE_CACHE_MASK;
+ pos = *ppos;
+ index = pos >> PAGE_CACHE_SHIFT;
+ offset = pos & ~PAGE_CACHE_MASK;
isize = i_size_read(inode);
if (!isize)
goto out;
end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
- for (;;) {
- struct page *page;
- unsigned long nr, ret;
+ do {
+ unsigned long nr, left;
+ void *xip_mem;
+ unsigned long xip_pfn;
+ int zero = 0;
/* nr is the maximum number of bytes to copy from this page */
nr = PAGE_CACHE_SIZE;
@@ -85,19 +90,17 @@ do_xip_mapping_read(struct address_space
}
}
nr = nr - offset;
+ if (nr > len)
+ nr = len;
- page = mapping->a_ops->get_xip_page(mapping,
- index*(PAGE_SIZE/512), 0);
- if (!page)
- goto no_xip_page;
- if (unlikely(IS_ERR(page))) {
- if (PTR_ERR(page) == -ENODATA) {
+ error = mapping->a_ops->get_xip_mem(mapping, index, 0,
+ &xip_mem, &xip_pfn);
+ if (unlikely(error)) {
+ if (error == -ENODATA) {
/* sparse */
- page = ZERO_PAGE(0);
- } else {
- desc->error = PTR_ERR(page);
+ zero = 1;
+ } else
goto out;
- }
}
/* If users can be writing to this page using arbitrary
@@ -105,10 +108,10 @@ do_xip_mapping_read(struct address_space
* before reading the page on the kernel side.
*/
if (mapping_writably_mapped(mapping))
- flush_dcache_page(page);
+ /* address based flush */ ;
/*
- * Ok, we have the page, so now we can copy it to user space...
+ * Ok, we have the mem, so now we can copy it to user space...
*
* The actor routine returns how many bytes were actually used..
* NOTE! This may not be the same as how much of a user buffer
@@ -116,47 +119,38 @@ do_xip_mapping_read(struct address_space
* "pos" here (the actor routine has to update the user buffer
* pointers and the remaining count).
*/
- ret = actor(desc, page, offset, nr);
- offset += ret;
- index += offset >> PAGE_CACHE_SHIFT;
- offset &= ~PAGE_CACHE_MASK;
+ if (!zero)
+ left = __copy_to_user(buf+copied, xip_mem+offset, nr);
+ else
+ left = __clear_user(buf + copied, nr);
- if (ret == nr && desc->count)
- continue;
- goto out;
+ if (left) {
+ error = -EFAULT;
+ goto out;
+ }
-no_xip_page:
- /* Did not get the page. Report it */
- desc->error = -EIO;
- goto out;
- }
+ copied += (nr - left);
+ offset += (nr - left);
+ index += offset >> PAGE_CACHE_SHIFT;
+ offset &= ~PAGE_CACHE_MASK;
+ } while (copied < len);
out:
- *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
+ *ppos = pos + copied;
if (filp)
file_accessed(filp);
+
+ return (copied ? copied : error);
}
ssize_t
xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
- read_descriptor_t desc;
-
if (!access_ok(VERIFY_WRITE, buf, len))
return -EFAULT;
- desc.written = 0;
- desc.arg.buf = buf;
- desc.count = len;
- desc.error = 0;
-
- do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
- ppos, &desc, file_read_actor);
-
- if (desc.written)
- return desc.written;
- else
- return desc.error;
+ return do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
+ buf, len, ppos);
}
EXPORT_SYMBOL_GPL(xip_file_read);
@@ -211,13 +205,16 @@ __xip_unmap (struct address_space * mapp
*
* This function is derived from filemap_fault, but used for execute in place
*/
-static int xip_file_fault(struct vm_area_struct *area, struct vm_fault *vmf)
+static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
- struct file *file = area->vm_file;
+ struct file *file = vma->vm_file;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
- struct page *page;
pgoff_t size;
+ void *xip_mem;
+ unsigned long xip_pfn;
+ struct page *page;
+ int error;
/* XXX: are VM_FAULT_ codes OK? */
@@ -225,35 +222,44 @@ static int xip_file_fault(struct vm_area
if (vmf->pgoff >= size)
return VM_FAULT_SIGBUS;
- page = mapping->a_ops->get_xip_page(mapping,
- vmf->pgoff*(PAGE_SIZE/512), 0);
- if (!IS_ERR(page))
- goto out;
- if (PTR_ERR(page) != -ENODATA)
+ error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 0,
+ &xip_mem, &xip_pfn);
+ if (likely(!error))
+ goto found;
+ if (error != -ENODATA)
return VM_FAULT_OOM;
/* sparse block */
- if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
- (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
+ if ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
+ (vma->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
(!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
+ int err;
+
/* maybe shared writable, allocate new block */
- page = mapping->a_ops->get_xip_page(mapping,
- vmf->pgoff*(PAGE_SIZE/512), 1);
- if (IS_ERR(page))
+ error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 1,
+ &xip_mem, &xip_pfn);
+ if (error)
return VM_FAULT_SIGBUS;
- /* unmap page at pgoff from all other vmas */
+ /* unmap sparse mappings at pgoff from all other vmas */
__xip_unmap(mapping, vmf->pgoff);
+
+found:
+ err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
+ xip_pfn);
+ if (err == -ENOMEM)
+ return VM_FAULT_OOM;
+ BUG_ON(err);
+ return VM_FAULT_NOPAGE;
} else {
/* not shared and writable, use xip_sparse_page() */
page = xip_sparse_page();
if (!page)
return VM_FAULT_OOM;
- }
-out:
- page_cache_get(page);
- vmf->page = page;
- return 0;
+ page_cache_get(page);
+ vmf->page = page;
+ return 0;
+ }
}
static struct vm_operations_struct xip_file_vm_ops = {
@@ -262,11 +268,11 @@ static struct vm_operations_struct xip_f
int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- BUG_ON(!file->f_mapping->a_ops->get_xip_page);
+ BUG_ON(!file->f_mapping->a_ops->get_xip_mem);
file_accessed(file);
vma->vm_ops = &xip_file_vm_ops;
- vma->vm_flags |= VM_CAN_NONLINEAR;
+ vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
return 0;
}
EXPORT_SYMBOL_GPL(xip_file_mmap);
@@ -279,17 +285,17 @@ __xip_file_write(struct file *filp, cons
const struct address_space_operations *a_ops = mapping->a_ops;
struct inode *inode = mapping->host;
long status = 0;
- struct page *page;
size_t bytes;
ssize_t written = 0;
- BUG_ON(!mapping->a_ops->get_xip_page);
+ BUG_ON(!mapping->a_ops->get_xip_mem);
do {
unsigned long index;
unsigned long offset;
size_t copied;
- char *kaddr;
+ void *xip_mem;
+ unsigned long xip_pfn;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
index = pos >> PAGE_CACHE_SHIFT;
@@ -297,28 +303,22 @@ __xip_file_write(struct file *filp, cons
if (bytes > count)
bytes = count;
- page = a_ops->get_xip_page(mapping,
- index*(PAGE_SIZE/512), 0);
- if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
+ status = a_ops->get_xip_mem(mapping, index, 0,
+ &xip_mem, &xip_pfn);
+ if (status == -ENODATA) {
/* we allocate a new page unmap it */
- page = a_ops->get_xip_page(mapping,
- index*(PAGE_SIZE/512), 1);
- if (!IS_ERR(page))
+ status = a_ops->get_xip_mem(mapping, index, 1,
+ &xip_mem, &xip_pfn);
+ if (!status)
/* unmap page at pgoff from all other vmas */
__xip_unmap(mapping, index);
}
- if (IS_ERR(page)) {
- status = PTR_ERR(page);
+ if (status)
break;
- }
- fault_in_pages_readable(buf, bytes);
- kaddr = kmap_atomic(page, KM_USER0);
copied = bytes -
- __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
- kunmap_atomic(kaddr, KM_USER0);
- flush_dcache_page(page);
+ __copy_from_user_nocache(xip_mem + offset, buf, bytes);
if (likely(copied > 0)) {
status = copied;
@@ -398,7 +398,7 @@ EXPORT_SYMBOL_GPL(xip_file_write);
/*
* truncate a page used for execute in place
- * functionality is analog to block_truncate_page but does use get_xip_page
+ * functionality is analog to block_truncate_page but does use get_xip_mem
* to get the page instead of page cache
*/
int
@@ -408,9 +408,11 @@ xip_truncate_page(struct address_space *
unsigned offset = from & (PAGE_CACHE_SIZE-1);
unsigned blocksize;
unsigned length;
- struct page *page;
+ void *xip_mem;
+ unsigned long xip_pfn;
+ int err;
- BUG_ON(!mapping->a_ops->get_xip_page);
+ BUG_ON(!mapping->a_ops->get_xip_mem);
blocksize = 1 << mapping->host->i_blkbits;
length = offset & (blocksize - 1);
@@ -421,18 +423,16 @@ xip_truncate_page(struct address_space *
length = blocksize - length;
- page = mapping->a_ops->get_xip_page(mapping,
- index*(PAGE_SIZE/512), 0);
- if (!page)
- return -ENOMEM;
- if (unlikely(IS_ERR(page))) {
- if (PTR_ERR(page) == -ENODATA)
+ err = mapping->a_ops->get_xip_mem(mapping, index, 0,
+ &xip_mem, &xip_pfn);
+ if (unlikely(err)) {
+ if (err == -ENODATA)
/* Hole? No need to truncate */
return 0;
else
- return PTR_ERR(page);
+ return err;
}
- zero_user(page, offset, length);
+ memset(xip_mem + offset, 0, length);
return 0;
}
EXPORT_SYMBOL_GPL(xip_truncate_page);
Index: linux-2.6/mm/madvise.c
===================================================================
--- linux-2.6.orig/mm/madvise.c
+++ linux-2.6/mm/madvise.c
@@ -112,7 +112,7 @@ static long madvise_willneed(struct vm_a
if (!file)
return -EBADF;
- if (file->f_mapping->a_ops->get_xip_page) {
+ if (file->f_mapping->a_ops->get_xip_mem) {
/* no bad return value, but ignore advice */
return 0;
}
--
--
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] 14+ messages in thread* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
` (4 preceding siblings ...)
2008-03-11 10:46 ` [patch 5/7] xip: support non-struct page backed memory npiggin
@ 2008-03-11 11:44 ` Nick Piggin
2008-03-11 21:12 ` Jared Hulbert
2008-03-12 4:35 ` Andrew Morton
6 siblings, 1 reply; 14+ messages in thread
From: Nick Piggin @ 2008-03-11 11:44 UTC (permalink / raw)
To: npiggin
Cc: Linus Torvalds, akpm, Jared Hulbert, Carsten Otte,
Martin Schwidefsky, Heiko Carstens, linux-mm
On Tuesday 11 March 2008 21:46, npiggin@nick.local0.net wrote:
> --
>
> (doh, please ignore the previous "x/6" patches, they're old. The
> new ones are these x/7 set)
Ah shit and now I use the wrong address. Sorry. If you could take
it in your heart to correct it when you reply to me, I won't have
to mailbomb everyone again.
--
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] 14+ messages in thread* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-11 11:44 ` [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work Nick Piggin
@ 2008-03-11 21:12 ` Jared Hulbert
2008-03-11 23:21 ` Nick Piggin
0 siblings, 1 reply; 14+ messages in thread
From: Jared Hulbert @ 2008-03-11 21:12 UTC (permalink / raw)
To: Nick Piggin
Cc: npiggin, Linus Torvalds, akpm, Carsten Otte, Martin Schwidefsky,
Heiko Carstens, linux-mm
> > (doh, please ignore the previous "x/6" patches, they're old. The
> > new ones are these x/7 set)
>
> Ah shit and now I use the wrong address. Sorry. If you could take
> it in your heart to correct it when you reply to me, I won't have
> to mailbomb everyone again.
is there a [patch 6/7] and [patch 7/7] I didn't see them...
--
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] 14+ messages in thread
* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-11 21:12 ` Jared Hulbert
@ 2008-03-11 23:21 ` Nick Piggin
0 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2008-03-11 23:21 UTC (permalink / raw)
To: Jared Hulbert
Cc: npiggin, Linus Torvalds, akpm, Carsten Otte, Martin Schwidefsky,
Heiko Carstens, linux-mm
On Wednesday 12 March 2008 08:12, Jared Hulbert wrote:
> > > (doh, please ignore the previous "x/6" patches, they're old. The
> > > new ones are these x/7 set)
> >
> > Ah shit and now I use the wrong address. Sorry. If you could take
> > it in your heart to correct it when you reply to me, I won't have
> > to mailbomb everyone again.
>
> is there a [patch 6/7] and [patch 7/7] I didn't see them...
Hmm, they were s390 patches that didn't get cc'ed to linux-mm, sorry.
They implement pte_special and struct page less XIP for s390, and
don't touch any core code.
--
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] 14+ messages in thread
* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-11 10:46 [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work npiggin
` (5 preceding siblings ...)
2008-03-11 11:44 ` [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work Nick Piggin
@ 2008-03-12 4:35 ` Andrew Morton
2008-03-12 5:33 ` Nick Piggin
2008-03-12 17:10 ` Jared Hulbert
6 siblings, 2 replies; 14+ messages in thread
From: Andrew Morton @ 2008-03-12 4:35 UTC (permalink / raw)
To: npiggin
Cc: Linus Torvalds, Jared Hulbert, Carsten Otte, Martin Schwidefsky,
Heiko Carstens, linux-mm
On Tue, 11 Mar 2008 21:46:53 +1100 npiggin@nick.local0.net wrote:
> --
>
> (doh, please ignore the previous "x/6" patches, they're old. The
> new ones are these x/7 set)
>
> Hi,
>
> I'm sorry for neglecting these patches for a few weeks :(
>
> I'd like to still get them into -mm and aim for the next merge window --
> they've been gradually getting a pretty reasonable amount of review and
> testing. I think the implementation of the pte_special path in vm_normal_page
> and vm_insert_mixed was the only point left unresolved since last time.
>
> I've included the dual kaddr/pfn API that we worked out with Jared, but
> he hasn't yet tested my patch rollup... so this is an RFC only. If we all
> agree on it, then I'll rebase to -mm and submit.
>
umm, could we have some executive summary about what this is all supposed
to achieve? I can see what each patch does, but what's the overall result?
[1/7] says:
> VM_MIXEDMAP achieves this by refcounting all pfn_valid pages, and not
> refcounting !pfn_valid pages (which is not an option for VM_PFNMAP, because
> it needs to avoid refcounting pfn_valid pages eg. for /dev/mem mappings).
I have this vague feeling that pfn_valid() isn't reliable - it can
sometimes lie, and that making it truthful was considered too expensive.
But maybe I'm thinking of something else?
--
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] 14+ messages in thread* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-12 4:35 ` Andrew Morton
@ 2008-03-12 5:33 ` Nick Piggin
2008-03-12 8:46 ` Martin Schwidefsky
2008-03-12 16:40 ` Jared Hulbert
2008-03-12 17:10 ` Jared Hulbert
1 sibling, 2 replies; 14+ messages in thread
From: Nick Piggin @ 2008-03-12 5:33 UTC (permalink / raw)
To: Andrew Morton
Cc: npiggin, Linus Torvalds, Jared Hulbert, Carsten Otte,
Martin Schwidefsky, Heiko Carstens, linux-mm
On Wednesday 12 March 2008 15:35, Andrew Morton wrote:
> On Tue, 11 Mar 2008 21:46:53 +1100 npiggin@nick.local0.net wrote:
> > --
> >
> > (doh, please ignore the previous "x/6" patches, they're old. The
> > new ones are these x/7 set)
> >
> > Hi,
> >
> > I'm sorry for neglecting these patches for a few weeks :(
> >
> > I'd like to still get them into -mm and aim for the next merge window --
> > they've been gradually getting a pretty reasonable amount of review and
> > testing. I think the implementation of the pte_special path in
> > vm_normal_page and vm_insert_mixed was the only point left unresolved
> > since last time.
> >
> > I've included the dual kaddr/pfn API that we worked out with Jared, but
> > he hasn't yet tested my patch rollup... so this is an RFC only. If we all
> > agree on it, then I'll rebase to -mm and submit.
>
> umm, could we have some executive summary about what this is all supposed
> to achieve? I can see what each patch does, but what's the overall result?
The overall result is that:
1. We now support XIP backed filesystems using memory that have no
struct page allocated to them. And patches 6 and 7 actually implement
this for s390.
This is pretty important in a number of cases. As far as I understand,
in the case of virtualisation (eg. s390), each guest may mount a
readonly copy of the same filesystem (eg. the distro). Currently,
guests need to allocate struct pages for this image. So if you have
100 guests, you already need to allocate more memory for the struct
pages than the size of the image. I think. (Carsten?)
For other (eg. embedded) systems, you may have a very large non-
volatile filesystem. If you have to have struct pages for this, then
your RAM consumption will go up proportionally to fs size. Even
though it is just a small proportion, RAM can be much more costly
eg in terms of power.
2. VM_MIXEDMAP allows us to support mappings where you actually do want
to refcount _some_ pages in the mapping, but not others. I haven't
actually seen his code, but I understand Jared requires this for his
filesystem that can migrate pages between RAM and XIP/NVRAM
transparently. Obviously the filesystem isn't finished yet, but
Jared is relying on these changes for it to work.
3. pte_special also has a peripheral usage that I need for my lockless
get_user_pages patch. That was shown to speed up "oltp" on db2 by
10% on a 2 socket system, which is kind of significant because they
scrounge for months to try to find 0.1% improvement on these
workloads. I'm hoping we might finally be faster than AIX on
pSeries with that patch. This is not meant to justify the whole
patchset of course, but just to show that pte_special is not some
s390 specific thing that should be hidden in arch code or xip code:
I want to use it on x86 and powerpc as well, and in that case I
need to use it for VM_PFNMAP not only VM_MIXEDMAP.
> [1/7] says:
> > VM_MIXEDMAP achieves this by refcounting all pfn_valid pages, and not
> > refcounting !pfn_valid pages (which is not an option for VM_PFNMAP,
> > because it needs to avoid refcounting pfn_valid pages eg. for /dev/mem
> > mappings).
>
> I have this vague feeling that pfn_valid() isn't reliable - it can
> sometimes lie, and that making it truthful was considered too expensive.
>
> But maybe I'm thinking of something else?
As far as I'm aware, if pfn_valid is true, then we can refcount the page.
This is the condition used by the page allocator to initialize the page
arrays, and should be the case if we're using one of the standard memory
models.
s390 is slightly different because it doesn't use a standard memory model
but something more dynamic. It doesn't quite do the right thing here, so
it uses pte_special. It could possibly tighten up pfn_valid, however I
think there are various reasons why they don't want to (one is that they
need to take a global lock in order to search their list of extents;
which will suck for VM_MIXEDMAP performance).
--
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] 14+ messages in thread
* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-12 5:33 ` Nick Piggin
@ 2008-03-12 8:46 ` Martin Schwidefsky
2008-03-12 16:40 ` Jared Hulbert
1 sibling, 0 replies; 14+ messages in thread
From: Martin Schwidefsky @ 2008-03-12 8:46 UTC (permalink / raw)
To: Nick Piggin
Cc: Andrew Morton, npiggin, Linus Torvalds, Jared Hulbert,
Carsten Otte, Heiko Carstens, linux-mm
On Wed, 2008-03-12 at 16:33 +1100, Nick Piggin wrote:
> s390 is slightly different because it doesn't use a standard memory model
> but something more dynamic. It doesn't quite do the right thing here, so
> it uses pte_special. It could possibly tighten up pfn_valid, however I
> think there are various reasons why they don't want to (one is that they
> need to take a global lock in order to search their list of extents;
> which will suck for VM_MIXEDMAP performance).
Indeed. Under z/VM we have mappable memory segments named DCSS that can
have different types. Dependend on the type we either want to do
refcounting (exclusive write for memory hotplug) or not (read-only
shared for memory sharing). pfn_valid() would have to scan the list of
DCCSes to find out which type the segment has. That is way too
expensive.
--
blue skies,
Martin.
"Reality continues to ruin my life." - Calvin.
--
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] 14+ messages in thread
* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-12 5:33 ` Nick Piggin
2008-03-12 8:46 ` Martin Schwidefsky
@ 2008-03-12 16:40 ` Jared Hulbert
1 sibling, 0 replies; 14+ messages in thread
From: Jared Hulbert @ 2008-03-12 16:40 UTC (permalink / raw)
To: Nick Piggin
Cc: Andrew Morton, npiggin, Linus Torvalds, Carsten Otte,
Martin Schwidefsky, Heiko Carstens, linux-mm
> 2. VM_MIXEDMAP allows us to support mappings where you actually do want
> to refcount _some_ pages in the mapping, but not others. I haven't
> actually seen his code, but I understand Jared requires this for his
> filesystem that can migrate pages between RAM and XIP/NVRAM
> transparently. Obviously the filesystem isn't finished yet, but
> Jared is relying on these changes for it to work.
So the filesystem I'm working on right now isn't that cool... It's
just a readonly XIP filesystem. But it does need VM_MIXEDMAP.
The problem was that VM_PFNMAP required pfn mapped pages to be
contiguous. My filesystem wants to allow a mixed of struct page and
pfn mapped pages within a given vma. VM_MIXEDMAP allows that to
happen.
But VM_MIXEDMAP is one of those foundation pieces that will allow us
to move on and do the cool migrate from RAM to NVM magic. You can't
transparently migrate pages when you are tied down to the VM_PFNMAP
rules. It'd be more like migrating vma chunks, yuck.
--
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] 14+ messages in thread
* Re: [patch 0/7] [rfc] VM_MIXEDMAP, pte_special, xip work
2008-03-12 4:35 ` Andrew Morton
2008-03-12 5:33 ` Nick Piggin
@ 2008-03-12 17:10 ` Jared Hulbert
1 sibling, 0 replies; 14+ messages in thread
From: Jared Hulbert @ 2008-03-12 17:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Linus Torvalds, Carsten Otte, Martin Schwidefsky, Heiko Carstens,
linux-mm, Nick Piggin
> umm, could we have some executive summary about what this is all supposed
> to achieve? I can see what each patch does, but what's the overall result?
We talked about this a couple years back at the Embedded Linux
Conference. In response to my whining about how ugly XIP hacks were
preventing me from merging my AXFS filesystem, you said, "We have an
XIP framework. Why don't you fix that?"
This is fixing the the XIP framework.
The old XIP framework just didn't work for embedded, mostly because it
was page based. Nick decided to help and proposed a way to rework the
XIP framework to be pfn based instead of page based. It turns out the
s390 guys (creators and only users of the XIP framework) prefer the
pfn based scheme. Now the creators and only users of the XIP
framework are excited about the very changes which allow the framework
to be used by us deviant embedded types. Everyone is happy!
--
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] 14+ messages in thread