All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] MIPS: Add hugeTLBfs support.
@ 2009-05-28  0:46 David Daney
  2009-05-28  0:47 ` [PATCH 1/5] MIPS: Add support files for hugeTLBfs David Daney
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: David Daney @ 2009-05-28  0:46 UTC (permalink / raw)
  To: Ralf Baechle, linux-mips; +Cc: wli

This patch set adds hugetlbfs support to the MIPS architecture.

Huge pages are implemented by placing the PTE for the huge page
(flagged by the _PAGE_HUGE) in the PMD.  This gives a huge page size
of 2M (PTRS_PER_PTE * PAGE_SIZE) when the PAGE_SIZE is 4K.  Each huge
page occupies a complete TLB entry with the first half of the page
covered by entrylo0 and the second half by entrylo1.  Since there is
only a single PTE for the huge page in the PMD, the value of entrylo1
is derived from entrylo0 by adding a constant of half a huge page.  We
do this for several reasons:

1) The valid values of PageMask are such that this combination is
allowed.

2) Since the PageMask applies to both entrylo0 *and* entrylo1 we
cannot leave one of them empty because the current vma allocation
mechanisms don't handle excluding areas that would fall in any gaps
caused by an empty entrylo from allocation to normal sized pages.

When hugetlbfs is enabled, there is an approximately two instruction
overhead in the normal path of the TLB refill handler.  This is needed
to check the _PAGE_HUGE bit of each PMD entry.  With hugetlbfs
disabled, there is no change.

Currently the patch only works for 64-bit kernels because the value of
PTRS_PER_PTE in 32-bit kernels is such that it is impossible to have a
valid PageMask.  It is thought that by adjusting the page allocation
scheme, 32-bit kernels could be supported in the future.

All of the patches except the forth touch only the arch/mips tree.
The forth patch is the generic Kconfig change to allow MIPS to turn on
hugetlbfs.

I will reply with the five patches.

David Daney (5):
   MIPS: Add support files for hugeTLBfs.
   MIPS: Add hugeTLBfs page defines.
   MIPS: TLB support for hugeTLBfs.
   Enable hugetlbfs for more systems.
   MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for
     some systems.

  arch/mips/Kconfig                    |   11 +++
  arch/mips/include/asm/hugetlb.h      |  114 +++++++++++++++++++++++
  arch/mips/include/asm/mipsregs.h     |   16 ++++
  arch/mips/include/asm/page.h         |    5 +
  arch/mips/include/asm/pgtable-bits.h |    1 +
  arch/mips/include/asm/pgtable.h      |   10 ++
  arch/mips/mm/Makefile                |    1 +
  arch/mips/mm/hugetlbpage.c           |  101 +++++++++++++++++++++
  arch/mips/mm/tlb-r4k.c               |   43 +++++++---
  arch/mips/mm/tlbex.c                 |  165 
+++++++++++++++++++++++++++++++++-
  fs/Kconfig                           |    2 +-
  11 files changed, 456 insertions(+), 13 deletions(-)
  create mode 100644 arch/mips/include/asm/hugetlb.h
  create mode 100644 arch/mips/mm/hugetlbpage.c

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] MIPS: Add support files for hugeTLBfs.
  2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
@ 2009-05-28  0:47 ` David Daney
  2009-05-28  0:47 ` [PATCH 2/5] MIPS: Add hugeTLBfs page defines David Daney
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: David Daney @ 2009-05-28  0:47 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: wli, David Daney

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/include/asm/hugetlb.h |  114 +++++++++++++++++++++++++++++++++++++++
 arch/mips/mm/Makefile           |    1 +
 arch/mips/mm/hugetlbpage.c      |  101 ++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/hugetlb.h
 create mode 100644 arch/mips/mm/hugetlbpage.c

diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h
new file mode 100644
index 0000000..f5e8560
--- /dev/null
+++ b/arch/mips/include/asm/hugetlb.h
@@ -0,0 +1,114 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008, 2009 Cavium Networks, Inc.
+ */
+
+#ifndef __ASM_HUGETLB_H
+#define __ASM_HUGETLB_H
+
+#include <asm/page.h>
+
+
+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)
+{
+	unsigned long task_size = STACK_TOP;
+	struct hstate *h = hstate_file(file);
+
+	if (len & ~huge_page_mask(h))
+		return -EINVAL;
+	if (addr & ~huge_page_mask(h))
+		return -EINVAL;
+	if (len > task_size)
+		return -ENOMEM;
+	if (task_size - len < addr)
+		return -EINVAL;
+	return 0;
+}
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+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 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 pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+					    unsigned long addr, pte_t *ptep)
+{
+	pte_t clear;
+	pte_t pte = *ptep;
+
+	pte_val(clear) = (unsigned long)invalid_pte_table;
+	set_pte_at(mm, addr, ptep, clear);
+	return pte;
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+					 unsigned long addr, pte_t *ptep)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+	unsigned long val = pte_val(pte) & ~_PAGE_GLOBAL;
+	return !val || (val == (unsigned long)invalid_pte_table);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+	return pte_wrprotect(pte);
+}
+
+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 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 pte_t huge_ptep_get(pte_t *ptep)
+{
+	return *ptep;
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+	return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+#endif /* __ASM_HUGETLB_H */
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index d7ec955..f0e4355 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -8,6 +8,7 @@ obj-y				+= cache.o dma-default.o extable.o fault.o \
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 
 obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o tlb-r4k.o
diff --git a/arch/mips/mm/hugetlbpage.c b/arch/mips/mm/hugetlbpage.c
new file mode 100644
index 0000000..471c09a
--- /dev/null
+++ b/arch/mips/mm/hugetlbpage.c
@@ -0,0 +1,101 @@
+/*
+ * MIPS Huge TLB Page Support for Kernel.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright 2005, Embedded Alley Solutions, Inc.
+ * Matt Porter <mporter@embeddedalley.com>
+ * Copyright (C) 2008, 2009 Cavium Networks, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.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)
+		pte = (pte_t *)pmd_alloc(mm, pud, addr);
+
+	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))
+			pmd = pmd_offset(pud, addr);
+	}
+	return (pte_t *) pmd;
+}
+
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+	return 0;
+}
+
+/*
+ * This function checks for proper alignment of input addr and len parameters.
+ */
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+{
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	if (addr & ~HPAGE_MASK)
+		return -EINVAL;
+	return 0;
+}
+
+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) & _PAGE_HUGE) != 0;
+}
+
+int pud_huge(pud_t pud)
+{
+	return (pud_val(pud) & _PAGE_HUGE) != 0;
+}
+
+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 & ~HPAGE_MASK) >> PAGE_SHIFT);
+	return page;
+}
+
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] MIPS: Add hugeTLBfs page defines.
  2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
  2009-05-28  0:47 ` [PATCH 1/5] MIPS: Add support files for hugeTLBfs David Daney
