Skip to contentSkip to conversation

PPC32 : Huge-page support for ppc440 - 2.6.19-rc4 - revised

PATCH In review Edi Shmueli 2 participants 4 messages Dec 1, 2006 – Dec 12, 2006

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 PPC32 : Huge-page support for ppc440 - 2.6.19-rc4 - revised

From: Edi Shmueli <[email protected]>

Following requests to test the patch under the latest kernel, here it is again, tested for 2.6.19-rc4. This patch enables applications to exploit the PPC440 TLB support for huge-page mapping, to minimize TLB thrashing. Applications with large memory footprint that exploit this support, experience minimal TLB misses, and boost in performance. NAS benchmarks tested with this patch indicate hundreds of percent of improvement in performance.

-----

Benchmarks and Implementation comments
======================================
Below is the NAS IS benchmark results, executing under Linux, with and without this huge-page mapping support.
IS Benchmark 4KB pages 16MB pages
=======================================================

 Class             =   A                     A
 Size              =   8388608               8388608
 Iterations        =   10                    10
 Time in seconds   =   24.44                 6.38
 Mop/s total       =   3.43                  13.15
 Operation type    =   keys ranked           keys ranked
 Verification      =   SUCCESSFUL            SUCCESSFUL

Implementation details:
=======================
This patch is ppc440 architecture-specific. It enables the use of huge-pages by processes executing under the 2.6.16 kernel on the ppc440 processors.
Huge-pages are accessible to user processes using either the hugetlbfs or using shared memory. See Documentation/vs/hugetlbpage.txt.
==
The ppc 32bit kernel uses 64bit PTEs (set by CONFIG_PTE_64BIT).
I exploit a "hole" of 4 unused bits in the PTE MS word (bits 24-27) and code the page size information in those bits.
I then modified the TLB miss handler (head_44x.S) to stop using the constant PPC44x_TLB_4K to set the page size in the TLB.
Instead, when a TLB miss happens, the miss handler reads the size information from the PTE and sets that size in the TLB entry.
This way, different TLB entries get to map different page sizes (e.g., 4KB or 16MB).
The TLB replacement policy remains RR. This means that a huge-page entry in the TLB may be overwritten if not used for a long time, but when accessed it will be set again by the TLB miss handler, with the correct size, as set in the PTE. ==
In arch/ppc/mm/hugetlbpage.c is where page table entries are set to map huge pages:
By default , each process has two-level page-tables. It has 2048, 32bit PMD (or PGD) entries at the higher-level, each maps 2MB of the process address spase, and 512, 64bit PTE entries in each lower-level page table. When a TLB miss happens and no PTE is found by the miss handler to offer the translation, a check is made (memory.c) on whether the faulting address belongs to a huge-page VM region.
If so, the code in set_huge_pte_at() will set the required number of PMDs (e.g.,8 PMDs for huge-pages of size 16MB, or 1 PMD for huge-pages of size 2MB or less) to point to the *same* lower-level PTE page table. Within the lower-level page table, it will set the required number PTEs (e.g., all 512 PTEs for huge-pages larger than 2MB, or 256 PTEs for huge-pages of size 1MB etc.) to point to the *same* physical huge-page frame. All these PTEs will be *identical* and have the page-size coded in their MS word as described above.
==
Once the TLB miss handler copies the mapping (and the size) from the PTE into on of a TLB entry, the process will not suffer any TLB misses for that huge-page.
If the mapping was overwritten by the TLB RR replacement policy, it will be re-loaded again (probably in a different TLB entry) when the process re-access that huge-page.

arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 renamed from arch/ppc/kernel/head_44x.S 2006-11-14 11:16:29.000000000 -0500 +14 -9
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/kernel/head_44x.S my_linux/arch/ppc/kernel/head_44x.S
@@ -21,12 +21,14 @@
  *            [email protected]
  *    Copyright 2002-2005 MontaVista Software, Inc.
  *      PowerPC 44x support, Matt Porter <[email protected]>
+ *    Copyright (C) 2006 Edi Shmueli, IBM Corporation.
+ *    PowerPC 44x handling of huge-page misses.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
- */
+*/
 
 #include <asm/processor.h>
 #include <asm/page.h>
