Loading arch/mips/mm/tlbex.c +25 −1 Original line number Diff line number Diff line Loading @@ -57,6 +57,21 @@ static __init int __maybe_unused r10000_llsc_war(void) return R10000_LLSC_WAR; } /* * Found by experiment: At least some revisions of the 4kc throw under * some circumstances a machine check exception, triggered by invalid * values in the index register. Delaying the tlbp instruction until * after the next branch, plus adding an additional nop in front of * tlbwi/tlbwr avoids the invalid index register values. Nobody knows * why; it's not an issue caused by the core RTL. * */ static __init int __attribute__((unused)) m4kc_tlbp_war(void) { return (current_cpu_data.processor_id & 0xffff00) == (PRID_COMP_MIPS | PRID_IMP_4KC); } /* * A little micro-assembler, intended for TLB refill handler * synthesizing. It is intentionally kept simple, does only support Loading Loading @@ -894,6 +909,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, case CPU_20KC: case CPU_25KF: case CPU_LOONGSON2: if (m4kc_tlbp_war()) i_nop(p); tlbw(p); break; Loading Loading @@ -1705,6 +1722,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l, l_smp_pgtable_change(l, *p); # endif iPTE_LW(p, l, pte, ptr); /* get even pte */ if (!m4kc_tlbp_war()) build_tlb_probe_entry(p); } Loading Loading @@ -1747,6 +1765,8 @@ static void __init build_r4000_tlb_load_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); build_make_valid(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading Loading @@ -1781,6 +1801,8 @@ static void __init build_r4000_tlb_store_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); build_make_write(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading Loading @@ -1815,6 +1837,8 @@ static void __init build_r4000_tlb_modify_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); /* Present and writable bits set, set accessed and dirty bits. */ build_make_write(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading Loading
arch/mips/mm/tlbex.c +25 −1 Original line number Diff line number Diff line Loading @@ -57,6 +57,21 @@ static __init int __maybe_unused r10000_llsc_war(void) return R10000_LLSC_WAR; } /* * Found by experiment: At least some revisions of the 4kc throw under * some circumstances a machine check exception, triggered by invalid * values in the index register. Delaying the tlbp instruction until * after the next branch, plus adding an additional nop in front of * tlbwi/tlbwr avoids the invalid index register values. Nobody knows * why; it's not an issue caused by the core RTL. * */ static __init int __attribute__((unused)) m4kc_tlbp_war(void) { return (current_cpu_data.processor_id & 0xffff00) == (PRID_COMP_MIPS | PRID_IMP_4KC); } /* * A little micro-assembler, intended for TLB refill handler * synthesizing. It is intentionally kept simple, does only support Loading Loading @@ -894,6 +909,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, case CPU_20KC: case CPU_25KF: case CPU_LOONGSON2: if (m4kc_tlbp_war()) i_nop(p); tlbw(p); break; Loading Loading @@ -1705,6 +1722,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l, l_smp_pgtable_change(l, *p); # endif iPTE_LW(p, l, pte, ptr); /* get even pte */ if (!m4kc_tlbp_war()) build_tlb_probe_entry(p); } Loading Loading @@ -1747,6 +1765,8 @@ static void __init build_r4000_tlb_load_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); build_make_valid(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading Loading @@ -1781,6 +1801,8 @@ static void __init build_r4000_tlb_store_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); build_make_write(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading Loading @@ -1815,6 +1837,8 @@ static void __init build_r4000_tlb_modify_handler(void) build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); /* Present and writable bits set, set accessed and dirty bits. */ build_make_write(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); Loading