This patch adds support for page sizes bigger than 4KB (16KB/64KB/256KB) on
PPC 44x.

Signed-off-by: Yuri Tikhonov <[EMAIL PROTECTED]>
Signed-off-by: Ilya Yanok <[EMAIL PROTECTED]>
---
 arch/powerpc/Kconfig                    |   23 +++++++++
 arch/powerpc/include/asm/highmem.h      |    8 +++-
 arch/powerpc/include/asm/page.h         |   26 +++++++++-
 arch/powerpc/include/asm/page_32.h      |    4 ++
 arch/powerpc/include/asm/ppc_page_asm.h |   75 +++++++++++++++++++++++++++++++
 arch/powerpc/include/asm/thread_info.h  |    4 ++
 arch/powerpc/kernel/head_44x.S          |   21 +++++---
 arch/powerpc/kernel/head_booke.h        |    7 ++-
 arch/powerpc/kernel/misc_32.S           |   13 +++---
 arch/powerpc/mm/pgtable_32.c            |    2 +-
 10 files changed, 162 insertions(+), 21 deletions(-)
 create mode 100644 arch/powerpc/include/asm/ppc_page_asm.h

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 587da5e..ca93157 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -413,6 +413,29 @@ config PPC_64K_PAGES
          while on hardware with such support, it will be used to map
          normal application pages.
 
+choice
+       prompt "Page size"
+       depends on 44x && PPC32
+       default PPC32_4K_PAGES
+       help
+         The PAGE_SIZE definition. Increasing the page size may
+         improve the system performance in some dedicated cases.
+         If unsure, set it to 4 KB.
+
+config PPC32_4K_PAGES
+       bool "4k page size"
+
+config PPC32_16K_PAGES
+       bool "16k page size"
+
+config PPC32_64K_PAGES
+       bool "64k page size"
+
+config PPC32_256K_PAGES
+       bool "256k page size"
+
+endchoice
+
 config FORCE_MAX_ZONEORDER
        int "Maximum zone order"
        default "9" if PPC_64K_PAGES
diff --git a/arch/powerpc/include/asm/highmem.h 
b/arch/powerpc/include/asm/highmem.h
index 5d99b64..1aec96d 100644
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -38,9 +38,15 @@ extern pte_t *pkmap_page_table;
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
+#if defined(CONFIG_PPC32_64K_PAGES) || defined(CONFIG_PPC32_256K_PAGES)
+#define PKMAP_ORDER    (27 - PAGE_SHIFT)
+#define LAST_PKMAP     (1 << PKMAP_ORDER)
+#define PKMAP_BASE     (FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1))
+#else
 #define LAST_PKMAP     (1 << PTE_SHIFT)
-#define LAST_PKMAP_MASK (LAST_PKMAP-1)
 #define PKMAP_BASE     ((FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1)) & 
PMD_MASK)
+#endif
+#define LAST_PKMAP_MASK        (LAST_PKMAP-1)
 #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index e088545..1de90b4 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -15,12 +15,17 @@
 #include <asm/types.h>
 
 /*
- * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
+ * On regular PPC32 page size is 4K (but we support 4K/16K/64K/256K pages
+ * on PPC44x). For PPC64 we support either 4K or 64K software
  * page size. When using 64K pages however, whether we are really supporting
  * 64K pages in HW or not is irrelevant to those definitions.
  */
-#ifdef CONFIG_PPC_64K_PAGES
+#if defined(CONFIG_PPC32_256K_PAGES)
+#define PAGE_SHIFT             18
+#elif defined(CONFIG_PPC32_64K_PAGES) || defined(CONFIG_PPC_64K_PAGES)
 #define PAGE_SHIFT             16
+#elif defined(CONFIG_PPC32_16K_PAGES)
+#define PAGE_SHIFT             14
 #else
 #define PAGE_SHIFT             12
 #endif
@@ -140,11 +145,19 @@ typedef struct { pte_basic_t pte; } pte_t;
 /* 64k pages additionally define a bigger "real PTE" type that gathers
  * the "second half" part of the PTE for pseudo 64k pages
  */
+#ifdef CONFIG_PPC64
 #ifdef CONFIG_PPC_64K_PAGES
 typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
 #else
 typedef struct { pte_t pte; } real_pte_t;
 #endif
