2008-03-12 17:34:45

by Martin Schwidefsky

[permalink] [raw]
Subject: [patch 09/10] Hugetlb common code update for System z.

From: Gerald Schaefer <[email protected]>

Huge ptes have a special type on s390 and cannot be handled with the
standard pte functions in certain cases. This patch adds some new
architecture-specific definitions and functions to hugetlb common code,
as a prerequisite for the System z large page support. They won't
affect other architectures.

Signed-off-by: Gerald Schaefer <[email protected]>
Signed-off-by: Martin Schwidefsky <[email protected]>
---

include/linux/hugetlb.h | 18 ++++++++++++++++++
mm/hugetlb.c | 36 +++++++++++++++++++++---------------
2 files changed, 39 insertions(+), 15 deletions(-)

Index: quilt-2.6/include/linux/hugetlb.h
===================================================================
--- quilt-2.6.orig/include/linux/hugetlb.h
+++ quilt-2.6/include/linux/hugetlb.h
@@ -80,6 +80,24 @@ static inline int prepare_hugepage_range
int prepare_hugepage_range(unsigned long addr, unsigned long len);
#endif

+#ifndef ARCH_HAS_HUGE_PTE_TYPE
+#define huge_pte_none(pte) pte_none(pte)
+#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
+#define huge_ptep_set_wrprotect(mm, addr, ptep) \
+ ptep_set_wrprotect(mm, addr, ptep)
+#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
+ ptep_set_access_flags(vma, addr, ptep, pte, dirty)
+#define huge_ptep_get(ptep) (*ptep)
+#endif
+
+#ifndef ARCH_HAS_PREPARE_HUGEPAGE
+#define arch_prepare_hugepage(page) 0
+#define arch_release_hugepage(page) do { } while (0)
+#else
+int arch_prepare_hugepage(struct page *page);
+void arch_release_hugepage(struct page *page);
+#endif
+
#ifndef ARCH_HAS_HUGEPAGE_CLEAR_FLUSH
#define huge_ptep_clear_flush(vma, addr, ptep) do { } while (0)
#endif
Index: quilt-2.6/mm/hugetlb.c
===================================================================
--- quilt-2.6.orig/mm/hugetlb.c
+++ quilt-2.6/mm/hugetlb.c
@@ -129,6 +129,7 @@ static void update_and_free_page(struct
}
set_compound_page_dtor(page, NULL);
set_page_refcounted(page);
+ arch_release_hugepage(page);
__free_pages(page, HUGETLB_PAGE_ORDER);
}

