aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/tlb-r4k.c
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-05-27 20:47:44 -0400
committerRalf Baechle <ralf@linux-mips.org>2009-06-17 06:06:30 -0400
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 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/mm.h> 13#include <linux/mm.h>
14#include <linux/hugetlb.h>
14 15
15#include <asm/cpu.h> 16#include <asm/cpu.h>
16#include <asm/bootinfo.h> 17#include <asm/bootinfo.h>
@@ -295,21 +296,41 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
295 pudp = pud_offset(pgdp, address); 296 pudp = pud_offset(pgdp, address);
296 pmdp = pmd_offset(pudp, address); 297 pmdp = pmd_offset(pudp, address);
297 idx = read_c0_index(); 298 idx = read_c0_index();
298 ptep = pte_offset_map(pmdp, address); 299#ifdef CONFIG_HUGETLB_PAGE
300 /* this could be a huge page */
301 if (pmd_huge(*pmdp)) {
302 unsigned long lo;
303 write_c0_pagemask(PM_HUGE_MASK);
304 ptep = (pte_t *)pmdp;
305 lo = pte_val(*ptep) >> 6;
306 write_c0_entrylo0(lo);
307 write_c0_entrylo1(lo + (HPAGE_SIZE >> 7));
308
309 mtc0_tlbw_hazard();
310 if (idx < 0)
311 tlb_write_random();
312 else
313 tlb_write_indexed();
314 write_c0_pagemask(PM_DEFAULT_MASK);
315 } else
316#endif
317 {
318 ptep = pte_offset_map(pmdp, address);
299 319
300#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 320#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
301 write_c0_entrylo0(ptep->pte_high); 321 write_c0_entrylo0(ptep->pte_high);
302 ptep++; 322 ptep++;
303 write_c0_entrylo1(ptep->pte_high); 323 write_c0_entrylo1(ptep->pte_high);
304#else 324#else
305 write_c0_entrylo0(pte_val(*ptep++) >> 6); 325 write_c0_entrylo0(pte_val(*ptep++) >> 6);
306 write_c0_entrylo1(pte_val(*ptep) >> 6); 326 write_c0_entrylo1(pte_val(*ptep) >> 6);
307#endif 327#endif
308 mtc0_tlbw_hazard(); 328 mtc0_tlbw_hazard();
309 if (idx < 0) 329 if (idx < 0)
310 tlb_write_random(); 330 tlb_write_random();
311 else 331 else
312 tlb_write_indexed(); 332 tlb_write_indexed();
333 }
313 tlbw_use_hazard(); 334 tlbw_use_hazard();
314 FLUSH_ITLB_VM(vma); 335 FLUSH_ITLB_VM(vma);
315 EXIT_CRITICAL(flags); 336 EXIT_CRITICAL(flags);