@@ -654,19 +656,22 @@ finish_tlb_load:
     lis    r11, tlb_44x_index@ha
     stw    r13, tlb_44x_index@l(r11)
 
-    lwz    r11, 0(r12)            /* Get MS word of PTE */
-    lwz    r12, 4(r12)            /* Get LS word of PTE */
-    rlwimi    r11, r12, 0, 0 , 19        /* Insert RPN */
-    tlbwe    r11, r13, PPC44x_TLB_XLAT    /* Write XLAT */
-
+    /*huge-page support*/
     /*
      * Create PAGEID. This is the faulting address,
      * page size, and valid flag.
-     */
-    li    r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
-    rlwimi    r10, r11, 0, 20, 31        /* Insert valid and page size */
+    */
+    lwz    r11, 0(r12)            /* Get MS word of PTE */
+    andi.   r11, r11, 0x000000F0        /* Leave only the size */
+    ori     r11, r11, PPC44x_TLB_VALID | PPC44x_TLB_4K /* Insert valid and page size */
+    rlwimi    r10, r11, 0, 20, 31        /* Combine EA from r10 with flags from r11 */
     tlbwe    r10, r13, PPC44x_TLB_PAGEID    /* Write PAGEID */
 
+    lwz    r11, 0(r12)            /* Get MS word of PTE */
+    lwz    r12, 4(r12)            /* Get LS word of PTE */
+    rlwimi    r11, r12, 0, 0 , 19        /* Insert RPN */
+    tlbwe    r11, r13, PPC44x_TLB_XLAT    /* Write XLAT */
+
     li    r10, PPC44x_TLB_SR@l        /* Set SR */
     rlwimi    r10, r12, 0, 30, 30        /* Set SW = _PAGE_RW */
     rlwimi    r10, r12, 29, 29, 29        /* SX = _PAGE_HWEXEC */
arch/ppc/mm/hugetlbpage.c 2006-11-15 11:44:43.297682864 -0500 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +185 -0

185 lines not on this page · raw message

arch/ppc/mm/Makefile 2006-11-06 09:52:41.000000000 -0500 renamed from arch/ppc/mm/Makefile 2006-11-14 11:16:29.000000000 -0500 +1 -0
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/mm/Makefile my_linux/arch/ppc/mm/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_PPC_STD_MMU)    += hashtable.o
 obj-$(CONFIG_40x)        += 4xx_mmu.o
 obj-$(CONFIG_44x)        += 44x_mmu.o
 obj-$(CONFIG_FSL_BOOKE)        += fsl_booke_mmu.o
+obj-$(CONFIG_HUGETLB_PAGE)      += hugetlbpage.o
fs/Kconfig 2006-11-14 17:26:13.000000000 -0500 renamed from fs/Kconfig 2006-11-14 11:17:37.000000000 -0500 +1 -1
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/fs/Kconfig my_linux/fs/Kconfig
@@ -1008,7 +1008,7 @@ config TMPFS_POSIX_ACL
 
 config HUGETLBFS
     bool "HugeTLB file system support"
-    depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+    depends X86 || IA64 || PPC || PPC64 || SPARC64 || SUPERH || BROKEN
     help
       hugetlbfs is a filesystem backing for HugeTLB pages, based on
       ramfs. For architectures that support it, say Y here and read
