aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2010-03-21 15:51:52 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-03-23 00:36:21 -0400
commitb5b6c7eea1124de5b110a48ac62650a690ed2419 (patch)
treed87983aa0d009f6cfc5813f67bc4beffbd4fadf2
parenta9eb4f6d1a168c830a206306dfbb1f95a7fed6b3 (diff)
sh: Replace unsafe manipulation of MMUCR
Setting the TI in MMUCR causes all the TLB bits in MMUCR to be cleared. Unfortunately, the TLB wired bits are also cleared when setting the TI bit, causing any wired TLB entries to become unwired. Use local_flush_tlb_all() which implements TLB flushing in a safer manner by using the memory-mapped TLB registers. As each CPU has its own PMB the modifications in pmb_init() only affect the local CPU, so only flush the local CPU's TLB. Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/mm/pmb.c2
-rw-r--r--arch/sh/mm/tlbflush_32.c21
2 files changed, 16 insertions, 7 deletions
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index a4662e2782c..0b14dcf05da 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -802,7 +802,7 @@ void __init pmb_init(void)
802 writel_uncached(0, PMB_IRMCR); 802 writel_uncached(0, PMB_IRMCR);
803 803
804 /* Flush out the TLB */ 804 /* Flush out the TLB */
805 __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR); 805 local_flush_tlb_all();
806 ctrl_barrier(); 806 ctrl_barrier();
807} 807}
808 808
diff --git a/arch/sh/mm/tlbflush_32.c b/arch/sh/mm/tlbflush_32.c
index 004bb3f25b5..77dc5efa712 100644
--- a/arch/sh/mm/tlbflush_32.c
+++ b/arch/sh/mm/tlbflush_32.c
@@ -123,18 +123,27 @@ void local_flush_tlb_mm(struct mm_struct *mm)
123void local_flush_tlb_all(void) 123void local_flush_tlb_all(void)
124{ 124{
125 unsigned long flags, status; 125 unsigned long flags, status;
126 int i;
126 127
127 /* 128 /*
128 * Flush all the TLB. 129 * Flush all the TLB.
129 *
130 * Write to the MMU control register's bit:
131 * TF-bit for SH-3, TI-bit for SH-4.
132 * It's same position, bit #2.
133 */ 130 */
134 local_irq_save(flags); 131 local_irq_save(flags);
132 jump_to_uncached();
133
135 status = __raw_readl(MMUCR); 134 status = __raw_readl(MMUCR);
136 status |= 0x04; 135 status = ((status & MMUCR_URB) >> MMUCR_URB_SHIFT);
137 __raw_writel(status, MMUCR); 136
137 if (status == 0)
138 status = MMUCR_URB_NENTRIES;
139
140 for (i = 0; i < status; i++)
141 __raw_writel(0x0, MMU_UTLB_ADDRESS_ARRAY | (i << 8));
142
143 for (i = 0; i < 4; i++)
144 __raw_writel(0x0, MMU_ITLB_ADDRESS_ARRAY | (i << 8));
145
146 back_to_cached();
138 ctrl_barrier(); 147 ctrl_barrier();
139 local_irq_restore(flags); 148 local_irq_restore(flags);
140} 149}