aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/tlbex.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm/tlbex.c')
-rw-r--r--arch/mips/mm/tlbex.c97
1 files changed, 62 insertions, 35 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 323d1d302f2b..32e0be27673f 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -311,6 +311,7 @@ static struct uasm_label labels[128];
311static struct uasm_reloc relocs[128]; 311static struct uasm_reloc relocs[128];
312 312
313static int check_for_high_segbits; 313static int check_for_high_segbits;
314static bool fill_includes_sw_bits;
314 315
315static unsigned int kscratch_used_mask; 316static unsigned int kscratch_used_mask;
316 317
@@ -630,8 +631,14 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
630static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, 631static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
631 unsigned int reg) 632 unsigned int reg)
632{ 633{
633 if (cpu_has_rixi) { 634 if (cpu_has_rixi && _PAGE_NO_EXEC) {
634 UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); 635 if (fill_includes_sw_bits) {
636 UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
637 } else {
638 UASM_i_SRL(p, reg, reg, ilog2(_PAGE_NO_EXEC));
639 UASM_i_ROTR(p, reg, reg,
640 ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
641 }
635 } else { 642 } else {
636#ifdef CONFIG_PHYS_ADDR_T_64BIT 643#ifdef CONFIG_PHYS_ADDR_T_64BIT
637 uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL)); 644 uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -1005,21 +1012,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
1005 * 64bit address support (36bit on a 32bit CPU) in a 32bit 1012 * 64bit address support (36bit on a 32bit CPU) in a 32bit
1006 * Kernel is a special case. Only a few CPUs use it. 1013 * Kernel is a special case. Only a few CPUs use it.
1007 */ 1014 */
1008#ifdef CONFIG_PHYS_ADDR_T_64BIT 1015 if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
1009 if (cpu_has_64bits) {
1010 uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
1011 uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
1012 if (cpu_has_rixi) {
1013 UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
1014 UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
1015 UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
1016 } else {
1017 uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
1018 UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
1019 uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
1020 }
1021 UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
1022 } else {
1023 int pte_off_even = sizeof(pte_t) / 2; 1016 int pte_off_even = sizeof(pte_t) / 2;
1024 int pte_off_odd = pte_off_even + sizeof(pte_t); 1017 int pte_off_odd = pte_off_even + sizeof(pte_t);
1025#ifdef CONFIG_XPA 1018#ifdef CONFIG_XPA
@@ -1043,31 +1036,23 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
1043 uasm_i_mthc0(p, tmp, C0_ENTRYLO0); 1036 uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
1044 uasm_i_mthc0(p, ptep, C0_ENTRYLO1); 1037 uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
1045#endif 1038#endif
1039 return;
1046 } 1040 }
1047#else 1041
1048 UASM_i_LW(p, tmp, 0, ptep); /* get even pte */ 1042 UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
1049 UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ 1043 UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
1050 if (r45k_bvahwbug()) 1044 if (r45k_bvahwbug())
1051 build_tlb_probe_entry(p); 1045 build_tlb_probe_entry(p);
1052 if (cpu_has_rixi) { 1046 build_convert_pte_to_entrylo(p, tmp);
1053 UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); 1047 if (r4k_250MHZhwbug())
1054 if (r4k_250MHZhwbug()) 1048 UASM_i_MTC0(p, 0, C0_ENTRYLO0);
1055 UASM_i_MTC0(p, 0, C0_ENTRYLO0); 1049 UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
1056 UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ 1050 build_convert_pte_to_entrylo(p, ptep);
1057 UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); 1051 if (r45k_bvahwbug())
1058 } else { 1052 uasm_i_mfc0(p, tmp, C0_INDEX);
1059 UASM_i_SRL(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
1060 if (r4k_250MHZhwbug())
1061 UASM_i_MTC0(p, 0, C0_ENTRYLO0);
1062 UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
1063 UASM_i_SRL(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
1064 if (r45k_bvahwbug())
1065 uasm_i_mfc0(p, tmp, C0_INDEX);
1066 }
1067 if (r4k_250MHZhwbug()) 1053 if (r4k_250MHZhwbug())
1068 UASM_i_MTC0(p, 0, C0_ENTRYLO1); 1054 UASM_i_MTC0(p, 0, C0_ENTRYLO1);
1069 UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ 1055 UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
1070#endif
1071} 1056}
1072 1057
1073struct mips_huge_tlb_info { 1058struct mips_huge_tlb_info {
@@ -2299,6 +2284,10 @@ static void config_htw_params(void)
2299 /* re-initialize the PTI field including the even/odd bit */ 2284 /* re-initialize the PTI field including the even/odd bit */
2300 pwfield &= ~MIPS_PWFIELD_PTI_MASK; 2285 pwfield &= ~MIPS_PWFIELD_PTI_MASK;
2301 pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT; 2286 pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
2287 if (CONFIG_PGTABLE_LEVELS >= 3) {
2288 pwfield &= ~MIPS_PWFIELD_MDI_MASK;
2289 pwfield |= PMD_SHIFT << MIPS_PWFIELD_MDI_SHIFT;
2290 }
2302 /* Set the PTEI right shift */ 2291 /* Set the PTEI right shift */
2303 ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT; 2292 ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
2304 pwfield |= ptei; 2293 pwfield |= ptei;
@@ -2320,9 +2309,11 @@ static void config_htw_params(void)
2320 2309
2321 pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT; 2310 pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
2322 pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT; 2311 pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
2312 if (CONFIG_PGTABLE_LEVELS >= 3)
2313 pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
2323 2314
2324 /* If XPA has been enabled, PTEs are 64-bit in size. */ 2315 /* If XPA has been enabled, PTEs are 64-bit in size. */
2325 if (read_c0_pagegrain() & PG_ELPA) 2316 if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
2326 pwsize |= 1; 2317 pwsize |= 1;
2327 2318
2328 write_c0_pwsize(pwsize); 2319 write_c0_pwsize(pwsize);
@@ -2360,6 +2351,41 @@ static void config_xpa_params(void)
2360#endif 2351#endif
2361} 2352}
2362 2353
2354static void check_pabits(void)
2355{
2356 unsigned long entry;
2357 unsigned pabits, fillbits;
2358
2359 if (!cpu_has_rixi || !_PAGE_NO_EXEC) {
2360 /*
2361 * We'll only be making use of the fact that we can rotate bits
2362 * into the fill if the CPU supports RIXI, so don't bother
2363 * probing this for CPUs which don't.
2364 */
2365 return;
2366 }
2367
2368 write_c0_entrylo0(~0ul);
2369 back_to_back_c0_hazard();
2370 entry = read_c0_entrylo0();
2371
2372 /* clear all non-PFN bits */
2373 entry &= ~((1 << MIPS_ENTRYLO_PFN_SHIFT) - 1);
2374 entry &= ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
2375
2376 /* find a lower bound on PABITS, and upper bound on fill bits */
2377 pabits = fls_long(entry) + 6;
2378 fillbits = max_t(int, (int)BITS_PER_LONG - pabits, 0);
2379
2380 /* minus the RI & XI bits */
2381 fillbits -= min_t(unsigned, fillbits, 2);
2382
2383 if (fillbits >= ilog2(_PAGE_NO_EXEC))
2384 fill_includes_sw_bits = true;
2385
2386 pr_debug("Entry* registers contain %u fill bits\n", fillbits);
2387}
2388
2363void build_tlb_refill_handler(void) 2389void build_tlb_refill_handler(void)
2364{ 2390{
2365 /* 2391 /*
@@ -2370,6 +2396,7 @@ void build_tlb_refill_handler(void)
2370 static int run_once = 0; 2396 static int run_once = 0;
2371 2397
2372 output_pgtable_bits_defines(); 2398 output_pgtable_bits_defines();
2399 check_pabits();
2373 2400
2374#ifdef CONFIG_64BIT 2401#ifdef CONFIG_64BIT
2375 check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); 2402 check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);