diff options
Diffstat (limited to 'arch/mips/mm/tlb-r4k.c')
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 0d394e0e8837..88dc49cfa163 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c | |||
@@ -120,22 +120,30 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
120 | 120 | ||
121 | if (cpu_context(cpu, mm) != 0) { | 121 | if (cpu_context(cpu, mm) != 0) { |
122 | unsigned long size, flags; | 122 | unsigned long size, flags; |
123 | int huge = is_vm_hugetlb_page(vma); | ||
123 | 124 | ||
124 | ENTER_CRITICAL(flags); | 125 | ENTER_CRITICAL(flags); |
125 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 126 | if (huge) { |
126 | size = (size + 1) >> 1; | 127 | start = round_down(start, HPAGE_SIZE); |
128 | end = round_up(end, HPAGE_SIZE); | ||
129 | size = (end - start) >> HPAGE_SHIFT; | ||
130 | } else { | ||
131 | start = round_down(start, PAGE_SIZE << 1); | ||
132 | end = round_up(end, PAGE_SIZE << 1); | ||
133 | size = (end - start) >> (PAGE_SHIFT + 1); | ||
134 | } | ||
127 | if (size <= current_cpu_data.tlbsize/2) { | 135 | if (size <= current_cpu_data.tlbsize/2) { |
128 | int oldpid = read_c0_entryhi(); | 136 | int oldpid = read_c0_entryhi(); |
129 | int newpid = cpu_asid(cpu, mm); | 137 | int newpid = cpu_asid(cpu, mm); |
130 | 138 | ||
131 | start &= (PAGE_MASK << 1); | ||
132 | end += ((PAGE_SIZE << 1) - 1); | ||
133 | end &= (PAGE_MASK << 1); | ||
134 | while (start < end) { | 139 | while (start < end) { |
135 | int idx; | 140 | int idx; |
136 | 141 | ||
137 | write_c0_entryhi(start | newpid); | 142 | write_c0_entryhi(start | newpid); |
138 | start += (PAGE_SIZE << 1); | 143 | if (huge) |
144 | start += HPAGE_SIZE; | ||
145 | else | ||
146 | start += (PAGE_SIZE << 1); | ||
139 | mtc0_tlbw_hazard(); | 147 | mtc0_tlbw_hazard(); |
140 | tlb_probe(); | 148 | tlb_probe(); |
141 | tlb_probe_hazard(); | 149 | tlb_probe_hazard(); |