[7/7] ppc64/aarch64: Dynamically define PAGE_SIZE

Submitted by Dmitry Safonov on March 26, 2018, 1:07 p.m.

Details

Message ID 20180326130702.13295-8-dima@arista.com
State New
Series "Large pages support for aarch64/ppc64"
Headers show

Commit Message

Dmitry Safonov March 26, 2018, 1:07 p.m.
On ppc64/aarch64 Linux can be set to use Large pages, so the PAGE_SIZE
isn't build-time constant anymore. Define it through _SC_PAGESIZE.

There are different sizes for a page on ppc64:
: #if defined(CONFIG_PPC_256K_PAGES)
: #define PAGE_SHIFT              18
: #elif defined(CONFIG_PPC_64K_PAGES)
: #define PAGE_SHIFT              16
: #elif defined(CONFIG_PPC_16K_PAGES)
: #define PAGE_SHIFT              14
: #else
: #define PAGE_SHIFT              12
: #endif

And on aarch64 there are default sizes and possibly someone can set his
own PAGE_SHIFT:
: config ARM64_PAGE_SHIFT
:         int
:         default 16 if ARM64_64K_PAGES
:         default 14 if ARM64_16K_PAGES
:         default 12

On the downside - each time we need PAGE_SIZE, we're doing libc
function call on aarch64/ppc64.

Fixes: #415

Tested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
 include/common/arch/aarch64/asm/page.h | 23 +++++++++++------------
 include/common/arch/ppc64/asm/page.h   | 25 ++++++++++---------------
 2 files changed, 21 insertions(+), 27 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/common/arch/aarch64/asm/page.h b/include/common/arch/aarch64/asm/page.h
index 4126c8474a7d..a4d98aa21fb7 100644
--- a/include/common/arch/aarch64/asm/page.h
+++ b/include/common/arch/aarch64/asm/page.h
@@ -4,22 +4,21 @@ 
 #define ARCH_HAS_LONG_PAGES
 
 #ifndef CR_NOGLIBC
-#include <unistd.h>
+#include <string.h> /* ffsl() */
+#include <unistd.h> /* _SC_PAGESIZE */
 
-#ifndef PAGE_SHIFT
-# define PAGE_SHIFT	12
-#endif
-
-#ifndef PAGE_SIZE
-# define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#endif
+#define page_size()	sysconf(_SC_PAGESIZE)
 
-#ifndef PAGE_MASK
-# define PAGE_MASK	(~(PAGE_SIZE - 1))
-#endif
+/*
+ * Don't add ifdefs for PAGE_SIZE: if any header defines it as a constant
+ * on aarch64, then we need refrain using PAGE_SIZE in criu and use
+ * page_size() across sources (as it may differ on aarch64).
+ */
+#define PAGE_SIZE	page_size()
+#define PAGE_MASK	(~(PAGE_SIZE - 1))
+#define PAGE_SHIFT	(ffsl(page_size()) - 1)
 
 #define PAGE_PFN(addr)	((addr) / PAGE_SIZE)
-#define page_size()	sysconf(_SC_PAGESIZE)
 
 #else /* CR_NOGLIBC */
 
diff --git a/include/common/arch/ppc64/asm/page.h b/include/common/arch/ppc64/asm/page.h
index a95af55ef8a0..f2e1dcaeb616 100644
--- a/include/common/arch/ppc64/asm/page.h
+++ b/include/common/arch/ppc64/asm/page.h
@@ -4,26 +4,21 @@ 
 #define ARCH_HAS_LONG_PAGES
 
 #ifndef CR_NOGLIBC
-#include <unistd.h>
+#include <string.h> /* ffsl() */
+#include <unistd.h> /* _SC_PAGESIZE */
+
+#define page_size()	sysconf(_SC_PAGESIZE)
 
 /*
- * Default config for Pseries is to use 64K pages.
- * See kernel file arch/powerpc/configs/pseries_*defconfig
+ * Don't add ifdefs for PAGE_SIZE: if any header defines it as a constant
+ * on ppc64, then we need refrain using PAGE_SIZE in criu and use
+ * page_size() across sources (as it may differ on ppc64).
  */
-#ifndef PAGE_SHIFT
-# define PAGE_SHIFT	16
-#endif
-
-#ifndef PAGE_SIZE
-# define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#endif
-
-#ifndef PAGE_MASK
-# define PAGE_MASK	(~(PAGE_SIZE - 1))
-#endif
+#define PAGE_SIZE	page_size()
+#define PAGE_MASK	(~(PAGE_SIZE - 1))
+#define PAGE_SHIFT	(ffsl(page_size()) - 1)
 
 #define PAGE_PFN(addr)	((addr) / PAGE_SIZE)
-#define page_size()	sysconf(_SC_PAGESIZE)
 
 #else /* CR_NOGLIBC */
 

Comments

