powerpc/e500: encode hugepage size in PTE bits
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Tue, 2 Jul 2024 13:51:29 +0000 (15:51 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 12 Jul 2024 22:52:18 +0000 (15:52 -0700)
Use PTE page size bits to encode hugepage size with the following format
corresponding to the values expected in bits 52-55 in MAS1 register.
Those bits are called TSIZE:
0001  4 Kbyte
0010  16 Kbyte
0011  64 Kbyte
0100  256 Kbyte
0101  1 Mbyte
0110  4 Mbyte
0111  16 Mbyte
1000  64 Mbyte
1001  256 Mbyte
1010  1 Gbyte
1011  4 Gbyte
1100  16 Gbyte
1101 64 Gbyte
1110 256 Gbyte
1111 1 Tbyte

It corresponds to shift value minus 10 with lowest bit removed.

It is not the value expected in the PTE in that field, but only e6500
performs HW based TLB loading and the e6500 reference manual explicitely
says that this field is ignored.

Also add pte_huge_size() which will be used later.

Link: https://lkml.kernel.org/r/6f7ce82fa8c381d55f65342d77060fc55802e612.1719928057.git.christophe.leroy@csgroup.eu
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Peter Xu <peterx@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
arch/powerpc/include/asm/nohash/hugetlb-e500.h
arch/powerpc/include/asm/nohash/pte-e500.h

index 8f04ad2..c6a0938 100644 (file)
@@ -42,4 +42,13 @@ static inline int check_and_get_huge_psize(int shift)
        return shift_to_mmu_psize(shift);
 }
 
+static inline pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
+{
+       unsigned int tsize = shift - _PAGE_PSIZE_SHIFT_OFFSET;
+       pte_basic_t val = (tsize << _PAGE_PSIZE_SHIFT) & _PAGE_PSIZE_MSK;
+
+       return __pte((pte_val(entry) & ~(pte_basic_t)_PAGE_PSIZE_MSK) | val);
+}
+#define arch_make_huge_pte arch_make_huge_pte
+
 #endif /* _ASM_POWERPC_NOHASH_HUGETLB_E500_H */
index 975facc..6dac1c0 100644 (file)
 #define _PAGE_BAP_SX   0x000040
 #define _PAGE_BAP_UX   0x000080
 #define _PAGE_PSIZE_MSK        0x000f00
-#define _PAGE_PSIZE_4K 0x000200
-#define _PAGE_PSIZE_8K 0x000300
-#define _PAGE_PSIZE_16K        0x000400
-#define _PAGE_PSIZE_32K        0x000500
-#define _PAGE_PSIZE_64K        0x000600
-#define _PAGE_PSIZE_128K       0x000700
-#define _PAGE_PSIZE_256K       0x000800
-#define _PAGE_PSIZE_512K       0x000900
-#define _PAGE_PSIZE_1M 0x000a00
-#define _PAGE_PSIZE_2M 0x000b00
-#define _PAGE_PSIZE_4M 0x000c00
-#define _PAGE_PSIZE_8M 0x000d00
-#define _PAGE_PSIZE_16M        0x000e00
-#define _PAGE_PSIZE_32M        0x000f00
+#define _PAGE_TSIZE_4K 0x000100
 #define _PAGE_DIRTY    0x001000 /* C: page changed */
 #define _PAGE_SW0      0x002000
 #define _PAGE_U3       0x004000
@@ -46,6 +33,9 @@
 #define _PAGE_NO_CACHE 0x400000 /* I: cache inhibit */
 #define _PAGE_WRITETHRU        0x800000 /* W: cache write-through */
 
+#define _PAGE_PSIZE_SHIFT              7
+#define _PAGE_PSIZE_SHIFT_OFFSET       10
+
 /* "Higher level" linux bit combinations */
 #define _PAGE_EXEC             (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */
 #define _PAGE_READ             (_PAGE_BAP_SR | _PAGE_BAP_UR) /* User read permission */
@@ -87,7 +77,7 @@
  * pages. We always set _PAGE_COHERENT when SMP is enabled or
  * the processor might need it for DMA coherency.
  */
-#define _PAGE_BASE_NC  (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE_4K)
+#define _PAGE_BASE_NC  (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_TSIZE_4K)
 #if defined(CONFIG_SMP)
 #define _PAGE_BASE     (_PAGE_BASE_NC | _PAGE_COHERENT)
 #else
@@ -103,6 +93,14 @@ static inline pte_t pte_mkexec(pte_t pte)
 }
 #define pte_mkexec pte_mkexec
 
+static inline unsigned long pte_huge_size(pte_t pte)
+{
+       pte_basic_t val = pte_val(pte);
+
+       return 1UL << (((val & _PAGE_PSIZE_MSK) >> _PAGE_PSIZE_SHIFT) + _PAGE_PSIZE_SHIFT_OFFSET);
+}
+#define pte_huge_size pte_huge_size
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */