* [RFC PATCH 1/9] mm: hugetlb: Copy huge_pmd_share from x86 to mm.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` [RFC PATCH 2/9] x86: mm: Remove x86 version of huge_pmd_share Steve Capper
` (7 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
Under x86, multiple puds can be made to reference the same bank of
huge pmds provided that they represent a full PUD_SIZE of shared
huge memory that is aligned to a PUD_SIZE boundary.
The code to share pmds does not require any architecture specific
knowledge other than the fact that pmds can be indexed, thus can
be beneficial to some other architectures.
This patch copies the huge pmd sharing (and unsharing) logic from
x86/ to mm/ and introduces a new config option to activate it:
CONFIG_ARCH_WANTS_HUGE_PMD_SHARE
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
include/linux/hugetlb.h | 4 ++
mm/hugetlb.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 16e4e9a..795c32d 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -68,6 +68,10 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
int dequeue_hwpoisoned_huge_page(struct page *page);
void copy_huge_page(struct page *dst, struct page *src);
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud);
+#endif
+
extern unsigned long hugepages_treat_as_movable;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ca9a7c6..41179b0 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3142,6 +3142,128 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
hugetlb_acct_memory(h, -(chg - freed));
}
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+static unsigned long page_table_shareable(struct vm_area_struct *svma,
+ struct vm_area_struct *vma,
+ unsigned long addr, pgoff_t idx)
+{
+ unsigned long saddr = ((idx - svma->vm_pgoff) << PAGE_SHIFT) +
+ svma->vm_start;
+ unsigned long sbase = saddr & PUD_MASK;
+ unsigned long s_end = sbase + PUD_SIZE;
+
+ /* Allow segments to share if only one is marked locked */
+ unsigned long vm_flags = vma->vm_flags & ~VM_LOCKED;
+ unsigned long svm_flags = svma->vm_flags & ~VM_LOCKED;
+
+ /*
+ * match the virtual addresses, permission and the alignment of the
+ * page table page.
+ */
+ if (pmd_index(addr) != pmd_index(saddr) ||
+ vm_flags != svm_flags ||
+ sbase < svma->vm_start || svma->vm_end < s_end)
+ return 0;
+
+ return saddr;
+}
+
+static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
+{
+ unsigned long base = addr & PUD_MASK;
+ unsigned long end = base + PUD_SIZE;
+
+ /*
+ * check on proper vm_flags and page table alignment
+ */
+ if (vma->vm_flags & VM_MAYSHARE &&
+ vma->vm_start <= base && end <= vma->vm_end)
+ return 1;
+ return 0;
+}
+
+/*
+ * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
+ * and returns the corresponding pte. While this is not necessary for the
+ * !shared pmd case because we can allocate the pmd later as well, it makes the
+ * code much cleaner. pmd allocation is essential for the shared case because
+ * pud has to be populated inside the same i_mmap_mutex section - otherwise
+ * racing tasks could either miss the sharing (see huge_pte_offset) or select a
+ * bad pmd for sharing.
+ */
+pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+{
+ struct vm_area_struct *vma = find_vma(mm, addr);
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) +
+ vma->vm_pgoff;
+ struct vm_area_struct *svma;
+ unsigned long saddr;
+ pte_t *spte = NULL;
+ pte_t *pte;
+
+ if (!vma_shareable(vma, addr))
+ return (pte_t *)pmd_alloc(mm, pud, addr);
+
+ mutex_lock(&mapping->i_mmap_mutex);
+ vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
+ if (svma == vma)
+ continue;
+
+ saddr = page_table_shareable(svma, vma, addr, idx);
+ if (saddr) {
+ spte = huge_pte_offset(svma->vm_mm, saddr);
+ if (spte) {
+ get_page(virt_to_page(spte));
+ break;
+ }
+ }
+ }
+
+ if (!spte)
+ goto out;
+
+ spin_lock(&mm->page_table_lock);
+ if (pud_none(*pud))
+ pud_populate(mm, pud,
+ (pmd_t *)((unsigned long)spte & PAGE_MASK));
+ else
+ put_page(virt_to_page(spte));
+ spin_unlock(&mm->page_table_lock);
+out:
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
+ mutex_unlock(&mapping->i_mmap_mutex);
+ return pte;
+}
+
+/*
+ * unmap huge page backed by shared pte.
+ *
+ * Hugetlb pte page is ref counted at the time of mapping. If pte is shared
+ * indicated by page_count > 1, unmap is achieved by clearing pud and
+ * decrementing the ref count. If count == 1, the pte page is not shared.
+ *
+ * called with vma->vm_mm->page_table_lock held.
+ *
+ * returns: 1 successfully unmapped a shared pte page
+ * 0 the underlying pte page is not shared, or it is the last user
+ */
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ pgd_t *pgd = pgd_offset(mm, *addr);
+ pud_t *pud = pud_offset(pgd, *addr);
+
+ BUG_ON(page_count(virt_to_page(ptep)) == 0);
+ if (page_count(virt_to_page(ptep)) == 1)
+ return 0;
+
+ pud_clear(pud);
+ put_page(virt_to_page(ptep));
+ *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
+ return 1;
+}
+#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
+
#ifdef CONFIG_MEMORY_FAILURE
/* Should be called in hugetlb_lock */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [RFC PATCH 2/9] x86: mm: Remove x86 version of huge_pmd_share.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
2013-04-30 16:30 ` [RFC PATCH 1/9] mm: hugetlb: Copy huge_pmd_share from x86 to mm Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm Steve Capper
` (6 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The huge_pmd_share code has been copied over to mm/hugetlb.c to
make it accessible to other architectures.
Remove the x86 copy of the huge_pmd_share code and enable the
ARCH_WANT_HUGE_PMD_SHARE config flag. That way we reference the
general one.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/x86/Kconfig | 3 ++
arch/x86/mm/hugetlbpage.c | 120 ----------------------------------------------
2 files changed, 3 insertions(+), 120 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70c0f3d..60e3c402 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -212,6 +212,9 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
+config ARCH_WANT_HUGE_PMD_SHARE
+ def_bool y
+
config ZONE_DMA32
bool
default X86_64
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index ae1aa71..7e522a3 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -16,126 +16,6 @@
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>
-static unsigned long page_table_shareable(struct vm_area_struct *svma,
- struct vm_area_struct *vma,
- unsigned long addr, pgoff_t idx)
-{
- unsigned long saddr = ((idx - svma->vm_pgoff) << PAGE_SHIFT) +
- svma->vm_start;
- unsigned long sbase = saddr & PUD_MASK;
- unsigned long s_end = sbase + PUD_SIZE;
-
- /* Allow segments to share if only one is marked locked */
- unsigned long vm_flags = vma->vm_flags & ~VM_LOCKED;
- unsigned long svm_flags = svma->vm_flags & ~VM_LOCKED;
-
- /*
- * match the virtual addresses, permission and the alignment of the
- * page table page.
- */
- if (pmd_index(addr) != pmd_index(saddr) ||
- vm_flags != svm_flags ||
- sbase < svma->vm_start || svma->vm_end < s_end)
- return 0;
-
- return saddr;
-}
-
-static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
-{
- unsigned long base = addr & PUD_MASK;
- unsigned long end = base + PUD_SIZE;
-
- /*
- * check on proper vm_flags and page table alignment
- */
- if (vma->vm_flags & VM_MAYSHARE &&
- vma->vm_start <= base && end <= vma->vm_end)
- return 1;
- return 0;
-}
-
-/*
- * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
- * and returns the corresponding pte. While this is not necessary for the
- * !shared pmd case because we can allocate the pmd later as well, it makes the
- * code much cleaner. pmd allocation is essential for the shared case because
- * pud has to be populated inside the same i_mmap_mutex section - otherwise
- * racing tasks could either miss the sharing (see huge_pte_offset) or select a
- * bad pmd for sharing.
- */
-static pte_t *
-huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
-{
- struct vm_area_struct *vma = find_vma(mm, addr);
- struct address_space *mapping = vma->vm_file->f_mapping;
- pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) +
- vma->vm_pgoff;
- struct vm_area_struct *svma;
- unsigned long saddr;
- pte_t *spte = NULL;
- pte_t *pte;
-
- if (!vma_shareable(vma, addr))
- return (pte_t *)pmd_alloc(mm, pud, addr);
-
- mutex_lock(&mapping->i_mmap_mutex);
- vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
- if (svma == vma)
- continue;
-
- saddr = page_table_shareable(svma, vma, addr, idx);
- if (saddr) {
- spte = huge_pte_offset(svma->vm_mm, saddr);
- if (spte) {
- get_page(virt_to_page(spte));
- break;
- }
- }
- }
-
- if (!spte)
- goto out;
-
- spin_lock(&mm->page_table_lock);
- if (pud_none(*pud))
- pud_populate(mm, pud, (pmd_t *)((unsigned long)spte & PAGE_MASK));
- else
- put_page(virt_to_page(spte));
- spin_unlock(&mm->page_table_lock);
-out:
- pte = (pte_t *)pmd_alloc(mm, pud, addr);
- mutex_unlock(&mapping->i_mmap_mutex);
- return pte;
-}
-
-/*
- * unmap huge page backed by shared pte.
- *
- * Hugetlb pte page is ref counted at the time of mapping. If pte is shared
- * indicated by page_count > 1, unmap is achieved by clearing pud and
- * decrementing the ref count. If count == 1, the pte page is not shared.
- *
- * called with vma->vm_mm->page_table_lock held.
- *
- * returns: 1 successfully unmapped a shared pte page
- * 0 the underlying pte page is not shared, or it is the last user
- */
-int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
-{
- pgd_t *pgd = pgd_offset(mm, *addr);
- pud_t *pud = pud_offset(pgd, *addr);
-
- BUG_ON(page_count(virt_to_page(ptep)) == 0);
- if (page_count(virt_to_page(ptep)) == 1)
- return 0;
-
- pud_clear(pud);
- put_page(virt_to_page(ptep));
- *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
- return 1;
-}
-
pte_t *huge_pte_alloc(struct mm_struct *mm,
unsigned long addr, unsigned long sz)
{
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
2013-04-30 16:30 ` [RFC PATCH 1/9] mm: hugetlb: Copy huge_pmd_share from x86 to mm Steve Capper
2013-04-30 16:30 ` [RFC PATCH 2/9] x86: mm: Remove x86 version of huge_pmd_share Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` Steve Capper
2013-04-30 16:48 ` Catalin Marinas
2013-04-30 16:30 ` [RFC PATCH 4/9] x86: mm: Remove general hugetlb code from x86 Steve Capper
` (5 subsequent siblings)
8 siblings, 2 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The huge_pte_alloc, huge_pte_offset and follow_huge_p[mu]d
functions in x86/mm/hugetlbpage.c do not rely on any architecture
specific knowledge other than the fact that pmds and puds can be
treated as huge ptes.
To allow other architectures to use this code (and reduce the need
for code duplication), this patch copies these functions into mm
and provides a config flag to activate them:
CONFIG_ARCH_WANT_GENERAL_HUGETLB
If CONFIG_ARCH_WANT_HUGE_PMD_SHARE is also active then the
huge_pmd_share code will be called by huge_pte_alloc (othewise we
call pmd_alloc and skip the sharing code).
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
mm/hugetlb.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 88 insertions(+), 9 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 41179b0..e1dc5ae 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2915,15 +2915,6 @@ out_mutex:
return ret;
}
-/* Can be overriden by architectures */
-__attribute__((weak)) struct page *
-follow_huge_pud(struct mm_struct *mm, unsigned long address,
- pud_t *pud, int write)
-{
- BUG();
- return NULL;
-}
-
long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
unsigned long *position, unsigned long *nr_pages,
@@ -3262,8 +3253,96 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
*addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
return 1;
}
+#define want_pmd_share() (1)
+#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
+pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+{
+ return NULL;
+}
+#define want_pmd_share() (0)
#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
+#ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ pud = pud_alloc(mm, pgd, addr);
+ if (pud) {
+ if (sz == PUD_SIZE) {
+ pte = (pte_t *)pud;
+ } else {
+ BUG_ON(sz != PMD_SIZE);
+ if (want_pmd_share() && pud_none(*pud))
+ pte = huge_pmd_share(mm, addr, pud);
+ else
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
+ }
+ }
+ BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
+
+ return pte;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd_present(*pgd)) {
+ pud = pud_offset(pgd, addr);
+ if (pud_present(*pud)) {
+ if (pud_large(*pud))
+ return (pte_t *)pud;
+ pmd = pmd_offset(pud, addr);
+ }
+ }
+ return (pte_t *) pmd;
+}
+
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pmd);
+ if (page)
+ page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pud);
+ if (page)
+ page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+#else /* !CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+
+/* Can be overriden by architectures */
+__attribute__((weak)) struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ BUG();
+ return NULL;
+}
+
+#endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+
#ifdef CONFIG_MEMORY_FAILURE
/* Should be called in hugetlb_lock */
--
1.8.1.4
--
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 related [flat|nested] 30+ messages in thread
* [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm.
2013-04-30 16:30 ` [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:48 ` Catalin Marinas
1 sibling, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The huge_pte_alloc, huge_pte_offset and follow_huge_p[mu]d
functions in x86/mm/hugetlbpage.c do not rely on any architecture
specific knowledge other than the fact that pmds and puds can be
treated as huge ptes.
To allow other architectures to use this code (and reduce the need
for code duplication), this patch copies these functions into mm
and provides a config flag to activate them:
CONFIG_ARCH_WANT_GENERAL_HUGETLB
If CONFIG_ARCH_WANT_HUGE_PMD_SHARE is also active then the
huge_pmd_share code will be called by huge_pte_alloc (othewise we
call pmd_alloc and skip the sharing code).
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
mm/hugetlb.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 88 insertions(+), 9 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 41179b0..e1dc5ae 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2915,15 +2915,6 @@ out_mutex:
return ret;
}
-/* Can be overriden by architectures */
-__attribute__((weak)) struct page *
-follow_huge_pud(struct mm_struct *mm, unsigned long address,
- pud_t *pud, int write)
-{
- BUG();
- return NULL;
-}
-
long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
unsigned long *position, unsigned long *nr_pages,
@@ -3262,8 +3253,96 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
*addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
return 1;
}
+#define want_pmd_share() (1)
+#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
+pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+{
+ return NULL;
+}
+#define want_pmd_share() (0)
#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
+#ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ pud = pud_alloc(mm, pgd, addr);
+ if (pud) {
+ if (sz == PUD_SIZE) {
+ pte = (pte_t *)pud;
+ } else {
+ BUG_ON(sz != PMD_SIZE);
+ if (want_pmd_share() && pud_none(*pud))
+ pte = huge_pmd_share(mm, addr, pud);
+ else
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
+ }
+ }
+ BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
+
+ return pte;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd_present(*pgd)) {
+ pud = pud_offset(pgd, addr);
+ if (pud_present(*pud)) {
+ if (pud_large(*pud))
+ return (pte_t *)pud;
+ pmd = pmd_offset(pud, addr);
+ }
+ }
+ return (pte_t *) pmd;
+}
+
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pmd);
+ if (page)
+ page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pud);
+ if (page)
+ page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+#else /* !CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+
+/* Can be overriden by architectures */
+__attribute__((weak)) struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ BUG();
+ return NULL;
+}
+
+#endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+
#ifdef CONFIG_MEMORY_FAILURE
/* Should be called in hugetlb_lock */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm.
2013-04-30 16:30 ` [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm Steve Capper
2013-04-30 16:30 ` Steve Capper
@ 2013-04-30 16:48 ` Catalin Marinas
2013-04-30 16:48 ` Catalin Marinas
1 sibling, 1 reply; 30+ messages in thread
From: Catalin Marinas @ 2013-04-30 16:48 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:42PM +0100, Steve Capper wrote:
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 41179b0..e1dc5ae 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
...
> +pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
> +{
> + pgd_t *pgd;
> + pud_t *pud;
> + pmd_t *pmd = NULL;
> +
> + pgd = pgd_offset(mm, addr);
> + if (pgd_present(*pgd)) {
> + pud = pud_offset(pgd, addr);
> + if (pud_present(*pud)) {
> + if (pud_large(*pud))
That's more of a question for the x86 guys - can we replace pud_large()
here with pud_huge()? It looks like the former simply checks for present
and huge, so pud_huge() would be enough. This saves an additional
definition.
--
Catalin
--
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] 30+ messages in thread
* Re: [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm.
2013-04-30 16:48 ` Catalin Marinas
@ 2013-04-30 16:48 ` Catalin Marinas
0 siblings, 0 replies; 30+ messages in thread
From: Catalin Marinas @ 2013-04-30 16:48 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:42PM +0100, Steve Capper wrote:
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 41179b0..e1dc5ae 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
...
> +pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
> +{
> + pgd_t *pgd;
> + pud_t *pud;
> + pmd_t *pmd = NULL;
> +
> + pgd = pgd_offset(mm, addr);
> + if (pgd_present(*pgd)) {
> + pud = pud_offset(pgd, addr);
> + if (pud_present(*pud)) {
> + if (pud_large(*pud))
That's more of a question for the x86 guys - can we replace pud_large()
here with pud_huge()? It looks like the former simply checks for present
and huge, so pud_huge() would be enough. This saves an additional
definition.
--
Catalin
^ permalink raw reply [flat|nested] 30+ messages in thread
* [RFC PATCH 4/9] x86: mm: Remove general hugetlb code from x86.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (2 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 3/9] mm: hugetlb: Copy general hugetlb code from x86 to mm Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages Steve Capper
` (4 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
huge_pte_alloc, huge_pte_offset and follow_huge_p[mu]d have
already been copied over to mm.
This patch removes the x86 copies of these functions and activates
the general ones by enabling:
CONFIG_ARCH_WANT_GENERAL_HUGETLB
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/x86/Kconfig | 3 +++
arch/x86/mm/hugetlbpage.c | 67 -----------------------------------------------
2 files changed, 3 insertions(+), 67 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 60e3c402..db1ff87 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -215,6 +215,9 @@ config ARCH_SUSPEND_POSSIBLE
config ARCH_WANT_HUGE_PMD_SHARE
def_bool y
+config ARCH_WANT_GENERAL_HUGETLB
+ def_bool y
+
config ZONE_DMA32
bool
default X86_64
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 7e522a3..7e73e8c 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -16,49 +16,6 @@
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>
-pte_t *huge_pte_alloc(struct mm_struct *mm,
- unsigned long addr, unsigned long sz)
-{
- pgd_t *pgd;
- pud_t *pud;
- pte_t *pte = NULL;
-
- pgd = pgd_offset(mm, addr);
- pud = pud_alloc(mm, pgd, addr);
- if (pud) {
- if (sz == PUD_SIZE) {
- pte = (pte_t *)pud;
- } else {
- BUG_ON(sz != PMD_SIZE);
- if (pud_none(*pud))
- pte = huge_pmd_share(mm, addr, pud);
- else
- pte = (pte_t *)pmd_alloc(mm, pud, addr);
- }
- }
- BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
-
- return pte;
-}
-
-pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd = NULL;
-
- pgd = pgd_offset(mm, addr);
- if (pgd_present(*pgd)) {
- pud = pud_offset(pgd, addr);
- if (pud_present(*pud)) {
- if (pud_large(*pud))
- return (pte_t *)pud;
- pmd = pmd_offset(pud, addr);
- }
- }
- return (pte_t *) pmd;
-}
-
#if 0 /* This is just for testing */
struct page *
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
@@ -120,30 +77,6 @@ int pud_huge(pud_t pud)
return !!(pud_val(pud) & _PAGE_PSE);
}
-struct page *
-follow_huge_pmd(struct mm_struct *mm, unsigned long address,
- pmd_t *pmd, int write)
-{
- struct page *page;
-
- page = pte_page(*(pte_t *)pmd);
- if (page)
- page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
- return page;
-}
-
-struct page *
-follow_huge_pud(struct mm_struct *mm, unsigned long address,
- pud_t *pud, int write)
-{
- struct page *page;
-
- page = pte_page(*(pte_t *)pud);
- if (page)
- page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
- return page;
-}
-
#endif
/* x86_64 also uses this file */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (3 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 4/9] x86: mm: Remove general hugetlb code from x86 Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-05-01 11:05 ` Will Deacon
2013-04-30 16:30 ` [RFC PATCH 6/9] ARM64: mm: Restore memblock limit when map_mem finished Steve Capper
` (3 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The code to flush the dcache of a dirty page, __flush_dcache_page,
will only flush the head of a HugeTLB/THP page.
This patch adjusts __flush_dcache_page such that the order of the
compound page is used to determine the size of area to flush.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/mm/flush.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index 88611c3..71c182d 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -72,7 +72,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
void __flush_dcache_page(struct page *page)
{
- __flush_dcache_area(page_address(page), PAGE_SIZE);
+ size_t page_size = PAGE_SIZE << compound_order(page);
+ __flush_dcache_area(page_address(page), page_size);
}
void __sync_icache_dcache(pte_t pte, unsigned long addr)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages.
2013-04-30 16:30 ` [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages Steve Capper
@ 2013-05-01 11:05 ` Will Deacon
2013-05-01 11:05 ` Will Deacon
2013-05-01 11:31 ` Catalin Marinas
0 siblings, 2 replies; 30+ messages in thread
From: Will Deacon @ 2013-05-01 11:05 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Catalin Marinas
Hi Steve,
On Tue, Apr 30, 2013 at 05:30:44PM +0100, Steve Capper wrote:
> The code to flush the dcache of a dirty page, __flush_dcache_page,
> will only flush the head of a HugeTLB/THP page.
>
> This patch adjusts __flush_dcache_page such that the order of the
> compound page is used to determine the size of area to flush.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/mm/flush.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> index 88611c3..71c182d 100644
> --- a/arch/arm64/mm/flush.c
> +++ b/arch/arm64/mm/flush.c
> @@ -72,7 +72,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
>
> void __flush_dcache_page(struct page *page)
> {
> - __flush_dcache_area(page_address(page), PAGE_SIZE);
> + size_t page_size = PAGE_SIZE << compound_order(page);
> + __flush_dcache_area(page_address(page), page_size);
> }
This penalises flush_dcache_page, while it might only be required for
__sync_icache_dcache (called when installing executable ptes).
Now, the job of flush_dcache_page is to deal with D-side aliases between
concurrent user and kernel mappings. On arm64, D-side aliasing is not a
problem so in theory flush_dcache_page could be a nop (well, a clear_bit,
but close enough).
The reason that flush_dcache_page *isn't* currently a nop, is because we
have harvard caches, so if we end up in a situation where the kernel is
writing executable text to a page which is also mapped into userspace (i.e.
there won't be a subsequent call to set_pte), then the user will execute
junk if we don't flush/invalidate things here.
This might be overkill. I can't think of a scenario where the above is true,
but I'm no mm expert, so it would be great if somebody else could chime in
to confirm/rubbish out suspicions...
Cheers,
Will
--
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] 30+ messages in thread
* Re: [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages.
2013-05-01 11:05 ` Will Deacon
@ 2013-05-01 11:05 ` Will Deacon
2013-05-01 11:31 ` Catalin Marinas
1 sibling, 0 replies; 30+ messages in thread
From: Will Deacon @ 2013-05-01 11:05 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Catalin Marinas
Hi Steve,
On Tue, Apr 30, 2013 at 05:30:44PM +0100, Steve Capper wrote:
> The code to flush the dcache of a dirty page, __flush_dcache_page,
> will only flush the head of a HugeTLB/THP page.
>
> This patch adjusts __flush_dcache_page such that the order of the
> compound page is used to determine the size of area to flush.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/mm/flush.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> index 88611c3..71c182d 100644
> --- a/arch/arm64/mm/flush.c
> +++ b/arch/arm64/mm/flush.c
> @@ -72,7 +72,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
>
> void __flush_dcache_page(struct page *page)
> {
> - __flush_dcache_area(page_address(page), PAGE_SIZE);
> + size_t page_size = PAGE_SIZE << compound_order(page);
> + __flush_dcache_area(page_address(page), page_size);
> }
This penalises flush_dcache_page, while it might only be required for
__sync_icache_dcache (called when installing executable ptes).
Now, the job of flush_dcache_page is to deal with D-side aliases between
concurrent user and kernel mappings. On arm64, D-side aliasing is not a
problem so in theory flush_dcache_page could be a nop (well, a clear_bit,
but close enough).
The reason that flush_dcache_page *isn't* currently a nop, is because we
have harvard caches, so if we end up in a situation where the kernel is
writing executable text to a page which is also mapped into userspace (i.e.
there won't be a subsequent call to set_pte), then the user will execute
junk if we don't flush/invalidate things here.
This might be overkill. I can't think of a scenario where the above is true,
but I'm no mm expert, so it would be great if somebody else could chime in
to confirm/rubbish out suspicions...
Cheers,
Will
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages.
2013-05-01 11:05 ` Will Deacon
2013-05-01 11:05 ` Will Deacon
@ 2013-05-01 11:31 ` Catalin Marinas
2013-05-01 11:31 ` Catalin Marinas
1 sibling, 1 reply; 30+ messages in thread
From: Catalin Marinas @ 2013-05-01 11:31 UTC (permalink / raw)
To: Will Deacon
Cc: Steve Capper, linux-mm@kvack.org, x86@kernel.org,
linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Michal Hocko, Ken Chen, Mel Gorman
On Wed, May 01, 2013 at 12:05:34PM +0100, Will Deacon wrote:
> Hi Steve,
>
> On Tue, Apr 30, 2013 at 05:30:44PM +0100, Steve Capper wrote:
> > The code to flush the dcache of a dirty page, __flush_dcache_page,
> > will only flush the head of a HugeTLB/THP page.
> >
> > This patch adjusts __flush_dcache_page such that the order of the
> > compound page is used to determine the size of area to flush.
> >
> > Signed-off-by: Steve Capper <steve.capper@linaro.org>
> > ---
> > arch/arm64/mm/flush.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> > index 88611c3..71c182d 100644
> > --- a/arch/arm64/mm/flush.c
> > +++ b/arch/arm64/mm/flush.c
> > @@ -72,7 +72,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
> >
> > void __flush_dcache_page(struct page *page)
> > {
> > - __flush_dcache_area(page_address(page), PAGE_SIZE);
> > + size_t page_size = PAGE_SIZE << compound_order(page);
> > + __flush_dcache_area(page_address(page), page_size);
> > }
>
> This penalises flush_dcache_page, while it might only be required for
> __sync_icache_dcache (called when installing executable ptes).
>
> Now, the job of flush_dcache_page is to deal with D-side aliases between
> concurrent user and kernel mappings. On arm64, D-side aliasing is not a
> problem so in theory flush_dcache_page could be a nop (well, a clear_bit,
> but close enough).
>
> The reason that flush_dcache_page *isn't* currently a nop, is because we
> have harvard caches, so if we end up in a situation where the kernel is
> writing executable text to a page which is also mapped into userspace (i.e.
> there won't be a subsequent call to set_pte), then the user will execute
> junk if we don't flush/invalidate things here.
>
> This might be overkill. I can't think of a scenario where the above is true,
> but I'm no mm expert, so it would be great if somebody else could chime in
> to confirm/rubbish out suspicions...
And looking at the powerpc implementation, flush_dcache_page just does
clear_bit(PG_arch_1) and they haven't seen any problems. I'm pretty sure
we can to the same on arm64 (and 32-bit ARMv7 where we don't have
D-cache aliasing). But let's see the mm guys have a better insight here.
--
Catalin
--
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] 30+ messages in thread
* Re: [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages.
2013-05-01 11:31 ` Catalin Marinas
@ 2013-05-01 11:31 ` Catalin Marinas
0 siblings, 0 replies; 30+ messages in thread
From: Catalin Marinas @ 2013-05-01 11:31 UTC (permalink / raw)
To: Will Deacon
Cc: Steve Capper, linux-mm@kvack.org, x86@kernel.org,
linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Michal Hocko, Ken Chen, Mel Gorman
On Wed, May 01, 2013 at 12:05:34PM +0100, Will Deacon wrote:
> Hi Steve,
>
> On Tue, Apr 30, 2013 at 05:30:44PM +0100, Steve Capper wrote:
> > The code to flush the dcache of a dirty page, __flush_dcache_page,
> > will only flush the head of a HugeTLB/THP page.
> >
> > This patch adjusts __flush_dcache_page such that the order of the
> > compound page is used to determine the size of area to flush.
> >
> > Signed-off-by: Steve Capper <steve.capper@linaro.org>
> > ---
> > arch/arm64/mm/flush.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> > index 88611c3..71c182d 100644
> > --- a/arch/arm64/mm/flush.c
> > +++ b/arch/arm64/mm/flush.c
> > @@ -72,7 +72,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
> >
> > void __flush_dcache_page(struct page *page)
> > {
> > - __flush_dcache_area(page_address(page), PAGE_SIZE);
> > + size_t page_size = PAGE_SIZE << compound_order(page);
> > + __flush_dcache_area(page_address(page), page_size);
> > }
>
> This penalises flush_dcache_page, while it might only be required for
> __sync_icache_dcache (called when installing executable ptes).
>
> Now, the job of flush_dcache_page is to deal with D-side aliases between
> concurrent user and kernel mappings. On arm64, D-side aliasing is not a
> problem so in theory flush_dcache_page could be a nop (well, a clear_bit,
> but close enough).
>
> The reason that flush_dcache_page *isn't* currently a nop, is because we
> have harvard caches, so if we end up in a situation where the kernel is
> writing executable text to a page which is also mapped into userspace (i.e.
> there won't be a subsequent call to set_pte), then the user will execute
> junk if we don't flush/invalidate things here.
>
> This might be overkill. I can't think of a scenario where the above is true,
> but I'm no mm expert, so it would be great if somebody else could chime in
> to confirm/rubbish out suspicions...
And looking at the powerpc implementation, flush_dcache_page just does
clear_bit(PG_arch_1) and they haven't seen any problems. I'm pretty sure
we can to the same on arm64 (and 32-bit ARMv7 where we don't have
D-cache aliasing). But let's see the mm guys have a better insight here.
--
Catalin
^ permalink raw reply [flat|nested] 30+ messages in thread
* [RFC PATCH 6/9] ARM64: mm: Restore memblock limit when map_mem finished.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (4 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 5/9] ARM64: mm: Add support for flushing huge pages Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` [RFC PATCH 7/9] ARM64: mm: HugeTLB support Steve Capper
` (2 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
In paging_init the memblock limit is set to restrict any addresses
returned by early_alloc to fit within the initial direct kernel
mapping in swapper_pg_dir. This allows map_mem to allocate puds,
pmds and ptes from the initial direct kernel mapping.
The limit stays low after paging_init() though, meaning any
bootmem allocations will be from a restricted subset of memory.
Gigabyte huge pages, for instance, are normally allocated from
bootmem as their order (18) is too large for the default buddy
allocator (MAX_ORDER = 11).
This patch restores the memblock limit when map_mem has finished,
allowing gigabyte huge pages (and other objects) to be allocated
from all of bootmem.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/mm/mmu.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 70b8cd4..d23188c 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -297,6 +297,16 @@ static void __init map_mem(void)
{
struct memblock_region *reg;
+ /*
+ * Temporarily limit the memblock range. We need to do this as
+ * create_mapping requires puds, pmds and ptes to be allocated from
+ * memory addressable from the initial direct kernel mapping.
+ *
+ * The initial direct kernel mapping, located at swapper_pg_dir,
+ * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (aligned).
+ */
+ memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
+
/* map all the memory banks */
for_each_memblock(memory, reg) {
phys_addr_t start = reg->base;
@@ -307,6 +317,9 @@ static void __init map_mem(void)
create_mapping(start, __phys_to_virt(start), end - start);
}
+
+ /* Limit no longer required. */
+ memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
}
/*
@@ -317,12 +330,6 @@ void __init paging_init(void)
{
void *zero_page;
- /*
- * Maximum PGDIR_SIZE addressable via the initial direct kernel
- * mapping in swapper_pg_dir.
- */
- memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
-
init_mem_pgprot();
map_mem();
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (5 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 6/9] ARM64: mm: Restore memblock limit when map_mem finished Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` Steve Capper
` (2 more replies)
2013-04-30 16:30 ` [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP Steve Capper
2013-04-30 16:30 ` [RFC PATCH 9/9] ARM64: mm: THP support Steve Capper
8 siblings, 3 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
Add huge page support to ARM64, different huge page sizes are
supported depending on the size of normal pages:
PAGE_SIZE is 4K:
2MB - (pmds) these can be allocated at any time.
1024MB - (puds) usually allocated on bootup with the command line
with something like: hugepagesz=1G hugepages=6
PAGE_SIZE is 64K:
512MB - (pmds), usually allocated on bootup via command line.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/Kconfig | 9 +++
arch/arm64/include/asm/hugetlb.h | 121 +++++++++++++++++++++++++++++++++
arch/arm64/include/asm/pgtable-hwdef.h | 1 +
arch/arm64/include/asm/pgtable.h | 9 +++
arch/arm64/mm/Makefile | 1 +
arch/arm64/mm/fault.c | 19 ++----
arch/arm64/mm/hugetlbpage.c | 70 +++++++++++++++++++
7 files changed, 215 insertions(+), 15 deletions(-)
create mode 100644 arch/arm64/include/asm/hugetlb.h
create mode 100644 arch/arm64/mm/hugetlbpage.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 43b0e9f..16aa780 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -185,6 +185,15 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
+config SYS_SUPPORTS_HUGETLBFS
+ def_bool y if MMU
+
+config ARCH_WANT_GENERAL_HUGETLB
+ def_bool y if MMU
+
+config ARCH_WANT_HUGE_PMD_SHARE
+ def_bool y if !ARM64_64K_PAGES
+
source "mm/Kconfig"
endmenu
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
new file mode 100644
index 0000000..d00d72a
--- /dev/null
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -0,0 +1,121 @@
+/*
+ * arch/arm64/include/asm/hugetlb.h
+ *
+ * Copyright (C) 2013 Linaro Ltd.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_HUGETLB_H
+#define __ASM_HUGETLB_H
+
+#include <asm/page.h>
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ return *ptep;
+}
+
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ set_pte_at(mm, addr, ptep, pte);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_clear_flush(vma, addr, ptep);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_set_wrprotect(mm, addr, ptep);
+}
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ return ptep_get_and_clear(mm, addr, ptep);
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor,
+ unsigned long ceiling)
+{
+ free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+ unsigned long addr, unsigned long len)
+{
+ return 0;
+}
+
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
+{
+ struct hstate *h = hstate_file(file);
+ if (len & ~huge_page_mask(h))
+ return -EINVAL;
+ if (addr & ~huge_page_mask(h))
+ return -EINVAL;
+ return 0;
+}
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+ return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+ return pte_wrprotect(pte);
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+ return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+ clear_bit(PG_dcache_clean, &page->flags);
+}
+
+static inline int pud_large(pud_t pud)
+{
+ return ((pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT);
+}
+
+#endif /* __ASM_HUGETLB_H */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 75fd13d..c3cac68 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -53,6 +53,7 @@
#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_HUGEPAGE (_AT(pmdval_t, 1) << 0)
#define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
#define PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e333a24..4b7a058 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -176,6 +176,15 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
#define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
#define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
+/*
+ * Hugetlb definitions.
+ */
+#define HUGE_MAX_HSTATE 2
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
#define __HAVE_ARCH_PTE_SPECIAL
/*
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index 3140a2a..b51d364 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -2,3 +2,4 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
cache.o copypage.o flush.o \
ioremap.o mmap.o pgd.o mmu.o \
context.o tlb.o proc.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5263817..36e3080 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -363,17 +363,6 @@ static int __kprobes do_translation_fault(unsigned long addr,
}
/*
- * Some section permission faults need to be handled gracefully. They can
- * happen due to a __{get,put}_user during an oops.
- */
-static int do_sect_fault(unsigned long addr, unsigned int esr,
- struct pt_regs *regs)
-{
- do_bad_area(addr, esr, regs);
- return 0;
-}
-
-/*
* This abort handler always returns "fault".
*/
static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
@@ -396,12 +385,12 @@ static struct fault_info {
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
{ do_bad, SIGBUS, 0, "reserved access flag fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
{ do_bad, SIGBUS, 0, "reserved permission fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
{ do_bad, SIGBUS, 0, "synchronous external abort" },
{ do_bad, SIGBUS, 0, "asynchronous external abort" },
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
new file mode 100644
index 0000000..06c74e8
--- /dev/null
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -0,0 +1,70 @@
+/*
+ * arch/arm64/mm/hugetlbpage.c
+ *
+ * Copyright (C) 2013 Linaro Ltd.
+ *
+ * Based on arch/x86/mm/hugetlbpage.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
+#ifndef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ return 0;
+}
+#endif
+
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ int write)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ return (pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
+}
+
+int pud_huge(pud_t pud)
+{
+ return (pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
+}
+
+static __init int setup_hugepagesz(char *opt)
+{
+ unsigned long ps = memparse(opt, &opt);
+ if (ps == PMD_SIZE) {
+ hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+ } else if (ps == PUD_SIZE) {
+ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ } else {
+ pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+ return 0;
+ }
+ return 1;
+}
+__setup("hugepagesz=", setup_hugepagesz);
--
1.8.1.4
--
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 related [flat|nested] 30+ messages in thread
* [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-04-30 16:30 ` [RFC PATCH 7/9] ARM64: mm: HugeTLB support Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-05-01 11:42 ` Will Deacon
2013-05-01 16:21 ` Catalin Marinas
2 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
Add huge page support to ARM64, different huge page sizes are
supported depending on the size of normal pages:
PAGE_SIZE is 4K:
2MB - (pmds) these can be allocated at any time.
1024MB - (puds) usually allocated on bootup with the command line
with something like: hugepagesz=1G hugepages=6
PAGE_SIZE is 64K:
512MB - (pmds), usually allocated on bootup via command line.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/Kconfig | 9 +++
arch/arm64/include/asm/hugetlb.h | 121 +++++++++++++++++++++++++++++++++
arch/arm64/include/asm/pgtable-hwdef.h | 1 +
arch/arm64/include/asm/pgtable.h | 9 +++
arch/arm64/mm/Makefile | 1 +
arch/arm64/mm/fault.c | 19 ++----
arch/arm64/mm/hugetlbpage.c | 70 +++++++++++++++++++
7 files changed, 215 insertions(+), 15 deletions(-)
create mode 100644 arch/arm64/include/asm/hugetlb.h
create mode 100644 arch/arm64/mm/hugetlbpage.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 43b0e9f..16aa780 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -185,6 +185,15 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
+config SYS_SUPPORTS_HUGETLBFS
+ def_bool y if MMU
+
+config ARCH_WANT_GENERAL_HUGETLB
+ def_bool y if MMU
+
+config ARCH_WANT_HUGE_PMD_SHARE
+ def_bool y if !ARM64_64K_PAGES
+
source "mm/Kconfig"
endmenu
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
new file mode 100644
index 0000000..d00d72a
--- /dev/null
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -0,0 +1,121 @@
+/*
+ * arch/arm64/include/asm/hugetlb.h
+ *
+ * Copyright (C) 2013 Linaro Ltd.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_HUGETLB_H
+#define __ASM_HUGETLB_H
+
+#include <asm/page.h>
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ return *ptep;
+}
+
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ set_pte_at(mm, addr, ptep, pte);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_clear_flush(vma, addr, ptep);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_set_wrprotect(mm, addr, ptep);
+}
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ return ptep_get_and_clear(mm, addr, ptep);
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor,
+ unsigned long ceiling)
+{
+ free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+ unsigned long addr, unsigned long len)
+{
+ return 0;
+}
+
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
+{
+ struct hstate *h = hstate_file(file);
+ if (len & ~huge_page_mask(h))
+ return -EINVAL;
+ if (addr & ~huge_page_mask(h))
+ return -EINVAL;
+ return 0;
+}
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+ return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+ return pte_wrprotect(pte);
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+ return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+ clear_bit(PG_dcache_clean, &page->flags);
+}
+
+static inline int pud_large(pud_t pud)
+{
+ return ((pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT);
+}
+
+#endif /* __ASM_HUGETLB_H */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 75fd13d..c3cac68 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -53,6 +53,7 @@
#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_HUGEPAGE (_AT(pmdval_t, 1) << 0)
#define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
#define PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e333a24..4b7a058 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -176,6 +176,15 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
#define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
#define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
+/*
+ * Hugetlb definitions.
+ */
+#define HUGE_MAX_HSTATE 2
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
#define __HAVE_ARCH_PTE_SPECIAL
/*
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index 3140a2a..b51d364 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -2,3 +2,4 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
cache.o copypage.o flush.o \
ioremap.o mmap.o pgd.o mmu.o \
context.o tlb.o proc.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5263817..36e3080 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -363,17 +363,6 @@ static int __kprobes do_translation_fault(unsigned long addr,
}
/*
- * Some section permission faults need to be handled gracefully. They can
- * happen due to a __{get,put}_user during an oops.
- */
-static int do_sect_fault(unsigned long addr, unsigned int esr,
- struct pt_regs *regs)
-{
- do_bad_area(addr, esr, regs);
- return 0;
-}
-
-/*
* This abort handler always returns "fault".
*/
static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
@@ -396,12 +385,12 @@ static struct fault_info {
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
{ do_bad, SIGBUS, 0, "reserved access flag fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
{ do_bad, SIGBUS, 0, "reserved permission fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
{ do_bad, SIGBUS, 0, "synchronous external abort" },
{ do_bad, SIGBUS, 0, "asynchronous external abort" },
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
new file mode 100644
index 0000000..06c74e8
--- /dev/null
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -0,0 +1,70 @@
+/*
+ * arch/arm64/mm/hugetlbpage.c
+ *
+ * Copyright (C) 2013 Linaro Ltd.
+ *
+ * Based on arch/x86/mm/hugetlbpage.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
+#ifndef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ return 0;
+}
+#endif
+
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ int write)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ return (pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
+}
+
+int pud_huge(pud_t pud)
+{
+ return (pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
+}
+
+static __init int setup_hugepagesz(char *opt)
+{
+ unsigned long ps = memparse(opt, &opt);
+ if (ps == PMD_SIZE) {
+ hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+ } else if (ps == PUD_SIZE) {
+ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ } else {
+ pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+ return 0;
+ }
+ return 1;
+}
+__setup("hugepagesz=", setup_hugepagesz);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-04-30 16:30 ` [RFC PATCH 7/9] ARM64: mm: HugeTLB support Steve Capper
2013-04-30 16:30 ` Steve Capper
@ 2013-05-01 11:42 ` Will Deacon
2013-05-01 11:42 ` Will Deacon
2013-05-01 13:04 ` Steve Capper
2013-05-01 16:21 ` Catalin Marinas
2 siblings, 2 replies; 30+ messages in thread
From: Will Deacon @ 2013-05-01 11:42 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Catalin Marinas
Hi Steve,
On Tue, Apr 30, 2013 at 05:30:46PM +0100, Steve Capper wrote:
> Add huge page support to ARM64, different huge page sizes are
> supported depending on the size of normal pages:
>
> PAGE_SIZE is 4K:
> 2MB - (pmds) these can be allocated at any time.
> 1024MB - (puds) usually allocated on bootup with the command line
> with something like: hugepagesz=1G hugepages=6
>
> PAGE_SIZE is 64K:
> 512MB - (pmds), usually allocated on bootup via command line.
[...]
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index 75fd13d..c3cac68 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -53,6 +53,7 @@
> #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
> #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
> #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
> +#define PTE_TYPE_HUGEPAGE (_AT(pmdval_t, 1) << 0)
This breaks PROT_NONE mappings, where you get:
pte = pte_mkhuge(pte_modify(pte, newprot));
The pte_modify will clear the valid bit and set the prot_none bit (in order
to create a present, faulting entry) but then your pte_mkhuge will come in
and clobber that with a valid block entry.
Will
--
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] 30+ messages in thread
* Re: [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-05-01 11:42 ` Will Deacon
@ 2013-05-01 11:42 ` Will Deacon
2013-05-01 13:04 ` Steve Capper
1 sibling, 0 replies; 30+ messages in thread
From: Will Deacon @ 2013-05-01 11:42 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Catalin Marinas
Hi Steve,
On Tue, Apr 30, 2013 at 05:30:46PM +0100, Steve Capper wrote:
> Add huge page support to ARM64, different huge page sizes are
> supported depending on the size of normal pages:
>
> PAGE_SIZE is 4K:
> 2MB - (pmds) these can be allocated at any time.
> 1024MB - (puds) usually allocated on bootup with the command line
> with something like: hugepagesz=1G hugepages=6
>
> PAGE_SIZE is 64K:
> 512MB - (pmds), usually allocated on bootup via command line.
[...]
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index 75fd13d..c3cac68 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -53,6 +53,7 @@
> #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
> #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
> #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
> +#define PTE_TYPE_HUGEPAGE (_AT(pmdval_t, 1) << 0)
This breaks PROT_NONE mappings, where you get:
pte = pte_mkhuge(pte_modify(pte, newprot));
The pte_modify will clear the valid bit and set the prot_none bit (in order
to create a present, faulting entry) but then your pte_mkhuge will come in
and clobber that with a valid block entry.
Will
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-05-01 11:42 ` Will Deacon
2013-05-01 11:42 ` Will Deacon
@ 2013-05-01 13:04 ` Steve Capper
1 sibling, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-05-01 13:04 UTC (permalink / raw)
To: Will Deacon
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Catalin Marinas
On Wed, May 01, 2013 at 12:42:38PM +0100, Will Deacon wrote:
> Hi Steve,
>
> On Tue, Apr 30, 2013 at 05:30:46PM +0100, Steve Capper wrote:
> > Add huge page support to ARM64, different huge page sizes are
> > supported depending on the size of normal pages:
> >
> > PAGE_SIZE is 4K:
> > 2MB - (pmds) these can be allocated at any time.
> > 1024MB - (puds) usually allocated on bootup with the command line
> > with something like: hugepagesz=1G hugepages=6
> >
> > PAGE_SIZE is 64K:
> > 512MB - (pmds), usually allocated on bootup via command line.
>
> [...]
>
> > diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> > index 75fd13d..c3cac68 100644
> > --- a/arch/arm64/include/asm/pgtable-hwdef.h
> > +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> > @@ -53,6 +53,7 @@
> > #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
> > #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
> > #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
> > +#define PTE_TYPE_HUGEPAGE (_AT(pmdval_t, 1) << 0)
>
> This breaks PROT_NONE mappings, where you get:
>
> pte = pte_mkhuge(pte_modify(pte, newprot));
>
> The pte_modify will clear the valid bit and set the prot_none bit (in order
> to create a present, faulting entry) but then your pte_mkhuge will come in
> and clobber that with a valid block entry.
Thanks Will, I'll re-work the pte_mkhuge/pte_huge logic and get a PROT_NONE
test case coded up.
Cheers,
--
Steve
>
> Will
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-04-30 16:30 ` [RFC PATCH 7/9] ARM64: mm: HugeTLB support Steve Capper
2013-04-30 16:30 ` Steve Capper
2013-05-01 11:42 ` Will Deacon
@ 2013-05-01 16:21 ` Catalin Marinas
2013-05-01 16:21 ` Catalin Marinas
2 siblings, 1 reply; 30+ messages in thread
From: Catalin Marinas @ 2013-05-01 16:21 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:46PM +0100, Steve Capper wrote:
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 43b0e9f..16aa780 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -185,6 +185,15 @@ config HW_PERF_EVENTS
> Enable hardware performance counter support for perf events. If
> disabled, perf events will use software events only.
>
> +config SYS_SUPPORTS_HUGETLBFS
> + def_bool y if MMU
> +
> +config ARCH_WANT_GENERAL_HUGETLB
> + def_bool y if MMU
We could drop MMU here, I don't plan a uClinux port ;)
> diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
> new file mode 100644
> index 0000000..d00d72a
> --- /dev/null
> +++ b/arch/arm64/include/asm/hugetlb.h
...
> +static inline pte_t huge_ptep_get(pte_t *ptep)
> +{
> + return *ptep;
> +}
> +
> +static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
> + pte_t *ptep, pte_t pte)
> +{
> + set_pte_at(mm, addr, ptep, pte);
> +}
> +
> +static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
> + unsigned long addr, pte_t *ptep)
> +{
> + ptep_clear_flush(vma, addr, ptep);
> +}
> +
> +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
> + unsigned long addr, pte_t *ptep)
> +{
> + ptep_set_wrprotect(mm, addr, ptep);
> +}
> +
> +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
> + unsigned long addr, pte_t *ptep)
> +{
> + return ptep_get_and_clear(mm, addr, ptep);
> +}
> +
> +static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
> + unsigned long addr, pte_t *ptep,
> + pte_t pte, int dirty)
> +{
> + return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
> +}
> +
> +static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
> + unsigned long addr, unsigned long end,
> + unsigned long floor,
> + unsigned long ceiling)
> +{
> + free_pgd_range(tlb, addr, end, floor, ceiling);
> +}
...
> +static inline int huge_pte_none(pte_t pte)
> +{
> + return pte_none(pte);
> +}
> +
> +static inline pte_t huge_pte_wrprotect(pte_t pte)
> +{
> + return pte_wrprotect(pte);
> +}
Could we make these generic too?
> diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
> new file mode 100644
> index 0000000..06c74e8
> --- /dev/null
> +++ b/arch/arm64/mm/hugetlbpage.c
> @@ -0,0 +1,70 @@
> +/*
> + * arch/arm64/mm/hugetlbpage.c
> + *
> + * Copyright (C) 2013 Linaro Ltd.
> + *
> + * Based on arch/x86/mm/hugetlbpage.c.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#include <linux/init.h>
> +#include <linux/fs.h>
> +#include <linux/mm.h>
> +#include <linux/hugetlb.h>
> +#include <linux/pagemap.h>
> +#include <linux/err.h>
> +#include <linux/sysctl.h>
> +#include <asm/mman.h>
> +#include <asm/tlb.h>
> +#include <asm/tlbflush.h>
> +#include <asm/pgalloc.h>
> +
> +#ifndef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
> +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
> +{
> + return 0;
> +}
> +#endif
> +
> +struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
> + int write)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +
> +int pmd_huge(pmd_t pmd)
> +{
> + return (pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
> +}
> +
> +int pud_huge(pud_t pud)
> +{
> + return (pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
> +}
The types are mismatched here since pud_val() returns a pgd when
pgtable-nopud.h is used. I think we should defined PGD_TYPE_* in terms
of pgdval_t and PUD_TYPE_* just an alias for them.
--
Catalin
--
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] 30+ messages in thread
* Re: [RFC PATCH 7/9] ARM64: mm: HugeTLB support.
2013-05-01 16:21 ` Catalin Marinas
@ 2013-05-01 16:21 ` Catalin Marinas
0 siblings, 0 replies; 30+ messages in thread
From: Catalin Marinas @ 2013-05-01 16:21 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:46PM +0100, Steve Capper wrote:
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 43b0e9f..16aa780 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -185,6 +185,15 @@ config HW_PERF_EVENTS
> Enable hardware performance counter support for perf events. If
> disabled, perf events will use software events only.
>
> +config SYS_SUPPORTS_HUGETLBFS
> + def_bool y if MMU
> +
> +config ARCH_WANT_GENERAL_HUGETLB
> + def_bool y if MMU
We could drop MMU here, I don't plan a uClinux port ;)
> diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
> new file mode 100644
> index 0000000..d00d72a
> --- /dev/null
> +++ b/arch/arm64/include/asm/hugetlb.h
...
> +static inline pte_t huge_ptep_get(pte_t *ptep)
> +{
> + return *ptep;
> +}
> +
> +static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
> + pte_t *ptep, pte_t pte)
> +{
> + set_pte_at(mm, addr, ptep, pte);
> +}
> +
> +static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
> + unsigned long addr, pte_t *ptep)
> +{
> + ptep_clear_flush(vma, addr, ptep);
> +}
> +
> +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
> + unsigned long addr, pte_t *ptep)
> +{
> + ptep_set_wrprotect(mm, addr, ptep);
> +}
> +
> +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
> + unsigned long addr, pte_t *ptep)
> +{
> + return ptep_get_and_clear(mm, addr, ptep);
> +}
> +
> +static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
> + unsigned long addr, pte_t *ptep,
> + pte_t pte, int dirty)
> +{
> + return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
> +}
> +
> +static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
> + unsigned long addr, unsigned long end,
> + unsigned long floor,
> + unsigned long ceiling)
> +{
> + free_pgd_range(tlb, addr, end, floor, ceiling);
> +}
...
> +static inline int huge_pte_none(pte_t pte)
> +{
> + return pte_none(pte);
> +}
> +
> +static inline pte_t huge_pte_wrprotect(pte_t pte)
> +{
> + return pte_wrprotect(pte);
> +}
Could we make these generic too?
> diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
> new file mode 100644
> index 0000000..06c74e8
> --- /dev/null
> +++ b/arch/arm64/mm/hugetlbpage.c
> @@ -0,0 +1,70 @@
> +/*
> + * arch/arm64/mm/hugetlbpage.c
> + *
> + * Copyright (C) 2013 Linaro Ltd.
> + *
> + * Based on arch/x86/mm/hugetlbpage.c.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#include <linux/init.h>
> +#include <linux/fs.h>
> +#include <linux/mm.h>
> +#include <linux/hugetlb.h>
> +#include <linux/pagemap.h>
> +#include <linux/err.h>
> +#include <linux/sysctl.h>
> +#include <asm/mman.h>
> +#include <asm/tlb.h>
> +#include <asm/tlbflush.h>
> +#include <asm/pgalloc.h>
> +
> +#ifndef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
> +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
> +{
> + return 0;
> +}
> +#endif
> +
> +struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
> + int write)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +
> +int pmd_huge(pmd_t pmd)
> +{
> + return (pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
> +}
> +
> +int pud_huge(pud_t pud)
> +{
> + return (pud_val(pud) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
> +}
The types are mismatched here since pud_val() returns a pgd when
pgtable-nopud.h is used. I think we should defined PGD_TYPE_* in terms
of pgdval_t and PUD_TYPE_* just an alias for them.
--
Catalin
^ permalink raw reply [flat|nested] 30+ messages in thread
* [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (6 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 7/9] ARM64: mm: HugeTLB support Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-04-30 16:30 ` Steve Capper
2013-05-02 10:00 ` Catalin Marinas
2013-04-30 16:30 ` [RFC PATCH 9/9] ARM64: mm: THP support Steve Capper
8 siblings, 2 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The buddy allocator has a default order of 11, which is too low to
allocate enough memory for 512MB Transparent HugePages if our base
page size is 64K. For any order less than 13, the combination of
THP with 64K pages will cause a compile error.
This patch introduces the MAX_ZONE_ORDER config option that allows
one to explicitly override the order of the buddy allocator. If
64K pages and THP are enabled the minimum value is set to 13.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/Kconfig | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 16aa780..908fd95 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -196,6 +196,23 @@ config ARCH_WANT_HUGE_PMD_SHARE
source "mm/Kconfig"
+config FORCE_MAX_ZONEORDER
+ int "Maximum zone order"
+ range 11 64 if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ range 13 64 if ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE
+ default "11" if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ help
+ The kernel memory allocator divides physically contiguous memory
+ blocks into "zones", where each zone is a power of two number of
+ pages. This option selects the largest power of two that the kernel
+ keeps in the memory allocator. If you need to allocate very large
+ blocks of physically contiguous memory, then you may need to
+ increase this value.
+
+ This config option is actually maximum order plus one. For example,
+ a value of 11 means that the largest free memory block is 2^10 pages.
+
endmenu
menu "Boot options"
--
1.8.1.4
--
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 related [flat|nested] 30+ messages in thread
* [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-04-30 16:30 ` [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-05-02 10:00 ` Catalin Marinas
1 sibling, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
The buddy allocator has a default order of 11, which is too low to
allocate enough memory for 512MB Transparent HugePages if our base
page size is 64K. For any order less than 13, the combination of
THP with 64K pages will cause a compile error.
This patch introduces the MAX_ZONE_ORDER config option that allows
one to explicitly override the order of the buddy allocator. If
64K pages and THP are enabled the minimum value is set to 13.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/Kconfig | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 16aa780..908fd95 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -196,6 +196,23 @@ config ARCH_WANT_HUGE_PMD_SHARE
source "mm/Kconfig"
+config FORCE_MAX_ZONEORDER
+ int "Maximum zone order"
+ range 11 64 if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ range 13 64 if ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE
+ default "11" if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+ help
+ The kernel memory allocator divides physically contiguous memory
+ blocks into "zones", where each zone is a power of two number of
+ pages. This option selects the largest power of two that the kernel
+ keeps in the memory allocator. If you need to allocate very large
+ blocks of physically contiguous memory, then you may need to
+ increase this value.
+
+ This config option is actually maximum order plus one. For example,
+ a value of 11 means that the largest free memory block is 2^10 pages.
+
endmenu
menu "Boot options"
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-04-30 16:30 ` [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP Steve Capper
2013-04-30 16:30 ` Steve Capper
@ 2013-05-02 10:00 ` Catalin Marinas
2013-05-02 10:00 ` Catalin Marinas
2013-05-02 10:05 ` Steve Capper
1 sibling, 2 replies; 30+ messages in thread
From: Catalin Marinas @ 2013-05-02 10:00 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:47PM +0100, Steve Capper wrote:
> The buddy allocator has a default order of 11, which is too low to
> allocate enough memory for 512MB Transparent HugePages if our base
> page size is 64K. For any order less than 13, the combination of
> THP with 64K pages will cause a compile error.
>
> This patch introduces the MAX_ZONE_ORDER config option that allows
> one to explicitly override the order of the buddy allocator. If
> 64K pages and THP are enabled the minimum value is set to 13.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/Kconfig | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 16aa780..908fd95 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -196,6 +196,23 @@ config ARCH_WANT_HUGE_PMD_SHARE
>
> source "mm/Kconfig"
>
> +config FORCE_MAX_ZONEORDER
> + int "Maximum zone order"
> + range 11 64 if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> + range 13 64 if ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE
> + default "11" if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> + default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
Can we just keep some sane defaults here without giving too much choice
to the user? Something like:
config FORCE_MAX_ZONEORDER
int
default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
default "11"
We can extend it later if people need this but I'm aiming for a single
config on a multitude of boards.
--
Catalin
--
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] 30+ messages in thread
* Re: [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-05-02 10:00 ` Catalin Marinas
@ 2013-05-02 10:00 ` Catalin Marinas
2013-05-02 10:05 ` Steve Capper
1 sibling, 0 replies; 30+ messages in thread
From: Catalin Marinas @ 2013-05-02 10:00 UTC (permalink / raw)
To: Steve Capper
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Tue, Apr 30, 2013 at 05:30:47PM +0100, Steve Capper wrote:
> The buddy allocator has a default order of 11, which is too low to
> allocate enough memory for 512MB Transparent HugePages if our base
> page size is 64K. For any order less than 13, the combination of
> THP with 64K pages will cause a compile error.
>
> This patch introduces the MAX_ZONE_ORDER config option that allows
> one to explicitly override the order of the buddy allocator. If
> 64K pages and THP are enabled the minimum value is set to 13.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/Kconfig | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 16aa780..908fd95 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -196,6 +196,23 @@ config ARCH_WANT_HUGE_PMD_SHARE
>
> source "mm/Kconfig"
>
> +config FORCE_MAX_ZONEORDER
> + int "Maximum zone order"
> + range 11 64 if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> + range 13 64 if ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE
> + default "11" if !(ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> + default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
Can we just keep some sane defaults here without giving too much choice
to the user? Something like:
config FORCE_MAX_ZONEORDER
int
default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
default "11"
We can extend it later if people need this but I'm aiming for a single
config on a multitude of boards.
--
Catalin
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-05-02 10:00 ` Catalin Marinas
2013-05-02 10:00 ` Catalin Marinas
@ 2013-05-02 10:05 ` Steve Capper
2013-05-02 10:05 ` Steve Capper
1 sibling, 1 reply; 30+ messages in thread
From: Steve Capper @ 2013-05-02 10:05 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Thu, May 02, 2013 at 11:00:00AM +0100, Catalin Marinas wrote:
> On Tue, Apr 30, 2013 at 05:30:47PM +0100, Steve Capper wrote:
> Can we just keep some sane defaults here without giving too much choice
> to the user? Something like:
>
> config FORCE_MAX_ZONEORDER
> int
> default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> default "11"
>
> We can extend it later if people need this but I'm aiming for a single
> config on a multitude of boards.
>
> --
> Catalin
Thanks, that does look a lot neater :-).
--
Steve
--
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] 30+ messages in thread
* Re: [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP.
2013-05-02 10:05 ` Steve Capper
@ 2013-05-02 10:05 ` Steve Capper
0 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-05-02 10:05 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Michal Hocko, Ken Chen,
Mel Gorman, Will Deacon
On Thu, May 02, 2013 at 11:00:00AM +0100, Catalin Marinas wrote:
> On Tue, Apr 30, 2013 at 05:30:47PM +0100, Steve Capper wrote:
> Can we just keep some sane defaults here without giving too much choice
> to the user? Something like:
>
> config FORCE_MAX_ZONEORDER
> int
> default "13" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
> default "11"
>
> We can extend it later if people need this but I'm aiming for a single
> config on a multitude of boards.
>
> --
> Catalin
Thanks, that does look a lot neater :-).
--
Steve
^ permalink raw reply [flat|nested] 30+ messages in thread
* [RFC PATCH 9/9] ARM64: mm: THP support.
2013-04-30 16:30 [RFC PATCH 0/9] HugeTLB and THP support for ARM64 Steve Capper
` (7 preceding siblings ...)
2013-04-30 16:30 ` [RFC PATCH 8/9] ARM64: mm: Introduce MAX_ZONE_ORDER for 64K and THP Steve Capper
@ 2013-04-30 16:30 ` Steve Capper
2013-05-01 14:16 ` Steve Capper
8 siblings, 1 reply; 30+ messages in thread
From: Steve Capper @ 2013-04-30 16:30 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon,
Steve Capper
Bring Transparent HugePage support to ARM. The size of a
transparent huge page depends on the normal page size. A
transparent huge page is always represented as a pmd.
If PAGE_SIZE is 4K, THPs are 2MB.
If PAGE_SIZE is 64K, THPs are 512MB.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
---
arch/arm64/Kconfig | 3 +++
arch/arm64/include/asm/pgtable-hwdef.h | 1 +
arch/arm64/include/asm/pgtable.h | 47 ++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/tlb.h | 6 +++++
arch/arm64/include/asm/tlbflush.h | 2 ++
5 files changed, 59 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 908fd95..9356802 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -194,6 +194,9 @@ config ARCH_WANT_GENERAL_HUGETLB
config ARCH_WANT_HUGE_PMD_SHARE
def_bool y if !ARM64_64K_PAGES
+config HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ def_bool y if MMU
+
source "mm/Kconfig"
config FORCE_MAX_ZONEORDER
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index c3cac68..862acf7 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -35,6 +35,7 @@
/*
* Section
*/
+#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
#define PMD_SECT_NG (_AT(pmdval_t, 1) << 11)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 4b7a058..06bfbd6 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -188,6 +188,53 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
#define __HAVE_ARCH_PTE_SPECIAL
/*
+ * Software PMD bits for THP
+ */
+
+#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
+#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57)
+
+/*
+ * THP definitions.
+ */
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
+
+#define __HAVE_ARCH_PMD_WRITE
+#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_trans_huge(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#endif
+
+#define PMD_BIT_FUNC(fn,op) \
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+
+PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
+PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
+PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
+PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+
+#define pmd_mkhuge(pmd) (__pmd((pmd_val(pmd) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+#define pmd_pfn(pmd) (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
+#define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
+
+#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
+
+#define pmd_modify(pmd,newprot) (__pmd(pmd_val(pmd) | pgprot_val(newprot)))
+#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd)
+
+static inline int has_transparent_hugepage(void)
+{
+ return 1;
+}
+
+/*
* Mark the prot value as uncacheable and unbufferable.
*/
#define pgprot_noncached(prot) \
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 654f096..46b3beb 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -187,4 +187,10 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
#define tlb_migrate_finish(mm) do { } while (0)
+static inline void
+tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
+{
+ tlb_add_flush(tlb, addr);
+}
+
#endif
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 122d632..8b48203 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -117,6 +117,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
dsb();
}
+#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
+
#endif
#endif
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 9/9] ARM64: mm: THP support.
2013-04-30 16:30 ` [RFC PATCH 9/9] ARM64: mm: THP support Steve Capper
@ 2013-05-01 14:16 ` Steve Capper
2013-05-01 14:16 ` Steve Capper
0 siblings, 1 reply; 30+ messages in thread
From: Steve Capper @ 2013-05-01 14:16 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon
On Tue, Apr 30, 2013 at 05:30:48PM +0100, Steve Capper wrote:
> Bring Transparent HugePage support to ARM. The size of a
> transparent huge page depends on the normal page size. A
> transparent huge page is always represented as a pmd.
>
> If PAGE_SIZE is 4K, THPs are 2MB.
> If PAGE_SIZE is 64K, THPs are 512MB.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/Kconfig | 3 +++
> arch/arm64/include/asm/pgtable-hwdef.h | 1 +
> arch/arm64/include/asm/pgtable.h | 47 ++++++++++++++++++++++++++++++++++
> arch/arm64/include/asm/tlb.h | 6 +++++
> arch/arm64/include/asm/tlbflush.h | 2 ++
> 5 files changed, 59 insertions(+)
>
[ ... ]
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index 4b7a058..06bfbd6 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
[ ... ]
> +#define pmd_modify(pmd,newprot) (__pmd(pmd_val(pmd) | pgprot_val(newprot)))
> +#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd)
Apologies, I have over-simplified (and broke) pmd_modify whilst tidying up this
patch. It should mask off certain bits. I will send out a correction once
PROT_NONE support has been sorted as this will affect this code path too.
--
Steve
--
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] 30+ messages in thread
* Re: [RFC PATCH 9/9] ARM64: mm: THP support.
2013-05-01 14:16 ` Steve Capper
@ 2013-05-01 14:16 ` Steve Capper
0 siblings, 0 replies; 30+ messages in thread
From: Steve Capper @ 2013-05-01 14:16 UTC (permalink / raw)
To: linux-mm, x86, linux-arch, linux-arm-kernel
Cc: Michal Hocko, Ken Chen, Mel Gorman, Catalin Marinas, Will Deacon
On Tue, Apr 30, 2013 at 05:30:48PM +0100, Steve Capper wrote:
> Bring Transparent HugePage support to ARM. The size of a
> transparent huge page depends on the normal page size. A
> transparent huge page is always represented as a pmd.
>
> If PAGE_SIZE is 4K, THPs are 2MB.
> If PAGE_SIZE is 64K, THPs are 512MB.
>
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> arch/arm64/Kconfig | 3 +++
> arch/arm64/include/asm/pgtable-hwdef.h | 1 +
> arch/arm64/include/asm/pgtable.h | 47 ++++++++++++++++++++++++++++++++++
> arch/arm64/include/asm/tlb.h | 6 +++++
> arch/arm64/include/asm/tlbflush.h | 2 ++
> 5 files changed, 59 insertions(+)
>
[ ... ]
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index 4b7a058..06bfbd6 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
[ ... ]
> +#define pmd_modify(pmd,newprot) (__pmd(pmd_val(pmd) | pgprot_val(newprot)))
> +#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd)
Apologies, I have over-simplified (and broke) pmd_modify whilst tidying up this
patch. It should mask off certain bits. I will send out a correction once
PROT_NONE support has been sorted as this will affect this code path too.
--
Steve
^ permalink raw reply [flat|nested] 30+ messages in thread