include/asm-ppc/page.h 2006-11-14 17:26:14.000000000 -0500 renamed from include/asm-ppc/page.h 2006-11-14 11:18:00.000000000 -0500 +6 -0
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/asm-ppc/page.h my_linux/include/asm-ppc/page.h
@@ -7,6 +7,12 @@
 #define PAGE_SHIFT    12
 #define PAGE_SIZE    (ASM_CONST(1) << PAGE_SHIFT)
 
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT     24
+#define HPAGE_SIZE      ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK      (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)
+#endif
 /*
  * Subtle: this is an int (not an unsigned long) and so it
  * gets extended to 64 bits the way want (i.e. with 1s).  -- paulus
include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 renamed from include/asm-ppc/pgtable.h 2006-11-14 11:18:00.000000000 -0500 +43 -1

68 lines not on this page · raw message

include/linux/hugetlb.h 2006-11-14 17:26:18.000000000 -0500 renamed from include/linux/hugetlb.h 2006-11-14 11:18:05.000000000 -0500 +1 -0
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/linux/hugetlb.h my_linux/include/linux/hugetlb.h
@@ -2,6 +2,7 @@
 #define _LINUX_HUGETLB_H
 
 #ifdef CONFIG_HUGETLB_PAGE
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 
 #include <linux/mempolicy.h>
 #include <asm/tlbflush.h>
include/linux/mmzone.h 2006-11-14 17:26:17.000000000 -0500 renamed from include/linux/mmzone.h 2006-11-14 11:18:06.000000000 -0500 +1 -1
diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/linux/mmzone.h my_linux/include/linux/mmzone.h
@@ -18,7 +18,7 @@
 
 /* Free memory management - zoned buddy allocator.  */
 #ifndef CONFIG_FORCE_MAX_ZONEORDER
-#define MAX_ORDER 11
+#define MAX_ORDER 13
 #else
 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
 #endif
#1 lore raw
Quoted 9 lines · Edi Shmueli

From: Edi Shmueli <[email protected]>

Following requests to test the patch under the latest kernel, here it is again, tested for 2.6.19-rc4. This patch enables applications to exploit the PPC440 TLB support for huge-page mapping, to minimize TLB thrashing. Applications with large memory footprint that exploit this support, experience minimal TLB misses, and boost in performance. NAS benchmarks tested with this patch indicate hundreds of percent of improvement in performance.

Ok, I'm still in the process of getting our Ebony set up again so I can test this. In the meantime some observations..

First things first: your patch has been hopelessly whitespace mangled, probably by Notes. You'll need to resend with a patch-safe mailer.

Have you attempted to run the testsuite from libhugetlbfs with this? It will require some tweaking, since it's not previously been needed on ppc32, but it has testcases for a whole pile of potential kernel hugepage bugs.

Also have you looked at how this code compares to the large page support on PPC 40x. 40x doesn't support hugetlbfs, but it does have about half the necessary bits, since it stores a page size in the PTE for implementing large page mapping of the linear mapping. I'm not sure how applicable any of that stuff is to 440.

Quoted 48 lines

-----

Benchmarks and Implementation comments
======================================
Below is the NAS IS benchmark results, executing under Linux, with and without this huge-page mapping support.
IS Benchmark 4KB pages 16MB pages
=======================================================

  Class             =   A                     A
  Size              =   8388608               8388608
  Iterations        =   10                    10
  Time in seconds   =   24.44                 6.38
  Mop/s total       =   3.43                  13.15
  Operation type    =   keys ranked           keys ranked
  Verification      =   SUCCESSFUL            SUCCESSFUL

Implementation details:
=======================

This patch is ppc440 architecture-specific. It enables the use of huge-pages by processes executing under the 2.6.16 kernel on the ppc440 processors. Huge-pages are accessible to user processes using either the hugetlbfs or using shared memory. See Documentation/vs/hugetlbpage.txt.

The ppc 32bit kernel uses 64bit PTEs (set by CONFIG_PTE_64BIT). I exploit a "hole" of 4 unused bits in the PTE MS word (bits 24-27) and code the page size information in those bits. I then modified the TLB miss handler (head_44x.S) to stop using the constant PPC44x_TLB_4K to set the page size in the TLB. Instead, when a TLB miss happens, the miss handler reads the size information from the PTE and sets that size in the TLB entry. This way, different TLB entries get to map different page sizes (e.g., 4KB or 16MB). The TLB replacement policy remains RR. This means that a huge-page entry in the TLB may be overwritten if not used for a long time, but when accessed it will be set again by the TLB miss handler, with the correct size, as set in the PTE.

In arch/ppc/mm/hugetlbpage.c is where page table entries are set to map huge pages:
By default , each process has two-level page-tables. It has 2048, 32bit PMD (or PGD) entries at the higher-level, each maps 2MB of the process address spase, and 512, 64bit PTE entries in each lower-level page table. When a TLB miss happens and no PTE is found by the miss handler to offer the translation, a check is made (memory.c) on whether the faulting address belongs to a huge-page VM region. If so, the code in set_huge_pte_at() will set the required

Quoted 8 lines

number of PMDs (e.g.,8 PMDs for huge-pages of size 16MB, or 1 PMD for huge-pages of size 2MB or less) to point to the *same* lower-level PTE page table. Within the lower-level page table, it will set the required number PTEs (e.g., all 512 PTEs for huge-pages larger than 2MB, or 256 PTEs for huge-pages of size 1MB etc.) to point to the *same* physical huge-page frame. All these PTEs will be *identical* and have the page-size coded in their MS word as described above.

Creating an all-equal PTE page even when using pages of a size greater than or equal to that mapped by a single PMD seems very wasteful.

Quoted 12 lines

Once the TLB miss handler copies the mapping (and the size) from the PTE into on of a TLB entry, the process will not suffer any TLB misses for that huge-page. If the mapping was overwritten by the TLB RR replacement policy, it will be re-loaded again (probably in a different TLB entry) when the process re-access that huge-page.

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/kernel/head_44x.S my_linux/arch/ppc/kernel/head_44x.S

arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 renamed from arch/ppc/kernel/head_44x.S 2006-11-14 11:16:29.000000000 -0500 +0 -0
@@ -21,12 +21,14 @@
   *            [email protected]
   *    Copyright 2002-2005 MontaVista Software, Inc.

arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 line 31

Quoted 10 lines
arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 renamed from arch/ppc/kernel/head_44x.S 2006-11-14 11:16:29.000000000 -0500 +3 -1
   *      PowerPC 44x support, Matt Porter <[email protected]>
+ *    Copyright (C) 2006 Edi Shmueli, IBM Corporation.
+ *    PowerPC 44x handling of huge-page misses.
   *
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
- */
+*/

Please try to avoid extraneous changes in your patch.

[snip]

Quoted 4 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/mm/hugetlbpage.c my_linux/arch/ppc/mm/hugetlbpage.c

arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +0 -0

11:44:43.297682864 -0500

Since this patch is 440 specific, and 40x at least could also support hugepages, this should probably go in hugetlbpage_44x.c

Quoted 17 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +16 -0
@@ -0,0 +1,185 @@
+/*
+ * PPC32 (440) Huge TLB Page Support for Kernel.
+ *
+ * Copyright (C) 2006 Edi Shmueli, IBM Corporation.
+ *
+ * Based on the IA-32 version:
+ * Copyright (C) 2002, Rohit Seth <[email protected]>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>

arch/ppc/mm/hugetlbpage.c 2006-11-15 line 26

Quoted 10 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +10 -0
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+  pgd_t *pgd;

I'm not sure if the bogus indentation here is yours, or the result of Notes whitespace mangling. If the former, please make sure your code is formatted as per CodingStyle.

[snip]

arch/ppc/mm/hugetlbpage.c 2006-11-15 line 30

Quoted 4 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +4 -0
+    return pte;
+}
+
+#ifdef ARCH_HAS_SETCLEAR_HUGE_PTE

This #ifdef makes no sense here. You already know that this arch will need this code.

Quoted 2 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +1 -0
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,

pte_t *ptep, pte_t pte){

Open brace on the next line, as per CodingStyle, please.

[snip]

arch/ppc/mm/hugetlbpage.c 2006-11-15

Quoted 8 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +8 -0
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+{
+  if (len & ~HPAGE_MASK)
+    return -EINVAL;
+  if (addr & ~HPAGE_MASK)
+    return -EINVAL;
+  return 0;
+}

The is_aligned_hugepage_range() callback was removed quite some time ago, please remove.

[snip]

Quoted 12 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/fs/Kconfig my_linux/fs/Kconfig

fs/Kconfig 2006-11-14 17:26:13.000000000 -0500 renamed from fs/Kconfig 2006-11-14 11:17:37.000000000 -0500 +1 -1
@@ -1008,7 +1008,7 @@ config TMPFS_POSIX_ACL
 
  config HUGETLBFS
      bool "HugeTLB file system support"
-    depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+    depends X86 || IA64 || PPC || PPC64 || SPARC64 || SUPERH || BROKEN
      help
        hugetlbfs is a filesystem backing for HugeTLB pages, based on
        ramfs. For architectures that support it, say Y here and
Quoted 1 line

read

This needs a test for 44x as well, or this option will be available and horribly broken for other ppc32 machines.

Quoted 21 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/asm-ppc/page.h my_linux/include/asm-ppc/page.h

include/asm-ppc/page.h 2006-11-14 17:26:14.000000000 -0500 renamed from include/asm-ppc/page.h 2006-11-14 11:18:00.000000000 -0500 +6 -0
@@ -7,6 +7,12 @@
  #define PAGE_SHIFT    12
  #define PAGE_SIZE    (ASM_CONST(1) << PAGE_SHIFT)
 
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT     24
+#define HPAGE_SIZE      ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK      (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)
+#endif
  /*
   * Subtle: this is an int (not an unsigned long) and so it
   * gets extended to 64 bits the way want (i.e. with 1s).  -- paulus

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/asm-ppc/pgtable.h my_linux/include/asm-ppc/pgtable.h

include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 renamed from include/asm-ppc/pgtable.h 2006-11-14 11:18:00.000000000 -0500 +0 -0
@@ -263,6 +263,40 @@ extern unsigned long ioremap_bot, iorema
  #define    _PAGE_NO_CACHE    0x00000400        /* H: I bit */