@ 2009-05-28  0:47 ` David Daney
  2009-05-28  0:47 ` [PATCH 3/5] MIPS: TLB support for hugeTLBfs David Daney
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: David Daney @ 2009-05-28  0:47 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: wli, David Daney

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/include/asm/mipsregs.h     |   16 ++++++++++++++++
 arch/mips/include/asm/page.h         |    5 +++++
 arch/mips/include/asm/pgtable-bits.h |    1 +
 arch/mips/include/asm/pgtable.h      |   10 ++++++++++
 4 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 32ef8be..a581d60 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -220,6 +220,22 @@
 #error Bad page size configuration!
 #endif
 
+/*
+ * Default huge tlb size for a given kernel configuration
+ */
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PM_HUGE_MASK	PM_1M
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+#define PM_HUGE_MASK	PM_4M
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+#define PM_HUGE_MASK	PM_16M
+#elif defined(CONFIG_PAGE_SIZE_32KB)
+#define PM_HUGE_MASK	PM_64M
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+#define PM_HUGE_MASK	PM_256M
+#elif defined(CONFIG_HUGETLB_PAGE)
+#error Bad page size configuration for hugetlbfs!
+#endif
 
 /*
  * Values used for computation of new tlb entries
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 9f946e4..61ef073 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -32,6 +32,11 @@
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
 
+#define HPAGE_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
+#define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK	(~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/pfn.h>
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
index 51b34a4..1073e6d 100644
--- a/arch/mips/include/asm/pgtable-bits.h
+++ b/arch/mips/include/asm/pgtable-bits.h
@@ -72,6 +72,7 @@
 #else
 
 #define _PAGE_R4KBUG                (1<<5)  /* workaround for r4k bug  */
