Building on 32 bits with pmd_leaf() not returning always false leads
to the following error:

  CC      arch/powerpc/mm/pgtable.o
arch/powerpc/mm/pgtable.c: In function '__find_linux_pte':
arch/powerpc/mm/pgtable.c:506:1: error: function may return address of local 
variable [-Werror=return-local-addr]
  506 | }
      | ^
arch/powerpc/mm/pgtable.c:394:15: note: declared here
  394 |         pud_t pud, *pudp;
      |               ^~~
arch/powerpc/mm/pgtable.c:394:15: note: declared here

This is due to pmd_offset() being a no-op in that case.

So rework it for powerpc/32 so that pXd_offset() are used on real
pointers and not on on-stack copies.

Behind fixing the problem, it also has the advantage of simplifying
__find_linux_pte() including the removal of stack frame:

After this patch:

        00000018 <__find_linux_pte>:
          18:   2c 06 00 00     cmpwi   r6,0
          1c:   41 82 00 0c     beq     28 <__find_linux_pte+0x10>
          20:   39 20 00 00     li      r9,0
          24:   91 26 00 00     stw     r9,0(r6)
          28:   2f 85 00 00     cmpwi   cr7,r5,0
          2c:   41 9e 00 0c     beq     cr7,38 <__find_linux_pte+0x20>
          30:   39 20 00 00     li      r9,0
          34:   99 25 00 00     stb     r9,0(r5)
          38:   54 89 65 3a     rlwinm  r9,r4,12,20,29
          3c:   7c 63 48 2e     lwzx    r3,r3,r9
          40:   2f 83 00 00     cmpwi   cr7,r3,0
          44:   41 9e 00 30     beq     cr7,74 <__find_linux_pte+0x5c>
          48:   54 69 07 3a     rlwinm  r9,r3,0,28,29
          4c:   2f 89 00 0c     cmpwi   cr7,r9,12
          50:   54 63 00 26     clrrwi  r3,r3,12
          54:   54 84 b5 36     rlwinm  r4,r4,22,20,27
          58:   3c 63 c0 00     addis   r3,r3,-16384
          5c:   7c 63 22 14     add     r3,r3,r4
          60:   4c be 00 20     bnelr+  cr7
          64:   4d 82 00 20     beqlr
          68:   39 20 00 17     li      r9,23
          6c:   91 26 00 00     stw     r9,0(r6)
          70:   4e 80 00 20     blr
          74:   38 60 00 00     li      r3,0
          78:   4e 80 00 20     blr

Before this patch:

        00000018 <__find_linux_pte>:
          18:   2c 06 00 00     cmpwi   r6,0
          1c:   94 21 ff e0     stwu    r1,-32(r1)
          20:   41 82 00 0c     beq     2c <__find_linux_pte+0x14>
          24:   39 20 00 00     li      r9,0
          28:   91 26 00 00     stw     r9,0(r6)
          2c:   2f 85 00 00     cmpwi   cr7,r5,0
          30:   41 9e 00 0c     beq     cr7,3c <__find_linux_pte+0x24>
          34:   39 20 00 00     li      r9,0
          38:   99 25 00 00     stb     r9,0(r5)
          3c:   54 89 65 3a     rlwinm  r9,r4,12,20,29
          40:   7c 63 48 2e     lwzx    r3,r3,r9
          44:   54 69 07 3a     rlwinm  r9,r3,0,28,29
          48:   2f 89 00 0c     cmpwi   cr7,r9,12
          4c:   90 61 00 0c     stw     r3,12(r1)
          50:   41 9e 00 4c     beq     cr7,9c <__find_linux_pte+0x84>
          54:   80 61 00 0c     lwz     r3,12(r1)
          58:   54 69 07 3a     rlwinm  r9,r3,0,28,29
          5c:   2f 89 00 0c     cmpwi   cr7,r9,12
          60:   90 61 00 08     stw     r3,8(r1)
          64:   41 9e 00 38     beq     cr7,9c <__find_linux_pte+0x84>
          68:   80 61 00 08     lwz     r3,8(r1)
          6c:   2f 83 00 00     cmpwi   cr7,r3,0
          70:   41 9e 00 54     beq     cr7,c4 <__find_linux_pte+0xac>
          74:   54 69 07 3a     rlwinm  r9,r3,0,28,29
          78:   2f 89 00 0c     cmpwi   cr7,r9,12
          7c:   54 69 00 26     clrrwi  r9,r3,12
          80:   54 8a b5 36     rlwinm  r10,r4,22,20,27
          84:   3c 69 c0 00     addis   r3,r9,-16384
          88:   7c 63 52 14     add     r3,r3,r10
          8c:   54 84 93 be     srwi    r4,r4,14
          90:   41 9e 00 14     beq     cr7,a4 <__find_linux_pte+0x8c>
          94:   38 21 00 20     addi    r1,r1,32
          98:   4e 80 00 20     blr
          9c:   54 69 00 26     clrrwi  r9,r3,12
          a0:   54 84 93 be     srwi    r4,r4,14
          a4:   3c 69 c0 00     addis   r3,r9,-16384
          a8:   54 84 25 36     rlwinm  r4,r4,4,20,27
          ac:   7c 63 22 14     add     r3,r3,r4
          b0:   41 a2 ff e4     beq     94 <__find_linux_pte+0x7c>
          b4:   39 20 00 17     li      r9,23
          b8:   91 26 00 00     stw     r9,0(r6)
          bc:   38 21 00 20     addi    r1,r1,32
          c0:   4e 80 00 20     blr
          c4:   38 60 00 00     li      r3,0
          c8:   38 21 00 20     addi    r1,r1,32
          cc:   4e 80 00 20     blr

Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu>
Reviewed-by: Oscar Salvador <osalva...@suse.de>
---
v3: Removed p4dp and pudp locals for PPC32 and add a comment.
v4: Properly set pdshift on PPC32 case
v5: Enhanced commit message
---
 arch/powerpc/mm/pgtable.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 9e7ba9c3851f..bce8a8619589 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -382,8 +382,10 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
                        bool *is_thp, unsigned *hpage_shift)
 {
        pgd_t *pgdp;
+#ifdef CONFIG_PPC64
        p4d_t p4d, *p4dp;
        pud_t pud, *pudp;
+#endif
        pmd_t pmd, *pmdp;
        pte_t *ret_pte;
        hugepd_t *hpdp = NULL;
@@ -401,8 +403,12 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
         * page fault or a page unmap. The return pte_t * is still not
         * stable. So should be checked there for above conditions.
         * Top level is an exception because it is folded into p4d.
+        *
+        * On PPC32, P4D/PUD/PMD are folded into PGD so go straight to
+        * PMD level.
         */
        pgdp = pgdir + pgd_index(ea);
+#ifdef CONFIG_PPC64
        p4dp = p4d_offset(pgdp, ea);
        p4d  = READ_ONCE(*p4dp);
        pdshift = P4D_SHIFT;
@@ -442,8 +448,11 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
                goto out_huge;
        }
 
-       pdshift = PMD_SHIFT;
        pmdp = pmd_offset(&pud, ea);
+#else
+       pmdp = pmd_offset(pud_offset(p4d_offset(pgdp, ea), ea), ea);
+#endif
+       pdshift = PMD_SHIFT;
        pmd  = READ_ONCE(*pmdp);
 
        /*
-- 
2.44.0

Reply via email to