+#else
+#ifdef CONFIG_PPC32_4K_PAGES
+typedef struct { pte_t pte; } real_pte_t;
+#else
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#endif
+#endif /* !CONFIG_PPC64 */
 
 /* PMD level */
 #ifdef CONFIG_PPC64
@@ -180,12 +193,19 @@ typedef pte_basic_t pte_t;
 #define pte_val(x)     (x)
 #define __pte(x)       (x)
 
+#ifdef CONFIG_PPC64
 #ifdef CONFIG_PPC_64K_PAGES
 typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
 #else
 typedef unsigned long real_pte_t;
 #endif
-
+#else
+#ifdef CONFIG_PPC32_4K_PAGES
+typedef unsigned long real_pte_t;
+#else
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#endif
+#endif /* !PPC64 */
 
 #ifdef CONFIG_PPC64
 typedef unsigned long pmd_t;
diff --git a/arch/powerpc/include/asm/page_32.h 
b/arch/powerpc/include/asm/page_32.h
index ebfae53..d176270 100644
--- a/arch/powerpc/include/asm/page_32.h
+++ b/arch/powerpc/include/asm/page_32.h
@@ -20,7 +20,11 @@
  */
 #ifdef CONFIG_PTE_64BIT
 typedef unsigned long long pte_basic_t;
+#ifdef CONFIG_PPC32_256K_PAGES
+#define PTE_SHIFT      (PAGE_SHIFT - 7)
+#else
 #define PTE_SHIFT      (PAGE_SHIFT - 3)        /* 512 ptes per page */
+#endif
 #else
 typedef unsigned long pte_basic_t;
 #define PTE_SHIFT      (PAGE_SHIFT - 2)        /* 1024 ptes per page */
diff --git a/arch/powerpc/include/asm/ppc_page_asm.h 
b/arch/powerpc/include/asm/ppc_page_asm.h
new file mode 100644
index 0000000..e1250fa
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc_page_asm.h
@@ -0,0 +1,75 @@
+/*
+ * arch/powerpc/include/asm/ppc_page_asm.h
+ *
+ * 2007 (C) DENX Software Engineering.
+ *
+ *  This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ *
+ *  The page definitions used in the asm files ppc_44x.S and misc.S.
+ * PAGE_SIZE = 4K and 64K are only supported on the PPC44x.
+ *
+ */
+#ifndef PPC_PAGE_ASM_H
+#define PPC_PAGE_ASM_H
+
+#include <asm/page.h>
+
+#if (PAGE_SHIFT == 12)
+/*
+ * PAGE_SIZE  4K
+ * PAGE_SHIFT 12
+ * PTE_SHIFT   9
+ * PMD_SHIFT  21
+ */
+#define PPC44x_TLBE_SIZE       PPC44x_TLB_4K
+#define PPC44x_PGD_OFF_SH      13 /*(32 - PMD_SHIFT + 2)*/
+#define PPC44x_PGD_OFF_M1      19 /*(PMD_SHIFT - 2)*/
+#define PPC44x_PTE_ADD_SH      23 /*32 - PMD_SHIFT + PTE_SHIFT + 3*/
+#define PPC44x_PTE_ADD_M1      20 /*32 - 3 - PTE_SHIFT*/
+#define PPC44x_RPN_M2          19 /*31 - PAGE_SHIFT*/
+#elif (PAGE_SHIFT == 14)
+/*
+ * PAGE_SIZE  16K
+ * PAGE_SHIFT 14
+ * PTE_SHIFT  11
+ * PMD_SHIFT  25
+ */
+#define PPC44x_TLBE_SIZE       PPC44x_TLB_16K
+#define PPC44x_PGD_OFF_SH      9  /*(32 - PMD_SHIFT + 2)*/
+#define PPC44x_PGD_OFF_M1      23 /*(PMD_SHIFT - 2)*/
+#define PPC44x_PTE_ADD_SH      21 /*32 - PMD_SHIFT + PTE_SHIFT + 3*/
+#define PPC44x_PTE_ADD_M1      18 /*32 - 3 - PTE_SHIFT*/
+#define PPC44x_RPN_M2          17 /*31 - PAGE_SHIFT*/
+#elif (PAGE_SHIFT == 16)
+/*
+ * PAGE_SIZE  64K
+ * PAGE_SHIFT 16
+ * PTE_SHIFT  13
+ * PMD_SHIFT  29
+ */
+#define PPC44x_TLBE_SIZE       PPC44x_TLB_64K
+#define PPC44x_PGD_OFF_SH      5  /*(32 - PMD_SHIFT + 2)*/
+#define PPC44x_PGD_OFF_M1      27 /*(PMD_SHIFT - 2)*/
+#define PPC44x_PTE_ADD_SH      19 /*32 - PMD_SHIFT + PTE_SHIFT + 3*/
+#define PPC44x_PTE_ADD_M1      16 /*32 - 3 - PTE_SHIFT*/
+#define PPC44x_RPN_M2          15 /*31 - PAGE_SHIFT*/
+#elif (PAGE_SHIFT == 18)
+/*
+ * PAGE_SIZE  256K
+ * PAGE_SHIFT 18
+ * PTE_SHIFT  11
+ * PMD_SHIFT  29
+ */
+#define PPC44x_TLBE_SIZE       PPC44x_TLB_256K
+#define PPC44x_PGD_OFF_SH      5  /*(32 - PMD_SHIFT + 2)*/
+#define PPC44x_PGD_OFF_M1      27 /*(PMD_SHIFT - 2)*/
+#define PPC44x_PTE_ADD_SH      17 /*32 - PMD_SHIFT + PTE_SHIFT + 3*/
+#define PPC44x_PTE_ADD_M1      18 /*32 - 3 - PTE_SHIFT*/
+#define PPC44x_RPN_M2          13 /*31 - PAGE_SHIFT*/
+#else
+#error "Unsupported PAGE_SIZE"
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/thread_info.h 
b/arch/powerpc/include/asm/thread_info.h
index 9665a26..4e7cd1f 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -15,8 +15,12 @@
 #ifdef CONFIG_PPC64
 #define THREAD_SHIFT           14
 #else
