smp_wmb();
 }
 
-static inline void create_shadowed_slbe(unsigned long ea, unsigned long flags,
-                                       unsigned long entry)
+static inline void slb_shadow_clear(unsigned long entry)
 {
-       /*
-        * Updating the shadow buffer before writing the SLB ensures
-        * we don't get a stale entry here if we get preempted by PHYP
-        * between these two statements.
-        */
-       slb_shadow_update(ea, flags, entry);
-
-       asm volatile("slbmte  %0,%1" :
-                    : "r" (mk_vsid_data(ea, flags)),
-                      "r" (mk_esid_data(ea, entry))
-                    : "memory" );
+       get_slb_shadow()->save_area[entry].esid = 0;
 }
 
 void slb_flush_and_rebolt(void)
        vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
        ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
-       if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET)
+       if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) {
                ksp_esid_data &= ~SLB_ESID_V;
-
-       /* Only third entry (stack) may change here so only resave that */
-       slb_shadow_update(get_paca()->kstack, lflags, 2);
+               slb_shadow_clear(2);
+       } else {
+               /* Update stack entry; others don't change */
+               slb_shadow_update(get_paca()->kstack, lflags, 2);
+       }
 
        /* We need to do this all in asm, so we're sure we don't touch
         * the stack between the slbia and rebolting it. */
        vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
        /* Invalidate the entire SLB (even slot 0) & all the ERATS */
-       asm volatile("isync":::"memory");
-       asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
-       asm volatile("isync; slbia; isync":::"memory");
-       create_shadowed_slbe(PAGE_OFFSET, lflags, 0);
-
-       create_shadowed_slbe(VMALLOC_START, vflags, 1);
-
-       /* We don't bolt the stack for the time being - we're in boot,
-        * so the stack is in the bolted segment.  By the time it goes
-        * elsewhere, we'll call _switch() which will bolt in the new
-        * one. */
-       asm volatile("isync":::"memory");
+       slb_shadow_update(PAGE_OFFSET, lflags, 0);
+       asm volatile("isync; slbia; sync; slbmte  %0,%1; isync" ::
+                    "r" (get_slb_shadow()->save_area[0].vsid),
+                    "r" (get_slb_shadow()->save_area[0].esid) : "memory");
+
+       slb_shadow_update(VMALLOC_START, vflags, 1);
+
+       slb_flush_and_rebolt();
 }