On Fri, 2007-08-03 at 11:55 +1000, Michael Neuling wrote: > We sometimes change the vmalloc segment in slb_flush_and_rebolt but we > never updated with slb shadow buffer. This fixes it. Thanks to paulus > for finding this. > > Also added some write barriers to ensure the shadow buffer is always > valid. > > Signed-off-by: Michael Neuling <[EMAIL PROTECTED]>
Acked-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]> > --- > Integrated more comments from people. > > arch/powerpc/kernel/entry_64.S | 3 +++ > arch/powerpc/mm/hash_utils_64.c | 2 +- > arch/powerpc/mm/slb.c | 28 ++++++++++++++++++---------- > include/asm-powerpc/mmu-hash64.h | 1 + > 4 files changed, 23 insertions(+), 11 deletions(-) > > Index: linux-2.6-ozlabs/arch/powerpc/kernel/entry_64.S > =================================================================== > --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/entry_64.S > +++ linux-2.6-ozlabs/arch/powerpc/kernel/entry_64.S > @@ -389,8 +389,11 @@ BEGIN_FTR_SECTION > ld r9,PACA_SLBSHADOWPTR(r13) > li r12,0 > std r12,SLBSHADOW_STACKESID(r9) /* Clear ESID */ > + eieio > std r7,SLBSHADOW_STACKVSID(r9) /* Save VSID */ > + eieio > std r0,SLBSHADOW_STACKESID(r9) /* Save ESID */ > + eieio > > slbie r6 > slbie r6 /* Workaround POWER5 < DD2.1 issue */ > Index: linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c > =================================================================== > --- linux-2.6-ozlabs.orig/arch/powerpc/mm/hash_utils_64.c > +++ linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c > @@ -759,7 +759,7 @@ int hash_page(unsigned long ea, unsigned > mmu_psize_defs[mmu_vmalloc_psize].sllp) { > get_paca()->vmalloc_sllp = > mmu_psize_defs[mmu_vmalloc_psize].sllp; > - slb_flush_and_rebolt(); > + slb_vmalloc_update(); > } > #endif /* CONFIG_PPC_64K_PAGES */ > > Index: linux-2.6-ozlabs/arch/powerpc/mm/slb.c > =================================================================== > --- linux-2.6-ozlabs.orig/arch/powerpc/mm/slb.c > +++ linux-2.6-ozlabs/arch/powerpc/mm/slb.c > @@ -53,7 +53,8 @@ static inline unsigned long mk_vsid_data > return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags; > } > > -static inline void slb_shadow_update(unsigned long esid, unsigned long vsid, > +static inline void slb_shadow_update(unsigned long ea, > + unsigned long flags, > unsigned long entry) > { > /* > @@ -61,11 +62,11 @@ static inline void slb_shadow_update(uns > * updating it. > */ > get_slb_shadow()->save_area[entry].esid = 0; > - barrier(); > - get_slb_shadow()->save_area[entry].vsid = vsid; > - barrier(); > - get_slb_shadow()->save_area[entry].esid = esid; > - > + smp_wmb(); > + get_slb_shadow()->save_area[entry].vsid = mk_vsid_data(ea, flags); > + smp_wmb(); > + get_slb_shadow()->save_area[entry].esid = mk_esid_data(ea, entry); > + smp_wmb(); > } > > static inline void create_shadowed_slbe(unsigned long ea, unsigned long > flags, > @@ -76,8 +77,7 @@ static inline void create_shadowed_slbe( > * we don't get a stale entry here if we get preempted by PHYP > * between these two statements. > */ > - slb_shadow_update(mk_esid_data(ea, entry), mk_vsid_data(ea, flags), > - entry); > + slb_shadow_update(ea, flags, entry); > > asm volatile("slbmte %0,%1" : > : "r" (mk_vsid_data(ea, flags)), > @@ -104,8 +104,7 @@ void slb_flush_and_rebolt(void) > ksp_esid_data &= ~SLB_ESID_V; > > /* Only third entry (stack) may change here so only resave that */ > - slb_shadow_update(ksp_esid_data, > - mk_vsid_data(ksp_esid_data, lflags), 2); > + 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. */ > @@ -123,6 +122,15 @@ void slb_flush_and_rebolt(void) > : "memory"); > } > > +void slb_vmalloc_update(void) > +{ > + unsigned long vflags; > + > + vflags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmalloc_psize].sllp; > + slb_shadow_update(VMALLOC_START, vflags, 1); > + slb_flush_and_rebolt(); > +} > + > /* Flush all user entries from the segment table of the current processor. */ > void switch_slb(struct task_struct *tsk, struct mm_struct *mm) > { > Index: linux-2.6-ozlabs/include/asm-powerpc/mmu-hash64.h > =================================================================== > --- linux-2.6-ozlabs.orig/include/asm-powerpc/mmu-hash64.h > +++ linux-2.6-ozlabs/include/asm-powerpc/mmu-hash64.h > @@ -262,6 +262,7 @@ extern void slb_initialize(void); > extern void slb_flush_and_rebolt(void); > extern void stab_initialize(unsigned long stab); > > +extern void slb_vmalloc_update(void); > #endif /* __ASSEMBLY__ */ > > /* _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev