summaryrefslogtreecommitdiff
path: root/arch/mips/mm/tlb-r4k.c
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-05-27 17:47:44 -0700
committerRalf Baechle <ralf@linux-mips.org>2009-06-17 11:06:30 +0100
commitfd062c847a8cea2821347d7e18165dfa658f7dce (patch)
tree95410c5460f7d153a9c9b15184ea52e2059427c3 /arch/mips/mm/tlb-r4k.c
parentdd7943920b492d9d8a79080fe05e25ecd7e10bc3 (diff)
MIPS: TLB support for hugetlbfs.
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> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm/tlb-r4k.c')
-rw-r--r--arch/mips/mm/tlb-r4k.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 892be426787c..f60fe513eb60 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>
@@ -295,21 +296,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);