[PATCH] fixes for the SLB shadow buffer

Benjamin Herrenschmidt benh at kernel.crashing.org
Fri Aug 3 12:50:42 EST 2007


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 <mikey at neuling.org>

Acked-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>

> ---
> 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__ */
>  
>  /*




More information about the Linuxppc-dev mailing list