Mike Rapoport March 27, 2018, 5:22 a.m.
On Mon, Mar 26, 2018 at 02:07:02PM +0100, Dmitry Safonov wrote:
> On ppc64/aarch64 Linux can be set to use Large pages, so the PAGE_SIZE
> isn't build-time constant anymore. Define it through _SC_PAGESIZE.
> 
> There are different sizes for a page on ppc64:
> : #if defined(CONFIG_PPC_256K_PAGES)
> : #define PAGE_SHIFT              18
> : #elif defined(CONFIG_PPC_64K_PAGES)
> : #define PAGE_SHIFT              16
> : #elif defined(CONFIG_PPC_16K_PAGES)
> : #define PAGE_SHIFT              14
> : #else
> : #define PAGE_SHIFT              12
> : #endif
> 
> And on aarch64 there are default sizes and possibly someone can set his
> own PAGE_SHIFT:
> : config ARM64_PAGE_SHIFT
> :         int
> :         default 16 if ARM64_64K_PAGES
> :         default 14 if ARM64_16K_PAGES
> :         default 12
> 
> On the downside - each time we need PAGE_SIZE, we're doing libc
> function call on aarch64/ppc64.
> 
> Fixes: #415
> 
> Tested-by: Adrian Reber <areber@redhat.com>
> Signed-off-by: Dmitry Safonov <dima@arista.com>
> ---
>  include/common/arch/aarch64/asm/page.h | 23 +++++++++++------------
>  include/common/arch/ppc64/asm/page.h   | 25 ++++++++++---------------
>  2 files changed, 21 insertions(+), 27 deletions(-)
> 
> diff --git a/include/common/arch/aarch64/asm/page.h b/include/common/arch/aarch64/asm/page.h
> index 4126c8474a7d..a4d98aa21fb7 100644
> --- a/include/common/arch/aarch64/asm/page.h
> +++ b/include/common/arch/aarch64/asm/page.h
> @@ -4,22 +4,21 @@
>  #define ARCH_HAS_LONG_PAGES
> 
>  #ifndef CR_NOGLIBC
> -#include <unistd.h>
> +#include <string.h> /* ffsl() */
> +#include <unistd.h> /* _SC_PAGESIZE */
> 
> -#ifndef PAGE_SHIFT
> -# define PAGE_SHIFT	12
> -#endif
> -
> -#ifndef PAGE_SIZE
> -# define PAGE_SIZE	(1UL << PAGE_SHIFT)
> -#endif
> +#define page_size()	sysconf(_SC_PAGESIZE)

Maybe we could save a couple of cycles with

static unsigned long __page_size;
static inline page_size(void)
{
	if (!__page_size)
		__page_size = sysconf(_SC_PAGESIZE);
	return _page_size;
}
 

> -#ifndef PAGE_MASK
> -# define PAGE_MASK	(~(PAGE_SIZE - 1))
> -#endif
> +/*
> + * Don't add ifdefs for PAGE_SIZE: if any header defines it as a constant
> + * on aarch64, then we need refrain using PAGE_SIZE in criu and use
> + * page_size() across sources (as it may differ on aarch64).
> + */
> +#define PAGE_SIZE	page_size()
> +#define PAGE_MASK	(~(PAGE_SIZE - 1))
> +#define PAGE_SHIFT	(ffsl(page_size()) - 1)
> 
>  #define PAGE_PFN(addr)	((addr) / PAGE_SIZE)
> -#define page_size()	sysconf(_SC_PAGESIZE)
> 
>  #else /* CR_NOGLIBC */
> 
> diff --git a/include/common/arch/ppc64/asm/page.h b/include/common/arch/ppc64/asm/page.h
> index a95af55ef8a0..f2e1dcaeb616 100644
> --- a/include/common/arch/ppc64/asm/page.h
> +++ b/include/common/arch/ppc64/asm/page.h
> @@ -4,26 +4,21 @@
>  #define ARCH_HAS_LONG_PAGES
> 
>  #ifndef CR_NOGLIBC
> -#include <unistd.h>
> +#include <string.h> /* ffsl() */
> +#include <unistd.h> /* _SC_PAGESIZE */
> +
> +#define page_size()	sysconf(_SC_PAGESIZE)
> 
>  /*
> - * Default config for Pseries is to use 64K pages.
> - * See kernel file arch/powerpc/configs/pseries_*defconfig
> + * Don't add ifdefs for PAGE_SIZE: if any header defines it as a constant
> + * on ppc64, then we need refrain using PAGE_SIZE in criu and use
> + * page_size() across sources (as it may differ on ppc64).
>   */
> -#ifndef PAGE_SHIFT
> -# define PAGE_SHIFT	16
> -#endif
> -
> -#ifndef PAGE_SIZE
> -# define PAGE_SIZE	(1UL << PAGE_SHIFT)
> -#endif
> -
> -#ifndef PAGE_MASK
> -# define PAGE_MASK	(~(PAGE_SIZE - 1))
> -#endif
> +#define PAGE_SIZE	page_size()
> +#define PAGE_MASK	(~(PAGE_SIZE - 1))
> +#define PAGE_SHIFT	(ffsl(page_size()) - 1)
> 
>  #define PAGE_PFN(addr)	((addr) / PAGE_SIZE)
> -#define page_size()	sysconf(_SC_PAGESIZE)
> 
>  #else /* CR_NOGLIBC */
> 
> -- 
> 2.13.6
>
Dmitry Safonov March 27, 2018, 11:09 a.m.
2018-03-27 6:22 GMT+01:00 Mike Rapoport <rppt@linux.vnet.ibm.com>:
> Maybe we could save a couple of cycles with
>
> static unsigned long __page_size;
> static inline page_size(void)
> {
>         if (!__page_size)
>                 __page_size = sysconf(_SC_PAGESIZE);
>         return _page_size;
> }

Yeah, makes sense - I thought of doing something alike, but my wild guess
was that it's how sysconf() does this. And I omitted premature optimization.

But I like your one-function simplicity.. will send v2 with that :)
Possibly moving __page_size somewhere in .c files - otherwise, we'll end up
with a static variable per-object /รถ\