Skip to content

Commit 07f8888

Browse files
gclementtsbogend
authored andcommitted
MIPS: disable MMID when not supported by the hardware
It is possible that MMID is supported at the CPU level, but its integration in a SoC prevents its usage. For instance, if the System-level Interconnect (also known as Network on Chip) does not support global invalidation, then the MMID feature is not usable. The current implementation of MMID relies on the GINV* instructions. This patch allows the disabling of MMID based on a device tree property, as this issue cannot be detected at runtime. MMID is set up very early during the boot process, even before device tree data can be accessed. Therefore, when we determine whether MMID needs to be disabled, some MMID setup has already been performed for the boot CPU. Consequently, we must revert the MMID setup on the first CPU before disabling the feature for the subsequent CPUs that will be initialized later. Signed-off-by: Gregory CLEMENT <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent ca94335 commit 07f8888

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

arch/mips/include/asm/cpu-info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ extern struct cpuinfo_mips cpu_data[];
123123

124124
extern void cpu_probe(void);
125125
extern void cpu_report(void);
126+
extern void cpu_disable_mmid(void);
126127

127128
extern const char *__cpu_name[];
128129
#define cpu_name_string() __cpu_name[raw_smp_processor_id()]

arch/mips/kernel/cpu-probe.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
#include <linux/init.h>
1111
#include <linux/kernel.h>
12+
#include <linux/mmu_context.h>
1213
#include <linux/ptrace.h>
1314
#include <linux/smp.h>
1415
#include <linux/stddef.h>
@@ -37,6 +38,8 @@
3738
unsigned int elf_hwcap __read_mostly;
3839
EXPORT_SYMBOL_GPL(elf_hwcap);
3940

41+
static bool mmid_disabled_quirk;
42+
4043
static inline unsigned long cpu_get_msa_id(void)
4144
{
4245
unsigned long status, msa_id;
@@ -645,7 +648,7 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
645648
config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE);
646649

647650
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))
649652
config5 |= MIPS_CONF5_MI;
650653
else
651654
config5 &= ~MIPS_CONF5_MI;
@@ -708,7 +711,6 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
708711
max_mmid_width);
709712
asid_mask = GENMASK(max_mmid_width - 1, 0);
710713
}
711-
712714
set_cpu_asid_mask(c, asid_mask);
713715
}
714716
}
@@ -2046,3 +2048,39 @@ void cpu_set_vpe_id(struct cpuinfo_mips *cpuinfo, unsigned int vpe)
20462048
cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_VP;
20472049
cpuinfo->globalnumber |= vpe << MIPS_GLOBALNUMBER_VP_SHF;
20482050
}
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 = &current_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+
}

arch/mips/kernel/mips-cm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ void mips_cm_update_property(void)
248248
return;
249249
pr_info("HCI (Hardware Cache Init for the L2 cache) in GCR_L2_RAM_CONFIG from the CM3 is broken");
250250
mips_cm_is_l2_hci_broken = true;
251+
252+
/* Disable MMID only if it was configured */
253+
if (cpu_has_mmid)
254+
cpu_disable_mmid();
255+
251256
of_node_put(cm_node);
252257
}
253258

0 commit comments

Comments
 (0)