|
9 | 9 | */
|
10 | 10 | #include <linux/init.h>
|
11 | 11 | #include <linux/kernel.h>
|
| 12 | +#include <linux/mmu_context.h> |
12 | 13 | #include <linux/ptrace.h>
|
13 | 14 | #include <linux/smp.h>
|
14 | 15 | #include <linux/stddef.h>
|
|
37 | 38 | unsigned int elf_hwcap __read_mostly;
|
38 | 39 | EXPORT_SYMBOL_GPL(elf_hwcap);
|
39 | 40 |
|
| 41 | +static bool mmid_disabled_quirk; |
| 42 | + |
40 | 43 | static inline unsigned long cpu_get_msa_id(void)
|
41 | 44 | {
|
42 | 45 | unsigned long status, msa_id;
|
@@ -645,7 +648,7 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
|
645 | 648 | config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE);
|
646 | 649 |
|
647 | 650 | if (cpu_has_mips_r6) {
|
648 |
| - if (!__builtin_constant_p(cpu_has_mmid) || cpu_has_mmid) |
| 651 | + if (!mmid_disabled_quirk && (!__builtin_constant_p(cpu_has_mmid) || cpu_has_mmid)) |
649 | 652 | config5 |= MIPS_CONF5_MI;
|
650 | 653 | else
|
651 | 654 | config5 &= ~MIPS_CONF5_MI;
|
@@ -708,7 +711,6 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
|
708 | 711 | max_mmid_width);
|
709 | 712 | asid_mask = GENMASK(max_mmid_width - 1, 0);
|
710 | 713 | }
|
711 |
| - |
712 | 714 | set_cpu_asid_mask(c, asid_mask);
|
713 | 715 | }
|
714 | 716 | }
|
@@ -2046,3 +2048,39 @@ void cpu_set_vpe_id(struct cpuinfo_mips *cpuinfo, unsigned int vpe)
|
2046 | 2048 | cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_VP;
|
2047 | 2049 | cpuinfo->globalnumber |= vpe << MIPS_GLOBALNUMBER_VP_SHF;
|
2048 | 2050 | }
|
| 2051 | + |
| 2052 | +void cpu_disable_mmid(void) |
| 2053 | +{ |
| 2054 | + int i; |
| 2055 | + unsigned long asid_mask; |
| 2056 | + unsigned int cpu = smp_processor_id(); |
| 2057 | + struct cpuinfo_mips *c = ¤t_cpu_data; |
| 2058 | + unsigned int config4 = read_c0_config4(); |
| 2059 | + unsigned int config5 = read_c0_config5(); |
| 2060 | + |
| 2061 | + /* Setup the initial ASID mask based on config4 */ |
| 2062 | + asid_mask = MIPS_ENTRYHI_ASID; |
| 2063 | + if (config4 & MIPS_CONF4_AE) |
| 2064 | + asid_mask |= MIPS_ENTRYHI_ASIDX; |
| 2065 | + set_cpu_asid_mask(c, asid_mask); |
| 2066 | + |
| 2067 | + /* Disable MMID in the C0 and update cpuinfo_mips accordingly */ |
| 2068 | + config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE); |
| 2069 | + config5 &= ~MIPS_CONF5_MI; |
| 2070 | + write_c0_config5(config5); |
| 2071 | + /* Ensure the write to config5 above takes effect */ |
| 2072 | + back_to_back_c0_hazard(); |
| 2073 | + c->options &= ~MIPS_CPU_MMID; |
| 2074 | + |
| 2075 | + /* Setup asid cache value cleared in per_cpu_trap_init() */ |
| 2076 | + cpu_data[cpu].asid_cache = asid_first_version(cpu); |
| 2077 | + |
| 2078 | + /* Reinit context for each CPU */ |
| 2079 | + for_each_possible_cpu(i) |
| 2080 | + set_cpu_context(i, &init_mm, 0); |
| 2081 | + |
| 2082 | + /* Ensure that now MMID will be seen as disable */ |
| 2083 | + mmid_disabled_quirk = true; |
| 2084 | + |
| 2085 | + pr_info("MMID support disabled due to hardware support issue\n"); |
| 2086 | +} |
0 commit comments