+#define _PAGE_HUGE                  (1<<5)  /* huge tlb page */
 #define _PAGE_GLOBAL                (1<<6)
 #define _PAGE_VALID                 (1<<7)
 #define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 6a0edf7..1a9f9b2 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -292,6 +292,16 @@ static inline pte_t pte_mkyoung(pte_t pte)
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
+
+#ifdef _PAGE_HUGE
+static inline int pte_huge(pte_t pte)	{ return pte_val(pte) & _PAGE_HUGE; }
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_HUGE;
+	return pte;
+}
+#endif /* _PAGE_HUGE */
 #endif
 static inline int pte_special(pte_t pte)	{ return 0; }
 static inline pte_t pte_mkspecial(pte_t pte)	{ return pte; }
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] MIPS: TLB support for hugeTLBfs.
  2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
  2009-05-28  0:47 ` [PATCH 1/5] MIPS: Add support files for hugeTLBfs David Daney
  2009-05-28  0:47 ` [PATCH 2/5] MIPS: Add hugeTLBfs page defines David Daney
@ 2009-05-28  0:47 ` David Daney
  2009-05-28  0:47 ` [PATCH 4/5] Enable hugetlbfs for more systems David Daney
  2009-05-28  0:47 ` [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems David Daney
  4 siblings, 0 replies; 8+ messages in thread
From: David Daney @ 2009-05-28  0:47 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: wli, David Daney

The TLB handlers need to check for huge pages and give them special
handling.  Huge pages consist of two contiguous sub-pages of physical
memory.

* Loading entrylo0 and entrylo1 need to be handled specially.

* The page mask must be set for huge pages and then restored after
  writing the TLB entries.

* The PTE for huge pages resides in the PMD, we halt traversal of the
  tables there.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/mm/tlb-r4k.c |   43 +++++++++---
 arch/mips/mm/tlbex.c   |  165 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 196 insertions(+), 12 deletions(-)

diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 9619f66..b8a73c4 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/hugetlb.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -297,21 +298,41 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 	pudp = pud_offset(pgdp, address);
 	pmdp = pmd_offset(pudp, address);
 	idx = read_c0_index();
-	ptep = pte_offset_map(pmdp, address);
+#ifdef CONFIG_HUGETLB_PAGE
+	/* this could be a huge page  */
+	if (pmd_huge(*pmdp)) {
+		unsigned long lo;
+		write_c0_pagemask(PM_HUGE_MASK);
+		ptep = (pte_t *)pmdp;
+		lo = pte_val(*ptep) >> 6;
+		write_c0_entrylo0(lo);
+		write_c0_entrylo1(lo + (HPAGE_SIZE >> 7));
+
+		mtc0_tlbw_hazard();
+		if (idx < 0)
+			tlb_write_random();
+		else
+			tlb_write_indexed();
+		write_c0_pagemask(PM_DEFAULT_MASK);
+	} else
+#endif
+	{
+		ptep = pte_offset_map(pmdp, address);
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
-	write_c0_entrylo0(ptep->pte_high);
-	ptep++;
-	write_c0_entrylo1(ptep->pte_high);
+		write_c0_entrylo0(ptep->pte_high);
+		ptep++;
+		write_c0_entrylo1(ptep->pte_high);
 #else
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+		write_c0_entrylo0(pte_val(*ptep++) >> 6);
+		write_c0_entrylo1(pte_val(*ptep) >> 6);
 #endif
-	mtc0_tlbw_hazard();
-	if (idx < 0)
-		tlb_write_random();
-	else
-		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+		if (idx < 0)
+			tlb_write_random();
+		else
+			tlb_write_indexed();
+	}
 	tlbw_use_hazard();
 	FLUSH_ITLB_VM(vma);
 	EXIT_CRITICAL(flags);
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 62fbd0d..8f606ea 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -8,6 +8,7 @@
  * Copyright (C) 2004, 2005, 2006, 2008  Thiemo Seufer
  * Copyright (C) 2005, 2007, 2008, 2009  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2008, 2009 Cavium Networks, Inc.
  *
  * ... and the days got worse and worse and now you see
  * I've gone completly out of my mind.
@@ -83,6 +84,9 @@ enum label_id {
 	label_nopage_tlbm,
 	label_smp_pgtable_change,
 	label_r3000_write_probe_fail,
+#ifdef CONFIG_HUGETLB_PAGE
+	label_tlb_huge_update,
+#endif
 };
 
 UASM_L_LA(_second_part)
@@ -99,6 +103,9 @@ UASM_L_LA(_nopage_tlbs)
 UASM_L_LA(_nopage_tlbm)
 UASM_L_LA(_smp_pgtable_change)
 UASM_L_LA(_r3000_write_probe_fail)
+#ifdef CONFIG_HUGETLB_PAGE
+UASM_L_LA(_tlb_huge_update)
+#endif
 
 /*
  * For debug purposes.
@@ -126,6 +133,7 @@ static inline void dump_handler(const u32 *handler, int count)
 #define C0_TCBIND	2, 2
 #define C0_ENTRYLO1	3, 0
 #define C0_CONTEXT	4, 0
+#define C0_PAGEMASK	5, 0
 #define C0_BADVADDR	8, 0
 #define C0_ENTRYHI	10, 0
 #define C0_EPC		14, 0
@@ -383,6 +391,98 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
 	}
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+static __cpuinit void build_huge_tlb_write_entry(u32 **p,
+						 struct uasm_label **l,
+						 struct uasm_reloc **r,
+						 unsigned int tmp,
+						 enum tlb_write_entry wmode)
+{
+	/* Set huge page tlb entry size */
+	uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16);
+	uasm_i_ori(p, tmp, tmp, PM_HUGE_MASK & 0xffff);
+	uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+
+	build_tlb_write_entry(p, l, r, wmode);
+
+	/* Reset default page size */
+	if (PM_DEFAULT_MASK >> 16) {
+		uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
+		uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+	} else if (PM_DEFAULT_MASK) {
+		uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+	} else {
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, 0, C0_PAGEMASK);
+	}
+}
+
+/*
+ * Check if Huge PTE is present, if so then jump to LABEL.
+ */
+static void __cpuinit
+build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp,
+		unsigned int pmd, int lid)
+{
+	UASM_i_LW(p, tmp, 0, pmd);
+	uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
+	uasm_il_bnez(p, r, tmp, lid);
+}
+
+static __cpuinit void build_huge_update_entries(u32 **p,
+						unsigned int pte,
+						unsigned int tmp)
+{
+	int small_sequence;
+
+	/*
+	 * A huge PTE describes an area the size of the
+	 * configured huge page size. This is twice the
+	 * of the large TLB entry size we intend to use.
+	 * A TLB entry half the size of the configured
+	 * huge page size is configured into entrylo0
+	 * and entrylo1 to cover the contiguous huge PTE
+	 * address space.
+	 */
+	small_sequence = (HPAGE_SIZE >> 7) < 0x10000;
+
+	/* We can clobber tmp.  It isn't used after this.*/
+	if (!small_sequence)
+		uasm_i_lui(p, tmp, HPAGE_SIZE >> (7 + 16));
+
+	UASM_i_SRL(p, pte, pte, 6); /* convert to entrylo */
+	uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* load it */
+	/* convert to entrylo1 */
+	if (small_sequence)
+		UASM_i_ADDIU(p, pte, pte, HPAGE_SIZE >> 7);
+	else
+		UASM_i_ADDU(p, pte, pte, tmp);
+
+	uasm_i_mtc0(p, pte, C0_ENTRYLO1); /* load it */
+}
+
+static __cpuinit void build_huge_handler_tail(u32 **p,
+					      struct uasm_reloc **r,
+					      struct uasm_label **l,
+					      unsigned int pte,
+					      unsigned int ptr)
+{
+#ifdef CONFIG_SMP
+	UASM_i_SC(p, pte, 0, ptr);
+	uasm_il_beqz(p, r, pte, label_tlb_huge_update);
+	UASM_i_LW(p, pte, 0, ptr); /* Needed because SC killed our PTE */
+#else
+	UASM_i_SW(p, pte, 0, ptr);
+#endif
+	build_huge_update_entries(p, pte, ptr);
+	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed);
+}
+#endif /* CONFIG_HUGETLB_PAGE */
+
 #ifdef CONFIG_64BIT
 /*
  * TMP and PTR are scratch.
@@ -689,12 +789,23 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 	build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
+#ifdef CONFIG_HUGETLB_PAGE
+	build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
+#endif
+
 	build_get_ptep(&p, K0, K1);
 	build_update_entries(&p, K0, K1);
 	build_tlb_write_entry(&p, &l, &r, tlb_random);
 	uasm_l_leave(&l, p);
 	uasm_i_eret(&p); /* return from trap */
 
+#ifdef CONFIG_HUGETLB_PAGE
+	uasm_l_tlb_huge_update(&l, p);
+	UASM_i_LW(&p, K0, 0, K1);
+	build_huge_update_entries(&p, K0, K1);
+	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random);
+#endif
+
 #ifdef CONFIG_64BIT
 	build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
 #endif
@@ -733,7 +844,9 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 		uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 		final_len = p - tlb_handler;
 	} else {
-#ifdef MODULE_START
+#if defined(CONFIG_HUGETLB_PAGE)
+		const enum label_id ls = label_tlb_huge_update;
+#elif defined(MODULE_START)
 		const enum label_id ls = label_module_alloc;
 #else
 		const enum label_id ls = label_vmalloc;
@@ -1130,6 +1243,15 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
 	build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
 #endif
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * For huge tlb entries, pmd doesn't contain an address but
+	 * instead contains the tlb pte. Check the PAGE_HUGE bit and
+	 * see if we need to jump to huge tlb processing.
+	 */
+	build_is_huge_pte(p, r, pte, ptr, label_tlb_huge_update);
+#endif
+
 	UASM_i_MFC0(p, pte, C0_BADVADDR);
 	UASM_i_LW(p, ptr, 0, ptr);
 	UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
@@ -1187,6 +1309,19 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 	build_make_valid(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when build_r4000_tlbchange_handler_head
+	 * spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0, (_PAGE_ACCESSED | _PAGE_VALID));
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbl(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
 	uasm_i_nop(&p);
@@ -1218,6 +1353,20 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when
+	 * build_r4000_tlbchange_handler_head spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0,
+		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbs(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
@@ -1250,6 +1399,20 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when
+	 * build_r4000_tlbchange_handler_head spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0,
+		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbm(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] Enable hugetlbfs for more systems.
  2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
                   ` (2 preceding siblings ...)
  2009-05-28  0:47 ` [PATCH 3/5] MIPS: TLB support for hugeTLBfs David Daney
@ 2009-05-28  0:47 ` David Daney
  2009-06-16 10:20   ` Ralf Baechle
  2009-05-28  0:47 ` [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems David Daney
  4 siblings, 1 reply; 8+ messages in thread
From: David Daney @ 2009-05-28  0:47 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: wli, David Daney

As part of adding hugetlbfs support for MIPS, I am adding a new
kconfig variable 'SYS_SUPPORTS_HUGETLBFS'.  Since some mips cpu
varients don't yet support it, we can enable selection of HUGETLBFS on
a system by system basis from the arch/mips/Kconfig.

CC: William Irwin <wli@holomorphy.com>
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 fs/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index 9f7270f..c36d63b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -124,7 +124,7 @@ config TMPFS_POSIX_ACL
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
-		   (S390 && 64BIT) || BROKEN
+		   (S390 && 64BIT) || SYS_SUPPORTS_HUGETLBFS || BROKEN
 	help
 	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
 	  ramfs. For architectures that support it, say Y here and read
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems.
  2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
                   ` (3 preceding siblings ...)
  2009-05-28  0:47 ` [PATCH 4/5] Enable hugetlbfs for more systems David Daney
@ 2009-05-28  0:47 ` David Daney
  2009-06-16 10:23   ` Ralf Baechle
  4 siblings, 1 reply; 8+ messages in thread
From: David Daney @ 2009-05-28  0:47 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: wli, David Daney

Add new kconfig variables SYS_SUPPORTS_HUGETLBFS and
CPU_SUPPORTS_HUGEPAGES.  They are enabled for systems that are known
to support huge pages.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/Kconfig |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c4a84a6..592949a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -852,6 +852,11 @@ config SYS_SUPPORTS_BIG_ENDIAN
 config SYS_SUPPORTS_LITTLE_ENDIAN
 	bool
 
+config SYS_SUPPORTS_HUGETLBFS
+	bool
+	depends on  CPU_SUPPORTS_HUGEPAGES && 64BIT
+	default y
+
 config IRQ_CPU
 	bool
 
@@ -1056,6 +1061,7 @@ config CPU_MIPS64_R1
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  Choose this option to build a kernel for release 1 or later of the
 	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
@@ -1075,6 +1081,7 @@ config CPU_MIPS64_R2
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
@@ -1161,6 +1168,7 @@ config CPU_R5500
 	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  NEC VR5500 and VR5500A series processors implement 64-bit MIPS IV
 	  instruction set.
@@ -1246,6 +1254,7 @@ config CPU_CAVIUM_OCTEON
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  The Cavium Octeon processor is a highly integrated chip containing
 	  many ethernet hardware widgets for networking tasks. The processor
@@ -1365,6 +1374,8 @@ config CPU_SUPPORTS_32BIT_KERNEL
 	bool
 config CPU_SUPPORTS_64BIT_KERNEL
 	bool
+config CPU_SUPPORTS_HUGEPAGES
+	bool
 
 #
 # Set to y for ptrace access to watch registers.
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] Enable hugetlbfs for more systems.
  2009-05-28  0:47 ` [PATCH 4/5] Enable hugetlbfs for more systems David Daney
@ 2009-06-16 10:20   ` Ralf Baechle
  0 siblings, 0 replies; 8+ messages in thread
