diff options
-rw-r--r-- | arch/powerpc/mm/slb.c | 45 |
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 | ||
72 | static inline void create_shadowed_slbe(unsigned long ea, unsigned long flags, | 72 | static 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 | ||
88 | void slb_flush_and_rebolt(void) | 77 | void 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 | } |