diff options
author | David Daney <ddaney@caviumnetworks.com> | 2009-05-27 17:47:44 -0700 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-06-17 11:06:30 +0100 |
commit | fd062c847a8cea2821347d7e18165dfa658f7dce (patch) | |
tree | 95410c5460f7d153a9c9b15184ea52e2059427c3 /arch/mips/mm/tlb-r4k.c | |
parent | dd7943920b492d9d8a79080fe05e25ecd7e10bc3 (diff) | |
download | lwn-fd062c847a8cea2821347d7e18165dfa658f7dce.tar.gz lwn-fd062c847a8cea2821347d7e18165dfa658f7dce.zip |
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.c | 43 |
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); |