+#if defined(CONFIG_PPC32_256K_PAGES)
+#define THREAD_SHIFT           15
+#else
 #define THREAD_SHIFT           13
 #endif
+#endif
 
 #define THREAD_SIZE            (1 << THREAD_SHIFT)
 
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index f3a1ea9..c0a99a4 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -36,6 +36,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ppc_page_asm.h>
 #include "head_booke.h"
 
 
@@ -391,12 +392,14 @@ interrupt_base:
        rlwimi  r13,r12,10,30,30
 
        /* Load the PTE */
-       rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
+       /* Compute pgdir/pmd offset */
+       rlwinm  r12, r10, PPC44x_PGD_OFF_SH, PPC44x_PGD_OFF_M1, 29
        lwzx    r11, r12, r11           /* Get pgd/pmd entry */
        rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
        beq     2f                      /* Bail if no table */
 
-       rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
+       /* Compute pte address */
+       rlwimi  r12, r10, PPC44x_PTE_ADD_SH, PPC44x_PTE_ADD_M1, 28
        lwz     r11, 0(r12)             /* Get high word of pte entry */
        lwz     r12, 4(r12)             /* Get low word of pte entry */
 
@@ -485,12 +488,14 @@ tlb_44x_patch_hwater_D:
        /* Make up the required permissions */
        li      r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
 
-       rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
+       /* Compute pgdir/pmd offset */
+       rlwinm  r12, r10, PPC44x_PGD_OFF_SH, PPC44x_PGD_OFF_M1, 29
        lwzx    r11, r12, r11           /* Get pgd/pmd entry */
        rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
        beq     2f                      /* Bail if no table */
 
-       rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
+       /* Compute pte address */
+       rlwimi  r12, r10, PPC44x_PTE_ADD_SH, PPC44x_PTE_ADD_M1, 28
        lwz     r11, 0(r12)             /* Get high word of pte entry */
        lwz     r12, 4(r12)             /* Get low word of pte entry */
 
@@ -554,14 +559,14 @@ tlb_44x_patch_hwater_I:
  */
 finish_tlb_load:
        /* Combine RPN & ERPN an write WS 0 */
-       rlwimi  r11,r12,0,0,19
+       rlwimi  r11,r12,0,0,PPC44x_RPN_M2
        tlbwe   r11,r13,PPC44x_TLB_XLAT
 
        /*
         * Create WS1. This is the faulting address (EPN),
         * page size, and valid flag.
         */
