| .. | .. |
|---|
| 21 | 21 | #include <asm/bootinfo.h> |
|---|
| 22 | 22 | #include <asm/hazards.h> |
|---|
| 23 | 23 | #include <asm/mmu_context.h> |
|---|
| 24 | | -#include <asm/pgtable.h> |
|---|
| 25 | 24 | #include <asm/tlb.h> |
|---|
| 26 | 25 | #include <asm/tlbmisc.h> |
|---|
| 27 | 26 | |
|---|
| .. | .. |
|---|
| 35 | 34 | static inline void flush_micro_tlb(void) |
|---|
| 36 | 35 | { |
|---|
| 37 | 36 | switch (current_cpu_type()) { |
|---|
| 38 | | - case CPU_LOONGSON2: |
|---|
| 37 | + case CPU_LOONGSON2EF: |
|---|
| 39 | 38 | write_c0_diag(LOONGSON_DIAG_ITLB); |
|---|
| 40 | 39 | break; |
|---|
| 41 | | - case CPU_LOONGSON3: |
|---|
| 40 | + case CPU_LOONGSON64: |
|---|
| 42 | 41 | write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); |
|---|
| 43 | 42 | break; |
|---|
| 44 | 43 | default: |
|---|
| .. | .. |
|---|
| 104 | 103 | } |
|---|
| 105 | 104 | EXPORT_SYMBOL(local_flush_tlb_all); |
|---|
| 106 | 105 | |
|---|
| 107 | | -/* All entries common to a mm share an asid. To effectively flush |
|---|
| 108 | | - these entries, we just bump the asid. */ |
|---|
| 109 | | -void local_flush_tlb_mm(struct mm_struct *mm) |
|---|
| 110 | | -{ |
|---|
| 111 | | - int cpu; |
|---|
| 112 | | - |
|---|
| 113 | | - preempt_disable(); |
|---|
| 114 | | - |
|---|
| 115 | | - cpu = smp_processor_id(); |
|---|
| 116 | | - |
|---|
| 117 | | - if (cpu_context(cpu, mm) != 0) { |
|---|
| 118 | | - drop_mmu_context(mm, cpu); |
|---|
| 119 | | - } |
|---|
| 120 | | - |
|---|
| 121 | | - preempt_enable(); |
|---|
| 122 | | -} |
|---|
| 123 | | - |
|---|
| 124 | 106 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
|---|
| 125 | 107 | unsigned long end) |
|---|
| 126 | 108 | { |
|---|
| .. | .. |
|---|
| 137 | 119 | if (size <= (current_cpu_data.tlbsizeftlbsets ? |
|---|
| 138 | 120 | current_cpu_data.tlbsize / 8 : |
|---|
| 139 | 121 | current_cpu_data.tlbsize / 2)) { |
|---|
| 140 | | - int oldpid = read_c0_entryhi(); |
|---|
| 122 | + unsigned long old_entryhi, old_mmid; |
|---|
| 141 | 123 | int newpid = cpu_asid(cpu, mm); |
|---|
| 124 | + |
|---|
| 125 | + old_entryhi = read_c0_entryhi(); |
|---|
| 126 | + if (cpu_has_mmid) { |
|---|
| 127 | + old_mmid = read_c0_memorymapid(); |
|---|
| 128 | + write_c0_memorymapid(newpid); |
|---|
| 129 | + } |
|---|
| 142 | 130 | |
|---|
| 143 | 131 | htw_stop(); |
|---|
| 144 | 132 | while (start < end) { |
|---|
| 145 | 133 | int idx; |
|---|
| 146 | 134 | |
|---|
| 147 | | - write_c0_entryhi(start | newpid); |
|---|
| 135 | + if (cpu_has_mmid) |
|---|
| 136 | + write_c0_entryhi(start); |
|---|
| 137 | + else |
|---|
| 138 | + write_c0_entryhi(start | newpid); |
|---|
| 148 | 139 | start += (PAGE_SIZE << 1); |
|---|
| 149 | 140 | mtc0_tlbw_hazard(); |
|---|
| 150 | 141 | tlb_probe(); |
|---|
| .. | .. |
|---|
| 160 | 151 | tlb_write_indexed(); |
|---|
| 161 | 152 | } |
|---|
| 162 | 153 | tlbw_use_hazard(); |
|---|
| 163 | | - write_c0_entryhi(oldpid); |
|---|
| 154 | + write_c0_entryhi(old_entryhi); |
|---|
| 155 | + if (cpu_has_mmid) |
|---|
| 156 | + write_c0_memorymapid(old_mmid); |
|---|
| 164 | 157 | htw_start(); |
|---|
| 165 | 158 | } else { |
|---|
| 166 | | - drop_mmu_context(mm, cpu); |
|---|
| 159 | + drop_mmu_context(mm); |
|---|
| 167 | 160 | } |
|---|
| 168 | 161 | flush_micro_tlb(); |
|---|
| 169 | 162 | local_irq_restore(flags); |
|---|
| .. | .. |
|---|
| 220 | 213 | int cpu = smp_processor_id(); |
|---|
| 221 | 214 | |
|---|
| 222 | 215 | if (cpu_context(cpu, vma->vm_mm) != 0) { |
|---|
| 223 | | - unsigned long flags; |
|---|
| 224 | | - int oldpid, newpid, idx; |
|---|
| 216 | + unsigned long old_mmid; |
|---|
| 217 | + unsigned long flags, old_entryhi; |
|---|
| 218 | + int idx; |
|---|
| 225 | 219 | |
|---|
| 226 | | - newpid = cpu_asid(cpu, vma->vm_mm); |
|---|
| 227 | 220 | page &= (PAGE_MASK << 1); |
|---|
| 228 | 221 | local_irq_save(flags); |
|---|
| 229 | | - oldpid = read_c0_entryhi(); |
|---|
| 222 | + old_entryhi = read_c0_entryhi(); |
|---|
| 230 | 223 | htw_stop(); |
|---|
| 231 | | - write_c0_entryhi(page | newpid); |
|---|
| 224 | + if (cpu_has_mmid) { |
|---|
| 225 | + old_mmid = read_c0_memorymapid(); |
|---|
| 226 | + write_c0_entryhi(page); |
|---|
| 227 | + write_c0_memorymapid(cpu_asid(cpu, vma->vm_mm)); |
|---|
| 228 | + } else { |
|---|
| 229 | + write_c0_entryhi(page | cpu_asid(cpu, vma->vm_mm)); |
|---|
| 230 | + } |
|---|
| 232 | 231 | mtc0_tlbw_hazard(); |
|---|
| 233 | 232 | tlb_probe(); |
|---|
| 234 | 233 | tlb_probe_hazard(); |
|---|
| .. | .. |
|---|
| 244 | 243 | tlbw_use_hazard(); |
|---|
| 245 | 244 | |
|---|
| 246 | 245 | finish: |
|---|
| 247 | | - write_c0_entryhi(oldpid); |
|---|
| 246 | + write_c0_entryhi(old_entryhi); |
|---|
| 247 | + if (cpu_has_mmid) |
|---|
| 248 | + write_c0_memorymapid(old_mmid); |
|---|
| 248 | 249 | htw_start(); |
|---|
| 249 | 250 | flush_micro_tlb_vm(vma); |
|---|
| 250 | 251 | local_irq_restore(flags); |
|---|
| .. | .. |
|---|
| 293 | 294 | { |
|---|
| 294 | 295 | unsigned long flags; |
|---|
| 295 | 296 | pgd_t *pgdp; |
|---|
| 297 | + p4d_t *p4dp; |
|---|
| 296 | 298 | pud_t *pudp; |
|---|
| 297 | 299 | pmd_t *pmdp; |
|---|
| 298 | 300 | pte_t *ptep; |
|---|
| .. | .. |
|---|
| 307 | 309 | local_irq_save(flags); |
|---|
| 308 | 310 | |
|---|
| 309 | 311 | htw_stop(); |
|---|
| 310 | | - pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); |
|---|
| 311 | 312 | address &= (PAGE_MASK << 1); |
|---|
| 312 | | - write_c0_entryhi(address | pid); |
|---|
| 313 | + if (cpu_has_mmid) { |
|---|
| 314 | + write_c0_entryhi(address); |
|---|
| 315 | + } else { |
|---|
| 316 | + pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); |
|---|
| 317 | + write_c0_entryhi(address | pid); |
|---|
| 318 | + } |
|---|
| 313 | 319 | pgdp = pgd_offset(vma->vm_mm, address); |
|---|
| 314 | 320 | mtc0_tlbw_hazard(); |
|---|
| 315 | 321 | tlb_probe(); |
|---|
| 316 | 322 | tlb_probe_hazard(); |
|---|
| 317 | | - pudp = pud_offset(pgdp, address); |
|---|
| 323 | + p4dp = p4d_offset(pgdp, address); |
|---|
| 324 | + pudp = pud_offset(p4dp, address); |
|---|
| 318 | 325 | pmdp = pmd_offset(pudp, address); |
|---|
| 319 | 326 | idx = read_c0_index(); |
|---|
| 320 | 327 | #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT |
|---|
| .. | .. |
|---|
| 375 | 382 | #ifdef CONFIG_XPA |
|---|
| 376 | 383 | panic("Broken for XPA kernels"); |
|---|
| 377 | 384 | #else |
|---|
| 385 | + unsigned int old_mmid; |
|---|
| 378 | 386 | unsigned long flags; |
|---|
| 379 | 387 | unsigned long wired; |
|---|
| 380 | 388 | unsigned long old_pagemask; |
|---|
| 381 | 389 | unsigned long old_ctx; |
|---|
| 382 | 390 | |
|---|
| 383 | 391 | local_irq_save(flags); |
|---|
| 392 | + if (cpu_has_mmid) { |
|---|
| 393 | + old_mmid = read_c0_memorymapid(); |
|---|
| 394 | + write_c0_memorymapid(MMID_KERNEL_WIRED); |
|---|
| 395 | + } |
|---|
| 384 | 396 | /* Save old context and create impossible VPN2 value */ |
|---|
| 385 | 397 | old_ctx = read_c0_entryhi(); |
|---|
| 386 | 398 | htw_stop(); |
|---|
| .. | .. |
|---|
| 398 | 410 | tlbw_use_hazard(); |
|---|
| 399 | 411 | |
|---|
| 400 | 412 | write_c0_entryhi(old_ctx); |
|---|
| 413 | + if (cpu_has_mmid) |
|---|
| 414 | + write_c0_memorymapid(old_mmid); |
|---|
| 401 | 415 | tlbw_use_hazard(); /* What is the hazard here? */ |
|---|
| 402 | 416 | htw_start(); |
|---|
| 403 | 417 | write_c0_pagemask(old_pagemask); |
|---|