include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 extern unsigned long ioremap_bot, iorema · line 273

Quoted 10 lines
include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 renamed from include/asm-ppc/pgtable.h 2006-11-14 11:18:00.000000000 -0500 +8 -0
  #define    _PAGE_WRITETHRU    0x00000800        /* H: W bit */
 
+#if   HPAGE_SHIFT == 10 /*Unsupported*/
+#define _PAGE_HUGE      0x0000000000000000ULL   /* H: SIZE=1K bytes */
+#define _PTE_MASK       0xfffffff8UL
+#define _PTE_CNT        ((1UL) << (PTE_SHIFT - 9))
+#elif HPAGE_SHIFT == 12
+#define _PAGE_HUGE      0x0000001000000000ULL   /* H: SIZE=4K bytes */
+#define _PTE_MASK       0xfffffff8UL
+#define _PTE_CNT        ((1UL) << (PTE_SHIFT - 9))

Yikes! Please use computed values here, not this ghastly string of #ifdefs.

Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#2 lore raw
Quoted 236 lines · David Gibson
Quoted 9 lines · Edi Shmueli

From: Edi Shmueli <[email protected]>

Following requests to test the patch under the latest kernel, here it is again, tested for 2.6.19-rc4. This patch enables applications to exploit the PPC440 TLB support for huge-page mapping, to minimize TLB thrashing. Applications with large memory footprint that exploit this support, experience minimal TLB misses, and boost in performance. NAS benchmarks tested with this patch indicate hundreds of percent of improvement in performance.

Ok, I'm still in the process of getting our Ebony set up again so I can test this. In the meantime some observations..

First things first: your patch has been hopelessly whitespace mangled, probably by Notes. You'll need to resend with a patch-safe mailer.

Have you attempted to run the testsuite from libhugetlbfs with this? It will require some tweaking, since it's not previously been needed on ppc32, but it has testcases for a whole pile of potential kernel hugepage bugs.

Also have you looked at how this code compares to the large page support on PPC 40x. 40x doesn't support hugetlbfs, but it does have about half the necessary bits, since it stores a page size in the PTE for implementing large page mapping of the linear mapping. I'm not sure how applicable any of that stuff is to 440.

Quoted 48 lines

-----

Benchmarks and Implementation comments
======================================
Below is the NAS IS benchmark results, executing under Linux, with and without this huge-page mapping support.
IS Benchmark 4KB pages 16MB pages
=======================================================

  Class             =   A                     A
  Size              =   8388608               8388608
  Iterations        =   10                    10
  Time in seconds   =   24.44                 6.38
  Mop/s total       =   3.43                  13.15
  Operation type    =   keys ranked           keys ranked
  Verification      =   SUCCESSFUL            SUCCESSFUL

Implementation details:
=======================

