aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/slb.c45
1 files changed, 16 insertions, 29 deletions
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index b0697017d0e8..a73d2d700973 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -69,20 +69,9 @@ static inline void slb_shadow_update(unsigned long ea,
69 smp_wmb(); 69 smp_wmb();
70} 70}
71 71
72static inline void create_shadowed_slbe(unsigned long ea, unsigned long flags, 72static inline void slb_shadow_clear(unsigned long entry)
73 unsigned long entry)
74{ 73{
75 /* 74 get_slb_shadow()->save_area[entry].esid = 0;
76 * Updating the shadow buffer before writing the SLB ensures
77 * we don't get a stale entry here if we get preempted by PHYP
78 * between these two statements.
79 */
80 slb_shadow_update(ea, flags, entry);
81
82 asm volatile("slbmte %0,%1" :
83 : "r" (mk_vsid_data(ea, flags)),
84 "r" (mk_esid_data(ea, entry))
85 : "memory" );
86} 75}
87 76
88void slb_flush_and_rebolt(void) 77void slb_flush_and_rebolt(void)
@@ -100,11 +89,13 @@ void slb_flush_and_rebolt(void)
100 vflags = SLB_VSID_KERNEL | vmalloc_llp; 89 vflags = SLB_VSID_KERNEL | vmalloc_llp;
101 90
102 ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); 91 ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
103 if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) 92 if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) {
104 ksp_esid_data &= ~SLB_ESID_V; 93 ksp_esid_data &= ~SLB_ESID_V;
105 94 slb_shadow_clear(2);
106 /* Only third entry (stack) may change here so only resave that */ 95 } else {
107 slb_shadow_update(get_paca()->kstack, lflags, 2); 96 /* Update stack entry; others don't change */
97 slb_shadow_update(get_paca()->kstack, lflags, 2);
98 }
108 99
109 /* We need to do this all in asm, so we're sure we don't touch 100 /* We need to do this all in asm, so we're sure we don't touch
110 * the stack between the slbia and rebolting it. */ 101 * the stack between the slbia and rebolting it. */
@@ -235,16 +226,12 @@ void slb_initialize(void)
235 vflags = SLB_VSID_KERNEL | vmalloc_llp; 226 vflags = SLB_VSID_KERNEL | vmalloc_llp;
236 227
237 /* Invalidate the entire SLB (even slot 0) & all the ERATS */ 228 /* Invalidate the entire SLB (even slot 0) & all the ERATS */
238 asm volatile("isync":::"memory"); 229 slb_shadow_update(PAGE_OFFSET, lflags, 0);
239 asm volatile("slbmte %0,%0"::"r" (0) : "memory"); 230 asm volatile("isync; slbia; sync; slbmte %0,%1; isync" ::
240 asm volatile("isync; slbia; isync":::"memory"); 231 "r" (get_slb_shadow()->save_area[0].vsid),
241 create_shadowed_slbe(PAGE_OFFSET, lflags, 0); 232 "r" (get_slb_shadow()->save_area[0].esid) : "memory");
242 233
243 create_shadowed_slbe(VMALLOC_START, vflags, 1); 234 slb_shadow_update(VMALLOC_START, vflags, 1);
244 235
245 /* We don't bolt the stack for the time being - we're in boot, 236 slb_flush_and_rebolt();
246 * so the stack is in the bolted segment. By the time it goes
247 * elsewhere, we'll call _switch() which will bolt in the new
248 * one. */
249 asm volatile("isync":::"memory");
250} 237}