-       li      r11,PPC44x_TLB_VALID | PPC44x_TLB_4K
+       li      r11,PPC44x_TLB_VALID | PPC44x_TLBE_SIZE
        rlwimi  r10,r11,0,20,31                 /* Insert valid and page size*/
        tlbwe   r10,r13,PPC44x_TLB_PAGEID       /* Write PAGEID */
 
@@ -634,12 +639,12 @@ _GLOBAL(set_context)
  * goes at the beginning of the data segment, which is page-aligned.
  */
        .data
-       .align  12
+       .align  PAGE_SHIFT
        .globl  sdata
 sdata:
        .globl  empty_zero_page
 empty_zero_page:
-       .space  4096
+       .space  PAGE_SIZE
 
 /*
  * To support >32-bit physical addresses, we use an 8KB pgdir.
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index fce2df9..4f802df 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -20,7 +20,9 @@
        beq     1f;                                                          \
        mfspr   r1,SPRN_SPRG3;          /* if from user, start at top of   */\
        lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-       addi    r1,r1,THREAD_SIZE;                                           \
+       lis     r11,[EMAIL PROTECTED];                                       \
+       ori     r11,r11,[EMAIL PROTECTED];                                      
     \
+       add     r1,r1,r11;                                                   \
 1:     subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
        mr      r11,r1;                                                      \
        stw     r10,_CCR(r11);          /* save various registers          */\
@@ -112,7 +114,8 @@
        andi.   r10,r10,MSR_PR;                                              \
        mfspr   r11,SPRN_SPRG3;         /* if from user, start at top of   */\
        lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame    */\
+       addis   r11,r11,[EMAIL PROTECTED]; /* allocate stack frame */\
+       addi    r11,r11,[EMAIL PROTECTED];  /* allocate stack frame */\
        beq     1f;                                                          \
        /* COMING FROM USER MODE */                                          \
        stw     r9,_CCR(r11);           /* save CR                         */\
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 7a6dfbc..97463ba 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -29,6 +29,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/processor.h>
 #include <asm/kexec.h>
+#include <asm/ppc_page_asm.h>
 
        .text
 
@@ -589,8 +590,8 @@ _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       rlwinm  r3,r3,0,0,19                    /* Get page base address */
-       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
+       rlwinm  r3,r3,0,0,PPC44x_RPN_M2         /* Get page base address */
+       li      r4,PAGE_SIZE/L1_CACHE_BYTES     /* Number of lines in a page */
        mtctr   r4
        mr      r6,r3
 0:     dcbst   0,r3                            /* Write line to ram */
@@ -630,8 +631,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r0,r10,0,28,26                  /* clear DR */
        mtmsr   r0
        isync
-       rlwinm  r3,r3,0,0,19                    /* Get page base address */
-       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
+       rlwinm  r3,r3,0,0,PPC44x_RPN_M2         /* Get page base address */
+       li      r4,PAGE_SIZE/L1_CACHE_BYTES     /* Number of lines in a page */
        mtctr   r4
        mr      r6,r3
 0:     dcbst   0,r3                            /* Write line to ram */
@@ -655,7 +656,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
  * void clear_pages(void *page, int order) ;
  */
 _GLOBAL(clear_pages)
-       li      r0,4096/L1_CACHE_BYTES
+       li      r0,PAGE_SIZE/L1_CACHE_BYTES
        slw     r0,r0,r4
        mtctr   r0
 #ifdef CONFIG_8xx
@@ -713,7 +714,7 @@ _GLOBAL(copy_page)
        dcbt    r5,r4
        li      r11,L1_CACHE_BYTES+4
 #endif /* MAX_COPY_PREFETCH */
-       li      r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
+       li      r0,PAGE_SIZE/L1_CACHE_BYTES - MAX_COPY_PREFETCH
        crclr   4*cr0+eq
 2:
        mtctr   r0
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 2001abd..efaf46a 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -400,7 +400,7 @@ void kernel_map_pages(struct page *page, int numpages, int 
enable)
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
 static int fixmaps;
-unsigned long FIXADDR_TOP = 0xfffff000;
+unsigned long FIXADDR_TOP = (-PAGE_SIZE);
 EXPORT_SYMBOL(FIXADDR_TOP);
 
 void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
-- 
1.5.6.1

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to