This patch is ppc440 architecture-specific. It enables the use of huge-pages by processes executing under the 2.6.16 kernel on the ppc440 processors. Huge-pages are accessible to user processes using either the hugetlbfs or using shared memory. See Documentation/vs/hugetlbpage.txt.

The ppc 32bit kernel uses 64bit PTEs (set by CONFIG_PTE_64BIT). I exploit a "hole" of 4 unused bits in the PTE MS word (bits 24-27) and code the page size information in those bits. I then modified the TLB miss handler (head_44x.S) to stop using the constant PPC44x_TLB_4K to set the page size in the TLB. Instead, when a TLB miss happens, the miss handler reads the size information from the PTE and sets that size in the TLB entry. This way, different TLB entries get to map different page sizes (e.g., 4KB or 16MB). The TLB replacement policy remains RR. This means that a huge-page entry in the TLB may be overwritten if not used for a long time, but when accessed it will be set again by the TLB miss handler, with the correct size, as set in the PTE.

In arch/ppc/mm/hugetlbpage.c is where page table entries are set to map huge pages:
By default , each process has two-level page-tables. It has 2048, 32bit PMD (or PGD) entries at the higher-level, each maps 2MB of the process address spase, and 512, 64bit PTE entries in each lower-level page table. When a TLB miss happens and no PTE is found by the miss handler to offer the translation, a check is made (memory.c) on whether the faulting address belongs to a huge-page VM region. If so, the code in set_huge_pte_at() will set the required

Quoted 8 lines

number of PMDs (e.g.,8 PMDs for huge-pages of size 16MB, or 1 PMD for huge-pages of size 2MB or less) to point to the *same* lower-level PTE page table. Within the lower-level page table, it will set the required number PTEs (e.g., all 512 PTEs for huge-pages larger than 2MB, or 256 PTEs for huge-pages of size 1MB etc.) to point to the *same* physical huge-page frame. All these PTEs will be *identical* and have the page-size coded in their MS word as described above.

Creating an all-equal PTE page even when using pages of a size greater than or equal to that mapped by a single PMD seems very wasteful.

Quoted 12 lines

Once the TLB miss handler copies the mapping (and the size) from the PTE into on of a TLB entry, the process will not suffer any TLB misses for that huge-page. If the mapping was overwritten by the TLB RR replacement policy, it will be re-loaded again (probably in a different TLB entry) when the process re-access that huge-page.

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/kernel/head_44x.S my_linux/arch/ppc/kernel/head_44x.S

arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 renamed from arch/ppc/kernel/head_44x.S 2006-11-14 11:16:29.000000000 -0500 +0 -0
@@ -21,12 +21,14 @@
   *            [email protected]
   *    Copyright 2002-2005 MontaVista Software, Inc.

arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 line 31

Quoted 10 lines
arch/ppc/kernel/head_44x.S 2006-11-14 17:26:13.000000000 -0500 renamed from arch/ppc/kernel/head_44x.S 2006-11-14 11:16:29.000000000 -0500 +3 -1
   *      PowerPC 44x support, Matt Porter <[email protected]>
+ *    Copyright (C) 2006 Edi Shmueli, IBM Corporation.
+ *    PowerPC 44x handling of huge-page misses.
   *
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
- */
+*/

Please try to avoid extraneous changes in your patch.

[snip]

Quoted 4 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/arch/ppc/mm/hugetlbpage.c my_linux/arch/ppc/mm/hugetlbpage.c

arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +0 -0

11:44:43.297682864 -0500

Since this patch is 440 specific, and 40x at least could also support hugepages, this should probably go in hugetlbpage_44x.c

