Christophe Leroy <christophe.le...@csgroup.eu> writes:
> __set_pte_at() handles 3 main cases with #ifdefs plus the 'percpu'
> subcase which leads to code duplication.
>
> Rewrite the function using IS_ENABLED() to minimise the total number
> of cases and remove duplicated code.

I think the code change is good, but the comment becomes completely
misleading. Because it talks about "the first case" etc., but then the
code is structured differently.

cheers

> diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h 
> b/arch/powerpc/include/asm/book3s/32/pgtable.h
> index 40041ac713d9..2a0ca1f9a1ff 100644
> --- a/arch/powerpc/include/asm/book3s/32/pgtable.h
> +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
> @@ -534,58 +534,43 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t 
> newprot)
>  
>  
>  /* This low level function performs the actual PTE insertion
> - * Setting the PTE depends on the MMU type and other factors. It's
> - * an horrible mess that I'm not going to try to clean up now but
> - * I'm keeping it in one place rather than spread around
> + * Setting the PTE depends on the MMU type and other factors.
> + *
> + * First case is 32-bit Hash MMU in SMP mode with 32-bit PTEs. We use the
> + * helper pte_update() which does an atomic update. We need to do that
> + * because a concurrent invalidation can clear _PAGE_HASHPTE. If it's a
> + * per-CPU PTE such as a kmap_atomic, we do a simple update preserving
> + * the hash bits instead (ie, same as the non-SMP case)
> + *
> + * Second case is 32-bit with 64-bit PTE.  In this case, we
> + * can just store as long as we do the two halves in the right order
> + * with a barrier in between. This is possible because we take care,
> + * in the hash code, to pre-invalidate if the PTE was already hashed,
> + * which synchronizes us with any concurrent invalidation.
> + * In the percpu case, we also fallback to the simple update preserving
> + * the hash bits
> + *
> + * Third case is 32-bit hash table in UP mode, we need to preserve
> + * the _PAGE_HASHPTE bit since we may not have invalidated the previous
> + * translation in the hash yet (done in a subsequent flush_tlb_xxx())
> + * and see we need to keep track that this PTE needs invalidating
>   */
>  static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>                               pte_t *ptep, pte_t pte, int percpu)
>  {
> -#if defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
> -     /* First case is 32-bit Hash MMU in SMP mode with 32-bit PTEs. We use 
> the
> -      * helper pte_update() which does an atomic update. We need to do that
> -      * because a concurrent invalidation can clear _PAGE_HASHPTE. If it's a
> -      * per-CPU PTE such as a kmap_atomic, we do a simple update preserving
> -      * the hash bits instead (ie, same as the non-SMP case)
> -      */
> -     if (percpu)
> -             *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
> -                           | (pte_val(pte) & ~_PAGE_HASHPTE));
> -     else
> -             pte_update(mm, addr, ptep, ~_PAGE_HASHPTE, pte_val(pte), 0);
> +     if ((!IS_ENABLED(CONFIG_SMP) && !IS_ENABLED(CONFIG_PTE_64BIT)) || 
> percpu) {
> +             *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE) |
> +                           (pte_val(pte) & ~_PAGE_HASHPTE));
> +     } else if (IS_ENABLED(CONFIG_PTE_64BIT)) {
> +             if (pte_val(*ptep) & _PAGE_HASHPTE)
> +                     flush_hash_entry(mm, ptep, addr);
>  
> -#elif defined(CONFIG_PTE_64BIT)
> -     /* Second case is 32-bit with 64-bit PTE.  In this case, we
> -      * can just store as long as we do the two halves in the right order
> -      * with a barrier in between. This is possible because we take care,
> -      * in the hash code, to pre-invalidate if the PTE was already hashed,
> -      * which synchronizes us with any concurrent invalidation.
> -      * In the percpu case, we also fallback to the simple update preserving
> -      * the hash bits
> -      */
> -     if (percpu) {
> -             *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
> -                           | (pte_val(pte) & ~_PAGE_HASHPTE));
> -             return;
> +             asm volatile("stw%X0 %2,%0; eieio; stw%X1 %L2,%1" :
> +                          "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) :
> +                          "r" (pte) : "memory");
> +     } else {
> +             pte_update(mm, addr, ptep, ~_PAGE_HASHPTE, pte_val(pte), 0);
>       }
> -     if (pte_val(*ptep) & _PAGE_HASHPTE)
> -             flush_hash_entry(mm, ptep, addr);
> -     __asm__ __volatile__("\
> -             stw%X0 %2,%0\n\
> -             eieio\n\
> -             stw%X1 %L2,%1"
> -     : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
> -     : "r" (pte) : "memory");
> -
> -#else
> -     /* Third case is 32-bit hash table in UP mode, we need to preserve
> -      * the _PAGE_HASHPTE bit since we may not have invalidated the previous
> -      * translation in the hash yet (done in a subsequent flush_tlb_xxx())
> -      * and see we need to keep track that this PTE needs invalidating
> -      */
> -     *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
> -                   | (pte_val(pte) & ~_PAGE_HASHPTE));
> -#endif
>  }
>  
>  /*
> -- 
> 2.36.1

Reply via email to