[PATCH 4/7] Store huge page linux pte in mm_struct

bill4carson at gmail.com bill4carson at gmail.com
Mon Jan 30 02:57:15 EST 2012


From: Bill Carson <bill4carson at gmail.com>

One easy way to store huge page linux pte is mm_struct instead of thread_info
that's because when parent task with huge page VMA calls fork, parent huge page
pagetable entries are copied into child pagetable. This is done in

int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
			    struct vm_area_struct *vma)

We cannot derive child's thread_info just using struct mm_struct *dst.
if we have struct mm_struct **dst, then it's easy to find the corresponding
task_struct as well as thread_info, but we only get struct mm_struct *dst.
It's possible to find the desired task_struct by iterating the global task list
by comparing task_struct->mm with dst.
So mm_struct is used for huge page linux pte for faster lookup and efficient.

Signed-off-by: Bill Carson <bill4carson at gmail.com>
---
 arch/arm/mm/pgd.c        |   28 ++++++++++++++++++++++++++++
 include/linux/mm_types.h |   11 +++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index a3e78cc..b04a69a 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -91,6 +91,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 		pte_unmap(new_pte);
 	}
 
+#ifdef CONFIG_ARM_HUGETLB_SUPPORT
+	/* reset the hugepage linux pte pointer
+	 * for new mm_struct when we do the fork
+	 */
+	mm->huge_2m_pte[HUGE_2M_PTE_1ST_ARRAY] = 0;
+	mm->huge_2m_pte[HUGE_2M_PTE_2ND_ARRAY] = 0;
+	mm->huge_16m_pte   = 0;
+#endif
 	return new_pgd;
 
 no_pte:
@@ -103,6 +111,25 @@ no_pgd:
 	return NULL;
 }
 
+#ifdef CONFIG_ARM_HUGETLB_SUPPORT
+static void free_huge_linuxpte(struct mm_struct *mm)
+{
+	pte_t **huge_linuxpte = &mm->huge_2m_pte[0];
+	int i;
+
+	for (i = 0; i < HUGE_2M_PTE_SIZE; i++)
+		if (huge_linuxpte[i] != 0)
+			free_page((unsigned long)huge_linuxpte[i]);
+
+	if (mm->huge_16m_pte != NULL)
+		kfree(mm->huge_16m_pte);
+}
+#else
+static void free_huge_linuxpte(struct mm_struct *mm)
+{
+}
+#endif
+
 void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
 {
 	pgd_t *pgd;
@@ -135,6 +162,7 @@ no_pud:
 	pgd_clear(pgd);
 	pud_free(mm, pud);
 no_pgd:
+	free_huge_linuxpte(mm);
 #ifdef CONFIG_ARM_LPAE
 	/*
 	 * Free modules/pkmap or identity pmd tables.
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 3cc3062..88f76e6 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -23,6 +23,11 @@
 struct address_space;
 
 #define USE_SPLIT_PTLOCKS	(NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
+#ifdef CONFIG_ARM_HUGETLB_SUPPORT
+#define HUGE_2M_PTE_SIZE      2
+#define HUGE_2M_PTE_1ST_ARRAY 0
+#define HUGE_2M_PTE_2ND_ARRAY 1
+#endif
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -388,6 +393,12 @@ struct mm_struct {
 #ifdef CONFIG_CPUMASK_OFFSTACK
 	struct cpumask cpumask_allocation;
 #endif
+
+#ifdef CONFIG_ARM_HUGETLB_SUPPORT
+	/* we place hugepage linux pte at mm_struct  */
+	pte_t *huge_2m_pte[HUGE_2M_PTE_SIZE];
+	pte_t *huge_16m_pte;
+#endif
 };
 
 static inline void mm_init_cpumask(struct mm_struct *mm)
-- 
1.7.1




More information about the linux-arm-kernel mailing list