[PATCH] powerpc: add support for PAGE_SIZEs greater than 4KB for

David Gibson david at gibson.dropbear.id.au
Fri Sep 12 13:48:14 EST 2008


On Thu, Sep 11, 2008 at 01:53:06AM +0400, Ilya Yanok wrote:
> This patch adds support for page sizes bigger than 4KB (16KB/64KB/256KB) on
> PPC 44x.

[snip]
> 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"
> +

I don't see any reason to have a separate set of config options for 32
and 64-bit.  Just make the once choice, but only have the individual
pagesize options enabled on machines that support them.

[snip]
> 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;

I don't think you should need a real_pte_t type for the 32-bit
implementation.  It's just there because of how we implement
64k granularity page allocation on hardware that only does 4k
translations.

[snip]
> 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)

This doesn't look right.  You should be eliding one of the levels of
page table if you don't need it, rather than leaving the bottom level
PTE page largely empty.

[snip]
> +#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*/

Uh.. you have the formulae for these things right there in the
comments, so why aren't you using those and avoiding this nasty
multiway ifdef...

[snip]
> 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

Hrm.. more peculiar special cases for 256K pages.  I think it might be
clearer if you split the patch into one which supports page sizes up
to 64k, then another that does the extra hacks for 256k pages.

[snip]
> @@ -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

I agree with others that these constants need better names.  Or even
derive the values from PMD_SHIFT or whatnot right here inline, rather
than defining special constants.

[snip]
> 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,THREAD_SIZE at h;					     \
> +	ori	r11,r11,THREAD_SIZE at l;					     \
> +	add	r1,r1,r11;
> \

It would be nice if we could avoid the extra instruction here when the
page sizes isn't big enough to require it.

>  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,EXC_LVL_FRAME_OVERHEAD at ha; /* allocate stack frame */\
> +	addi	r11,r11,EXC_LVL_FRAME_OVERHEAD at l;  /* allocate stack frame */\

And here.

-- 
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



More information about the Linuxppc-dev mailing list