@@ -198,6 +199,10 @@ static struct page *alloc_fresh_huge_pag
htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|__GFP_NOWARN,
HUGETLB_PAGE_ORDER);
if (page) {
+ if (arch_prepare_hugepage(page)) {
+ __free_pages(page, HUGETLB_PAGE_ORDER);
+ return 0;
+ }
set_compound_page_dtor(page, free_huge_page);
spin_lock(&hugetlb_lock);
nr_huge_pages++;
@@ -707,7 +712,7 @@ static pte_t make_huge_pte(struct vm_are
entry =
pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
} else {
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+ entry = huge_pte_wrprotect(mk_pte(page, vma->vm_page_prot));
}
entry = pte_mkyoung(entry);
entry = pte_mkhuge(entry);
@@ -720,8 +725,8 @@ static void set_huge_ptep_writable(struc
{
pte_t entry;

- entry = pte_mkwrite(pte_mkdirty(*ptep));
- if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+ entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep)));
+ if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) {
update_mmu_cache(vma, address, entry);
}
}
@@ -751,10 +756,10 @@ int copy_hugetlb_page_range(struct mm_st

spin_lock(&dst->page_table_lock);
spin_lock(&src->page_table_lock);
- if (!pte_none(*src_pte)) {
+ if (!huge_pte_none(huge_ptep_get(src_pte))) {
if (cow)
- ptep_set_wrprotect(src, addr, src_pte);
- entry = *src_pte;
+ huge_ptep_set_wrprotect(src, addr, src_pte);
+ entry = huge_ptep_get(src_pte);
ptepage = pte_page(entry);
get_page(ptepage);
set_huge_pte_at(dst, addr, dst_pte, entry);
@@ -798,7 +803,7 @@ void __unmap_hugepage_range(struct vm_ar
continue;

pte = huge_ptep_get_and_clear(mm, address, ptep);
- if (pte_none(pte))
+ if (huge_pte_none(pte))
continue;

page = pte_page(pte);
@@ -862,7 +867,7 @@ static int hugetlb_cow(struct mm_struct
spin_lock(&mm->page_table_lock);

ptep = huge_pte_offset(mm, address & HPAGE_MASK);
- if (likely(pte_same(*ptep, pte))) {
+ if (likely(pte_same(huge_ptep_get(ptep), pte))) {
/* Break COW */
huge_ptep_clear_flush(vma, address, ptep);
set_huge_pte_at(mm, address, ptep,
@@ -932,7 +937,7 @@ retry:
goto backout;

ret = 0;
- if (!pte_none(*ptep))
+ if (!huge_pte_none(huge_ptep_get(ptep)))
goto backout;

new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
@@ -974,8 +979,8 @@ int hugetlb_fault(struct mm_struct *mm,
* the same page in the page cache.
*/
mutex_lock(&hugetlb_instantiation_mutex);
- entry = *ptep;
- if (pte_none(entry)) {
+ entry = huge_ptep_get(ptep);
+ if (huge_pte_none(entry)) {
ret = hugetlb_no_page(mm, vma, address, ptep, write_access);
mutex_unlock(&hugetlb_instantiation_mutex);
return ret;
@@ -985,7 +990,7 @@ int hugetlb_fault(struct mm_struct *mm,

spin_lock(&mm->page_table_lock);
/* Check for a racing update before calling hugetlb_cow */
- if (likely(pte_same(entry, *ptep)))
+ if (likely(pte_same(entry, huge_ptep_get(ptep))))
if (write_access && !pte_write(entry))
ret = hugetlb_cow(mm, vma, address, ptep, entry);
spin_unlock(&mm->page_table_lock);
@@ -1015,7 +1020,8 @@ int follow_hugetlb_page(struct mm_struct
*/
pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);

- if (!pte || pte_none(*pte) || (write && !pte_write(*pte))) {
+ if (!pte || huge_pte_none(huge_ptep_get(pte)) ||
+ (write && !pte_write(huge_ptep_get(pte)))) {
int ret;

spin_unlock(&mm->page_table_lock);
@@ -1031,7 +1037,7 @@ int follow_hugetlb_page(struct mm_struct
}

pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
- page = pte_page(*pte);
+ page = pte_page(huge_ptep_get(pte));
same_page:
if (pages) {
get_page(page);
@@ -1080,7 +1086,7 @@ void hugetlb_change_protection(struct vm
continue;
if (huge_pmd_unshare(mm, &address, ptep))
continue;
- if (!pte_none(*ptep)) {
+ if (!huge_pte_none(huge_ptep_get(ptep))) {
pte = huge_ptep_get_and_clear(mm, address, ptep);
pte = pte_mkhuge(pte_modify(pte, newprot));
set_huge_pte_at(mm, address, ptep, pte);

--
blue skies,
Martin.

"Reality continues to ruin my life." - Calvin.


2008-03-12 17:51:53

by Dave Hansen

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Wed, 2008-03-12 at 18:32 +0100, Martin Schwidefsky wrote:
> +#ifndef ARCH_HAS_HUGE_PTE_TYPE
> +#define huge_pte_none(pte) pte_none(pte)
> +#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
> +#define huge_ptep_set_wrprotect(mm, addr, ptep) \
> + ptep_set_wrprotect(mm, addr, ptep)
> +#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
> + ptep_set_access_flags(vma, addr, ptep, pte, dirty)
> +#define huge_ptep_get(ptep) (*ptep)
> +#endif
> +
> +#ifndef ARCH_HAS_PREPARE_HUGEPAGE

Can you guys please do these defines in Kconfig instead of headers? I
find them much easier to track down when I have one place to look,
rather than a mess of 14 other #includes in a arch-specific header. :)

I'm also a little concerned that you just #ifdef'd in about 44 new ptep
functions in here. Have you carefully considered doing this in a way
that would fit in better with the other architectures?

> Huge ptes have a special type on s390 and cannot be handled with the
> standard pte functions in certain cases.

Can you elaborate a bit more on that?

-- Dave

2008-03-12 23:17:36

by Gerald Schaefer

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Wed, 2008-03-12 at 10:51 -0700, Dave Hansen wrote:
> > +#ifndef ARCH_HAS_HUGE_PTE_TYPE
> > +#define huge_pte_none(pte) pte_none(pte)
> > +#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
> > +#define huge_ptep_set_wrprotect(mm, addr, ptep) \
> > + ptep_set_wrprotect(mm, addr, ptep)
> > +#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
> > + ptep_set_access_flags(vma, addr, ptep, pte, dirty)
> > +#define huge_ptep_get(ptep) (*ptep)
> > +#endif
> > +
> > +#ifndef ARCH_HAS_PREPARE_HUGEPAGE
>
> Can you guys please do these defines in Kconfig instead of headers? I
> find them much easier to track down when I have one place to look,
> rather than a mess of 14 other #includes in a arch-specific header. :)

There are already several ARCH_HAS_xxx defines which are being used in
inlude/linux/hugetlb.h. All of them are defined in
include/asm-<arch>/page.h for every architecture that needs them (with
the exception of powerpc, where it is include/asm-powerpc/page_64.h).
So there is already one place to look for them, and so we put our
defines into include/asm-s390/page.h.

> I'm also a little concerned that you just #ifdef'd in about 44 new ptep
> functions in here. Have you carefully considered doing this in a way
> that would fit in better with the other architectures?

Other architectures should not be affected at all. Because of the
#ifdef, the new ptep functions are either a nop for them or just the
same as they were before our patch.

> > Huge ptes have a special type on s390 and cannot be handled with the
> > standard pte functions in certain cases.
>
> Can you elaborate a bit more on that?

Large ptes are not really ptes but segment table entries (pmd entries),
in our case. This is similar to other architectures with hardware large
page support, because there simply is no page table level (and thus no
ptes) anymore. Unfortunately, the hugetlbfs common code does not
consider that discrepancy and just uses a standard pte_t and standard
pte functions, probably because it did not really make a difference on
other architectures.

On s390, a segment table entry (pmd) type is different from a pte type
mainly in the location of its invalid bit. This means that we cannot
use pte_none(), pte_wrprotect() and similar functions for large ptes,
which was the reason for the new huge_pte functions that we introduced.

--
Gerald Schaefer

2008-03-12 23:48:51

by Andrew Morton

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Thu, 13 Mar 2008 00:18:57 +0100
Gerald Schaefer <[email protected]> wrote:

> On Wed, 2008-03-12 at 10:51 -0700, Dave Hansen wrote:
> > > +#ifndef ARCH_HAS_HUGE_PTE_TYPE
> > > +#define huge_pte_none(pte) pte_none(pte)
> > > +#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
> > > +#define huge_ptep_set_wrprotect(mm, addr, ptep) \
> > > + ptep_set_wrprotect(mm, addr, ptep)
> > > +#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
> > > + ptep_set_access_flags(vma, addr, ptep, pte, dirty)
> > > +#define huge_ptep_get(ptep) (*ptep)
> > > +#endif
> > > +
> > > +#ifndef ARCH_HAS_PREPARE_HUGEPAGE
> >
> > Can you guys please do these defines in Kconfig instead of headers? I
> > find them much easier to track down when I have one place to look,
> > rather than a mess of 14 other #includes in a arch-specific header. :)
>
> There are already several ARCH_HAS_xxx defines which are being used in
> inlude/linux/hugetlb.h. All of them are defined in
> include/asm-<arch>/page.h for every architecture that needs them (with
> the exception of powerpc, where it is include/asm-powerpc/page_64.h).

Yes, but that's fugly and it would be better to put in place the
infrastructure for cleaning it up, rather than worsening it.

So...

Put this:

+#define huge_pte_none(pte) pte_none(pte)
+#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
+#define huge_ptep_set_wrprotect(mm, addr, ptep) \
+ ptep_set_wrprotect(mm, addr, ptep)
+#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
+ ptep_set_access_flags(vma, addr, ptep, pte, dirty)
+#define huge_ptep_get(ptep) (*ptep)

into include/asm-generic/hugetlb.h

then for each architecture except s390 add an include/asm-foo/hugetlb.h
which does

#include <asm-generic/hugetlb.h>

then in include/linux/hugetlb.h add

#include <asm/hugetlb.h>

and then in include/asm-s390/hugetlb.h, add your s390-specific versions of
huge_pte_none() and friends.

later, someone can hopefully use this new infrastructure to rid us of
ARCH_HAS_HUGEPAGE_ONLY_RANGE, ARCH_HAS_HUGETLB_FREE_PGD_RANGE,
ARCH_HAS_PREPARE_HUGEPAGE_RANGE, ARCH_HAS_SETCLEAR_HUGE_PTE and
ARCH_HAS_HUGETLB_PREFAULT_HOOK.

2008-03-13 17:50:32

by Gerald Schaefer

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Wed, 2008-03-12 at 16:43 -0700, Andrew Morton wrote:
> Yes, but that's fugly and it would be better to put in place the
> infrastructure for cleaning it up, rather than worsening it.
>
> So...

OK, we'll start the clean-up, thanks for the detailed suggestions.

--
Gerald Schaefer

2008-03-28 14:03:41

by Gerald Schaefer

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Wed, 2008-03-12 at 16:43 -0700, Andrew Morton wrote:
> > There are already several ARCH_HAS_xxx defines which are being used in
> > inlude/linux/hugetlb.h. All of them are defined in
> > include/asm-<arch>/page.h for every architecture that needs them (with
> > the exception of powerpc, where it is include/asm-powerpc/page_64.h).
>
> Yes, but that's fugly and it would be better to put in place the
> infrastructure for cleaning it up, rather than worsening it.
>
> So...
>
> Put this:
>
> +#define huge_pte_none(pte) pte_none(pte)
> +#define huge_pte_wrprotect(pte) pte_wrprotect(pte)
> +#define huge_ptep_set_wrprotect(mm, addr, ptep) \
> + ptep_set_wrprotect(mm, addr, ptep)
> +#define huge_ptep_set_access_flags(vma, addr, ptep, pte, dirty) \
> + ptep_set_access_flags(vma, addr, ptep, pte, dirty)
> +#define huge_ptep_get(ptep) (*ptep)
>
> into include/asm-generic/hugetlb.h
>
> then for each architecture except s390 add an include/asm-foo/hugetlb.h
> which does
>
> #include <asm-generic/hugetlb.h>
>
> then in include/linux/hugetlb.h add
>
> #include <asm/hugetlb.h>
>
> and then in include/asm-s390/hugetlb.h, add your s390-specific versions of
> huge_pte_none() and friends.
>
> later, someone can hopefully use this new infrastructure to rid us of
> ARCH_HAS_HUGEPAGE_ONLY_RANGE, ARCH_HAS_HUGETLB_FREE_PGD_RANGE,
> ARCH_HAS_PREPARE_HUGEPAGE_RANGE, ARCH_HAS_SETCLEAR_HUGE_PTE and
> ARCH_HAS_HUGETLB_PREFAULT_HOOK.

This patch moves all architecture functions for hugetlb to architecture
header files (include/asm-foo/hugetlb.h). It also removes (!)
ARCH_HAS_HUGEPAGE_ONLY_RANGE, ARCH_HAS_HUGETLB_FREE_PGD_RANGE,
ARCH_HAS_PREPARE_HUGEPAGE_RANGE, ARCH_HAS_SETCLEAR_HUGE_PTE and
ARCH_HAS_HUGETLB_PREFAULT_HOOK.

Cross-Compile tests on the affected architectures (and one unaffected)
worked fine, but I had no cross-compiler for sh.

If this patch is accepted, we will resend the s390 large page patches
so that they will use/extend this new infrastructure.

--
Gerald Schaefer

---
include/asm-ia64/hugetlb.h | 21 +++++++++++++++++++
include/asm-ia64/page.h | 6 -----
include/asm-powerpc/hugetlb.h | 35 +++++++++++++++++++++++++++++++
include/asm-powerpc/page_64.h | 7 ------
include/asm-sh/hugetlb.h | 28 +++++++++++++++++++++++++
include/asm-sparc64/hugetlb.h | 30 +++++++++++++++++++++++++++
include/asm-sparc64/page.h | 2 -
include/asm-x86/hugetlb.h | 28 +++++++++++++++++++++++++
include/linux/hugetlb.h | 46 ------------------------------------------
9 files changed, 143 insertions(+), 60 deletions(-)

Index: linux-2.6.25-rc7/include/asm-ia64/hugetlb.h
===================================================================
--- /dev/null
+++ linux-2.6.25-rc7/include/asm-ia64/hugetlb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_IA64_HUGETLB_H
+#define _ASM_IA64_HUGETLB_H
+
+#include <asm/page.h>
+
+
+#define is_hugepage_only_range(mm, addr, len) \
+ (REGION_NUMBER(addr) == RGN_HPAGE || \
+ REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
+
+void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+ unsigned long end, unsigned long floor,
+ unsigned long ceiling);
+int prepare_hugepage_range(unsigned long addr, unsigned long len);
+
+#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+
+#endif /* _ASM_IA64_HUGETLB_H */
Index: linux-2.6.25-rc7/include/asm-sh/hugetlb.h
===================================================================
--- /dev/null
+++ linux-2.6.25-rc7/include/asm-sh/hugetlb.h
@@ -0,0 +1,28 @@
+#ifndef _ASM_SH_HUGETLB_H
+#define _ASM_SH_HUGETLB_H
+
+#include <asm/page.h>
+
+
+#define is_hugepage_only_range(mm, addr, len) 0
+#define hugetlb_free_pgd_range free_pgd_range
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+
+#endif /* _ASM_SH_HUGETLB_H */
Index: linux-2.6.25-rc7/include/asm-sparc64/hugetlb.h
===================================================================
--- /dev/null
+++ linux-2.6.25-rc7/include/asm-sparc64/hugetlb.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_SPARC64_HUGETLB_H
+#define _ASM_SPARC64_HUGETLB_H
+
+#include <asm/page.h>
+
+
+#define is_hugepage_only_range(mm, addr, len) 0
+#define hugetlb_free_pgd_range free_pgd_range
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep);
+
+void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+
+#endif /* _ASM_SPARC64_HUGETLB_H */
Index: linux-2.6.25-rc7/include/asm-x86/hugetlb.h
===================================================================
--- /dev/null
+++ linux-2.6.25-rc7/include/asm-x86/hugetlb.h
@@ -0,0 +1,28 @@
+#ifndef _ASM_X86_HUGETLB_H
+#define _ASM_X86_HUGETLB_H
+
+#include <asm/page.h>
+
+
+#define is_hugepage_only_range(mm, addr, len) 0
+#define hugetlb_free_pgd_range free_pgd_range
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+
+#endif /* _ASM_X86_HUGETLB_H */
Index: linux-2.6.25-rc7/include/linux/hugetlb.h
===================================================================
--- linux-2.6.25-rc7.orig/include/linux/hugetlb.h
+++ linux-2.6.25-rc7/include/linux/hugetlb.h
@@ -8,6 +8,7 @@
#include <linux/mempolicy.h>
#include <linux/shm.h>
#include <asm/tlbflush.h>
+#include <asm/hugetlb.h>

struct ctl_table;

@@ -51,51 +52,6 @@ int pmd_huge(pmd_t pmd);
void hugetlb_change_protection(struct vm_area_struct *vma,
unsigned long address, unsigned long end, pgprot_t newprot);

-#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
-#define is_hugepage_only_range(mm, addr, len) 0
-#endif
-
-#ifndef ARCH_HAS_HUGETLB_FREE_PGD_RANGE
-#define hugetlb_free_pgd_range free_pgd_range
-#else
-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
- unsigned long end, unsigned long floor,
- unsigned long ceiling);
-#endif
-
-#ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE
-/*
- * If the arch doesn't supply something else, assume that hugepage
- * size aligned regions are ok without further preparation.
- */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
-{
- if (len & ~HPAGE_MASK)
- return -EINVAL;
- if (addr & ~HPAGE_MASK)
- return -EINVAL;
- return 0;
-}
-#else
-int prepare_hugepage_range(unsigned long addr, unsigned long len);
-#endif
-
-#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
-#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
-#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
-#else
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte);
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep);
-#endif
-
-#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
-#define hugetlb_prefault_arch_hook(mm) do { } while (0)
-#else
-void hugetlb_prefault_arch_hook(struct mm_struct *mm);
-#endif
-
#else /* !CONFIG_HUGETLB_PAGE */

static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
Index: linux-2.6.25-rc7/include/asm-powerpc/hugetlb.h
===================================================================
--- /dev/null
+++ linux-2.6.25-rc7/include/asm-powerpc/hugetlb.h
@@ -0,0 +1,35 @@
+#ifndef _ASM_POWERPC_HUGETLB_H
+#define _ASM_POWERPC_HUGETLB_H
+
+#include <asm/page.h>
+
+
+extern int is_hugepage_only_range(struct mm_struct *m,
+ unsigned long addr,
+ unsigned long len);
+
+void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+ unsigned long end, unsigned long floor,
+ unsigned long ceiling);
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep);
+
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+
+#endif /* _ASM_POWERPC_HUGETLB_H */
Index: linux-2.6.25-rc7/include/asm-ia64/page.h
===================================================================
--- linux-2.6.25-rc7.orig/include/asm-ia64/page.h
+++ linux-2.6.25-rc7/include/asm-ia64/page.h
@@ -54,9 +54,6 @@
# define HPAGE_MASK (~(HPAGE_SIZE - 1))

# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-# define ARCH_HAS_HUGEPAGE_ONLY_RANGE
-# define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
-# define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
#endif /* CONFIG_HUGETLB_PAGE */

#ifdef __ASSEMBLY__
@@ -153,9 +150,6 @@ typedef union ia64_va {
# define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \
| (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-# define is_hugepage_only_range(mm, addr, len) \
- (REGION_NUMBER(addr) == RGN_HPAGE || \
- REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
extern unsigned int hpage_shift;
#endif

Index: linux-2.6.25-rc7/include/asm-powerpc/page_64.h
===================================================================
--- linux-2.6.25-rc7.orig/include/asm-powerpc/page_64.h
+++ linux-2.6.25-rc7/include/asm-powerpc/page_64.h
@@ -128,11 +128,6 @@ extern void slice_init_context(struct mm
extern void slice_set_user_psize(struct mm_struct *mm, unsigned int psize);
#define slice_mm_new_context(mm) ((mm)->context.id == 0)

-#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
-extern int is_hugepage_only_range(struct mm_struct *m,
- unsigned long addr,
- unsigned long len);
-
#endif /* __ASSEMBLY__ */
#else
#define slice_init()
@@ -146,8 +141,6 @@ do { \

#ifdef CONFIG_HUGETLB_PAGE

-#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
-#define ARCH_HAS_SETCLEAR_HUGE_PTE
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA

#endif /* !CONFIG_HUGETLB_PAGE */
Index: linux-2.6.25-rc7/include/asm-sparc64/page.h
===================================================================
--- linux-2.6.25-rc7.orig/include/asm-sparc64/page.h
+++ linux-2.6.25-rc7/include/asm-sparc64/page.h
@@ -39,8 +39,6 @@
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-#define ARCH_HAS_SETCLEAR_HUGE_PTE
-#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
#endif


2008-03-28 14:08:18

by Ingo Molnar

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.


* Gerald Schaefer <[email protected]> wrote:

> include/asm-sh/hugetlb.h | 28 +++++++++++++++++++++++++
> include/asm-sparc64/hugetlb.h | 30 +++++++++++++++++++++++++++
> include/asm-x86/hugetlb.h | 28 +++++++++++++++++++++++++

these seem largely duplicated - shouldnt there be an
asm-generic/hugetlb.h instead, which asm/hugetlb.h could include to get
default behavior? It would probably reduce the linecount of your patch
as well.

Ingo

2008-03-28 14:31:51

by Gerald Schaefer

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Fri, 2008-03-28 at 15:06 +0100, Ingo Molnar wrote:
> * Gerald Schaefer <[email protected]> wrote:
>
> > include/asm-sh/hugetlb.h | 28 +++++++++++++++++++++++++
> > include/asm-sparc64/hugetlb.h | 30 +++++++++++++++++++++++++++
> > include/asm-x86/hugetlb.h | 28 +++++++++++++++++++++++++
>
> these seem largely duplicated - shouldnt there be an
> asm-generic/hugetlb.h instead, which asm/hugetlb.h could include to get
> default behavior? It would probably reduce the linecount of your patch
> as well.

Right, asm-generic was also suggested by Andrew as a first step, before
getting rid of the ARCH_HAS_xxx stuff, and it would also reduce the loc.
But it would make things complicated if one architecture later wants to
take out some of the generic stuff to define it on their own, then they'd
need to touch all architecture headers again.

So I thought I'd rather not introduce the asm-generic header at all but
let all architectures have their own headers, risking code duplication
but hopefully making future updates easier.

--
Gerald Schaefer

2008-03-28 15:54:17

by Martin Schwidefsky

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.

On Fri, 2008-03-28 at 15:06 +0100, Ingo Molnar wrote:
> * Gerald Schaefer <[email protected]> wrote:
>
> > include/asm-sh/hugetlb.h | 28 +++++++++++++++++++++++++
> > include/asm-sparc64/hugetlb.h | 30 +++++++++++++++++++++++++++
> > include/asm-x86/hugetlb.h | 28 +++++++++++++++++++++++++
>
> these seem largely duplicated - shouldnt there be an
> asm-generic/hugetlb.h instead, which asm/hugetlb.h could include to get
> default behavior? It would probably reduce the linecount of your patch
> as well.

Well the hugetlbfs primitives are architecture specific, aren't they?
Just like the other page table manipulation functions. I find the usual
method to use asm-generic/<xxx> and a lot of defines and #ifdefs to pick
up the correct definition from a generic header file rather hard to
read. In the end each arch that wants to use hugetlbfs has to define
each of the hugetlb primitives. Most of them are rather simple, e.g. the
x86 set_huge_pte_at is just a set_pte_at. One line to define the
primitive. Now we could have an #ifdef block around the default
definition that maps set_huge_pte_at to set_pte_at in asm-generic and an
ARCH_HAS_xx override for architecture that need to do something more
complicated. Somehow that was where we started ..
I think the best way to get rid of the ARCH_HAS_xxx fugliness is to let
each architecture define their primitives, even if it looks like code
duplication.

--
blue skies,
Martin.

"Reality continues to ruin my life." - Calvin.

2008-03-28 16:04:22

by Ingo Molnar

[permalink] [raw]
Subject: Re: [patch 09/10] Hugetlb common code update for System z.


* Martin Schwidefsky <[email protected]> wrote:

> > > include/asm-sh/hugetlb.h | 28 +++++++++++++++++++++++++
> > > include/asm-sparc64/hugetlb.h | 30 +++++++++++++++++++++++++++
> > > include/asm-x86/hugetlb.h | 28 +++++++++++++++++++++++++
> >
> > these seem largely duplicated - shouldnt there be an
> > asm-generic/hugetlb.h instead, which asm/hugetlb.h could include to
> > get default behavior? It would probably reduce the linecount of your
> > patch as well.
>
> Well the hugetlbfs primitives are architecture specific, aren't they?
> Just like the other page table manipulation functions. I find the
> usual method to use asm-generic/<xxx> and a lot of defines and #ifdefs
> to pick up the correct definition from a generic header file rather
> hard to read. In the end each arch that wants to use hugetlbfs has to
> define each of the hugetlb primitives. Most of them are rather simple,
> e.g. the x86 set_huge_pte_at is just a set_pte_at. One line to define
> the primitive. Now we could have an #ifdef block around the default
> definition that maps set_huge_pte_at to set_pte_at in asm-generic and
> an ARCH_HAS_xx override for architecture that need to do something
> more complicated. Somehow that was where we started .. I think the
> best way to get rid of the ARCH_HAS_xxx fugliness is to let each
> architecture define their primitives, even if it looks like code
> duplication.

sorry, i misread your patch - it indeed looks cleaner with your patch
applied.

Ingo