Quoted 17 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +16 -0
@@ -0,0 +1,185 @@
+/*
+ * PPC32 (440) Huge TLB Page Support for Kernel.
+ *
+ * Copyright (C) 2006 Edi Shmueli, IBM Corporation.
+ *
+ * Based on the IA-32 version:
+ * Copyright (C) 2002, Rohit Seth <[email protected]>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>

arch/ppc/mm/hugetlbpage.c 2006-11-15 line 26

Quoted 10 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +10 -0
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+  pgd_t *pgd;

I'm not sure if the bogus indentation here is yours, or the result of Notes whitespace mangling. If the former, please make sure your code is formatted as per CodingStyle.

[snip]

arch/ppc/mm/hugetlbpage.c 2006-11-15 line 30

Quoted 4 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +4 -0
+    return pte;
+}
+
+#ifdef ARCH_HAS_SETCLEAR_HUGE_PTE

This #ifdef makes no sense here. You already know that this arch will need this code.

Quoted 2 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +1 -0
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,

pte_t *ptep, pte_t pte){

Open brace on the next line, as per CodingStyle, please.

[snip]

arch/ppc/mm/hugetlbpage.c 2006-11-15

Quoted 8 lines
arch/ppc/mm/hugetlbpage.c 2006-11-15 renamed from arch/ppc/mm/hugetlbpage.c 1969-12-31 19:00:00.000000000 -0500 +8 -0
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+{
+  if (len & ~HPAGE_MASK)
+    return -EINVAL;
+  if (addr & ~HPAGE_MASK)
+    return -EINVAL;
+  return 0;
+}

The is_aligned_hugepage_range() callback was removed quite some time ago, please remove.

[snip]

Quoted 12 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/fs/Kconfig my_linux/fs/Kconfig

fs/Kconfig 2006-11-14 17:26:13.000000000 -0500 renamed from fs/Kconfig 2006-11-14 11:17:37.000000000 -0500 +1 -1
@@ -1008,7 +1008,7 @@ config TMPFS_POSIX_ACL
 
  config HUGETLBFS
      bool "HugeTLB file system support"
-    depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+    depends X86 || IA64 || PPC || PPC64 || SPARC64 || SUPERH || BROKEN
      help
        hugetlbfs is a filesystem backing for HugeTLB pages, based on
        ramfs. For architectures that support it, say Y here and
Quoted 1 line

read

This needs a test for 44x as well, or this option will be available and horribly broken for other ppc32 machines.

Quoted 21 lines

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/asm-ppc/page.h my_linux/include/asm-ppc/page.h

include/asm-ppc/page.h 2006-11-14 17:26:14.000000000 -0500 renamed from include/asm-ppc/page.h 2006-11-14 11:18:00.000000000 -0500 +6 -0
@@ -7,6 +7,12 @@
  #define PAGE_SHIFT    12
  #define PAGE_SIZE    (ASM_CONST(1) << PAGE_SHIFT)
 
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT     24
+#define HPAGE_SIZE      ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK      (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)
+#endif
  /*
   * Subtle: this is an int (not an unsigned long) and so it
   * gets extended to 64 bits the way want (i.e. with 1s).  -- paulus

diff -uprP -X linux-2.6.19-rc4-vanilla/Documentation/dontdiff linux-2.6.19-rc4-vanilla/include/asm-ppc/pgtable.h my_linux/include/asm-ppc/pgtable.h

include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 renamed from include/asm-ppc/pgtable.h 2006-11-14 11:18:00.000000000 -0500 +0 -0
@@ -263,6 +263,40 @@ extern unsigned long ioremap_bot, iorema
  #define    _PAGE_NO_CACHE    0x00000400        /* H: I bit */

include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 extern unsigned long ioremap_bot, iorema · line 273

Quoted 10 lines
include/asm-ppc/pgtable.h 2006-11-15 11:40:45.332514013 -0500 renamed from include/asm-ppc/pgtable.h 2006-11-14 11:18:00.000000000 -0500 +8 -0
  #define    _PAGE_WRITETHRU    0x00000800        /* H: W bit */
 
+#if   HPAGE_SHIFT == 10 /*Unsupported*/
+#define _PAGE_HUGE      0x0000000000000000ULL   /* H: SIZE=1K bytes */
+#define _PTE_MASK       0xfffffff8UL
+#define _PTE_CNT        ((1UL) << (PTE_SHIFT - 9))
+#elif HPAGE_SHIFT == 12
+#define _PAGE_HUGE      0x0000001000000000ULL   /* H: SIZE=4K bytes */
+#define _PTE_MASK       0xfffffff8UL
+#define _PTE_CNT        ((1UL) << (PTE_SHIFT - 9))

Yikes! Please use computed values here, not this ghastly string of #ifdefs.