From: Ralf Baechle @ 2009-06-16 10:20 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, wli, linux-kernel

On Wed, May 27, 2009 at 05:47:45PM -0700, David Daney wrote:
> From: David Daney <ddaney@caviumnetworks.com>
> Date: Wed, 27 May 2009 17:47:45 -0700
> To: linux-mips@linux-mips.org, ralf@linux-mips.org
> Cc: wli@holomorphy.com, David Daney <ddaney@caviumnetworks.com>

Holomorphy.com is unreachable since like a year.  Use wli@kernel.org.

> Subject: [PATCH 4/5] Enable hugetlbfs for more systems.
> 
> As part of adding hugetlbfs support for MIPS, I am adding a new
> kconfig variable 'SYS_SUPPORTS_HUGETLBFS'.  Since some mips cpu
> varients don't yet support it, we can enable selection of HUGETLBFS on
> a system by system basis from the arch/mips/Kconfig.
> 
> CC: William Irwin <wli@holomorphy.com>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
>  fs/Kconfig |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 9f7270f..c36d63b 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -124,7 +124,7 @@ config TMPFS_POSIX_ACL
>  config HUGETLBFS
>  	bool "HugeTLB file system support"
>  	depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
> -		   (S390 && 64BIT) || BROKEN
> +		   (S390 && 64BIT) || SYS_SUPPORTS_HUGETLBFS || BROKEN

I'm ok with this patch but it's really crying for some follup patch to
convert all the other architectures to use SYS_SUPPORTS_HUGETLBFS.

  Ralf

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems.
  2009-05-28  0:47 ` [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems David Daney
@ 2009-06-16 10:23   ` Ralf Baechle
  0 siblings, 0 replies; 8+ messages in thread
From: Ralf Baechle @ 2009-06-16 10:23 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, wli

On Wed, May 27, 2009 at 05:47:46PM -0700, David Daney wrote:
> From: David Daney <ddaney@caviumnetworks.com>
> Date: Wed, 27 May 2009 17:47:46 -0700
> To: linux-mips@linux-mips.org, ralf@linux-mips.org
> Cc: wli@holomorphy.com, David Daney <ddaney@caviumnetworks.com>
> Subject: [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and
> 	enable it for some systems.
> 
> Add new kconfig variables SYS_SUPPORTS_HUGETLBFS and
> CPU_SUPPORTS_HUGEPAGES.  They are enabled for systems that are known
> to support huge pages.

Which should be all processors except R2000 / R3000, R6000 and R8000, no?

  Ralf

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-06-16 10:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-28  0:46 [PATCH 0/5] MIPS: Add hugeTLBfs support David Daney
2009-05-28  0:47 ` [PATCH 1/5] MIPS: Add support files for hugeTLBfs David Daney
2009-05-28  0:47 ` [PATCH 2/5] MIPS: Add hugeTLBfs page defines David Daney
2009-05-28  0:47 ` [PATCH 3/5] MIPS: TLB support for hugeTLBfs David Daney
2009-05-28  0:47 ` [PATCH 4/5] Enable hugetlbfs for more systems David Daney
2009-06-16 10:20   ` Ralf Baechle
2009-05-28  0:47 ` [PATCH 5/5] MIPS: Add SYS_SUPPORTS_HUGETLBFS Kconfig variable and enable it for some systems David Daney
2009-06-16 10:23   ` Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.