Quoted 5 lines

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_

				| _way_ _around_!

http://www.ozlabs.org/~dgibson

Thanks David,
One step at a time, lets start with libhugetlbfs :-)
I'm successfully able to run most of my tests using the library, backing my data,text and BSS with huge-pages. There is a major improvement in performance, similar to what I reported above.
Good job with the library !!!

There is a problem though when a program calls "fopen".
I see hugetlbfs does the unmapping/mapping , moves control to main(), and then a crash with the following error:
"*** glibc detected *** free(): invalid pointer: 0x3002a008 ***" This happens inside fopen() (....which never returns).

Here is the detailed output.

/bgd-public/edi/IS # ./is.A.linux_ser_hugetlbfs
libhugetlbfs: Hugepage segment 0 (phdr 2): 0x10000000-0x10001b70 (filesz=0x1b70) (prot = 0x5)
libhugetlbfs: Hugepage segment 1 (phdr 3): 0x11000000-0x170006e8 (filesz=0x274) (prot = 0x7)
libhugetlbfs: HUGETLB_SHARE=0, sharing disabled
libhugetlbfs: Got unshared fd as expected -- Preparing
libhugetlbfs: Mapped hugeseg at 0x31000000. Copying 0x1b70 bytes from 0x10000000... done
libhugetlbfs: Minimal copy was not performed
libhugetlbfs: Prepare succeeded
libhugetlbfs: HUGETLB_SHARE=0, sharing disabled
libhugetlbfs: Got unshared fd as expected -- Preparing
libhugetlbfs: Mapped hugeseg at 0x31000000. Copying 0x274 bytes from 0x11000000... done
libhugetlbfs: Minimal copy was not performed
libhugetlbfs: Prepare succeeded
*** glibc detected *** free(): invalid pointer: 0x3002a008 ***
Aborted

#3 lore raw

On Tue, Dec 12, 2006 at 11:04:07AM -0500, Edi Shmueli wrote:
[snip]

Quoted 5 lines

Thanks David,
One step at a time, lets start with libhugetlbfs :-)
I'm successfully able to run most of my tests using the library, backing my data,text and BSS with huge-pages. There is a major improvement in performance, similar to what I reported above.
Good job with the library !!!

Ok.. how does the library's own testsuite go ("make check"). That testsuite has tests for kernel bugs as well as library bugs.

Quoted 5 lines

There is a problem though when a program calls "fopen".
I see hugetlbfs does the unmapping/mapping , moves control to main(), and then a crash with the following error:
"*** glibc detected *** free(): invalid pointer: 0x3002a008 ***" This happens inside fopen() (....which never returns).

Ok, do you get any similar problems with the minimal tests in the testsuite?

`> Here is the detailed output.

Quoted 10 lines

/bgd-public/edi/IS # ./is.A.linux_ser_hugetlbfs
libhugetlbfs: Hugepage segment 0 (phdr 2): 0x10000000-0x10001b70 (filesz=0x1b70) (prot = 0x5)
libhugetlbfs: Hugepage segment 1 (phdr 3): 0x11000000-0x170006e8 (filesz=0x274) (prot = 0x7)
libhugetlbfs: HUGETLB_SHARE=0, sharing disabled
libhugetlbfs: Got unshared fd as expected -- Preparing
libhugetlbfs: Mapped hugeseg at 0x31000000. Copying 0x1b70 bytes from 0x10000000... done
libhugetlbfs: Minimal copy was not performed
libhugetlbfs: Prepare succeeded

Quoted 8 lines

libhugetlbfs: HUGETLB_SHARE=0, sharing disabled
libhugetlbfs: Got unshared fd as expected -- Preparing
libhugetlbfs: Mapped hugeseg at 0x31000000. Copying 0x274 bytes from 0x11000000... done
libhugetlbfs: Minimal copy was not performed
libhugetlbfs: Prepare succeeded
*** glibc detected *** free(): invalid pointer: 0x3002a008 *** Aborted

If you can send me a non-whitespace-mangled version of your patch, I can try to replicate this here. If you made any hacks to libhugetlbfs to get it working on ppc32, a patch for those would be handy too.

Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson