From cefe22bdaca2e6f42fa8aec4979465fd702a38ef Mon Sep 17 00:00:00 2001 From: Christopher Covington Date: Mon, 20 Apr 2015 18:09:00 +0300 Subject: [PATCH] Use run-time page size where it matters In AArch64, pages may be 4K or 64K depending on kernel configuration. The GNU C Library documentation suggests [1], "the correct interface to query about the page size is sysconf". Introduce one new architecture-specific function-like macro, page_size(), that on x86 and AArch32 remains a constant so as to minimally affect performance, but on AArch64 is sysconf(_SC_PAGESIZE) for correctness. 1. https://www.gnu.org/software/libc/manual/html_node/Query-Memory-Parameters.html To minimize churn, the PAGE_SIZE macro is left as a build-time estimation of what the run-time page size might be. This fixes the following errors for CRIU on AArch64 kernels with CONFIG_ARM64_64K_PAGES=y, allowing dump of `setsid sleep < /dev/null &> /dev/null` to succeed. Error (kerndat.c:48): Can't stat self map_files: No such file or directory Error (util.c:668): Can't read pme for pid 90: No such file or directory Error (parasite-syscall.c:1135): Can't open 89/map_files/0x3ffb7da0000-0x3ffb7dac000 on procfs: No such file or directory Signed-off-by: Christopher Covington Acked-by: Cyrill Gorcunov Signed-off-by: Pavel Emelyanov --- arch/aarch64/include/asm/page.h | 19 +++++++++++++++++++ arch/aarch64/include/asm/types.h | 2 +- .../arm/include/asm}/page.h | 7 ++++--- arch/arm/include/asm/types.h | 2 +- arch/x86/include/asm/page.h | 19 +++++++++++++++++++ arch/x86/include/asm/types.h | 2 +- bfd.c | 2 +- include/pagemap-cache.h | 2 +- kerndat.c | 2 +- parasite-syscall.c | 2 +- util.c | 2 +- 11 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 arch/aarch64/include/asm/page.h rename {include/asm-generic => arch/arm/include/asm}/page.h (66%) create mode 100644 arch/x86/include/asm/page.h diff --git a/arch/aarch64/include/asm/page.h b/arch/aarch64/include/asm/page.h new file mode 100644 index 000000000..c16f46783 --- /dev/null +++ b/arch/aarch64/include/asm/page.h @@ -0,0 +1,19 @@ +#ifndef __CR_ASM_PAGE_H__ +#define __CR_ASM_PAGE_H__ + +#ifndef PAGE_SHIFT +# define PAGE_SHIFT 12 +#endif + +#ifndef PAGE_SIZE +# define PAGE_SIZE (1UL << PAGE_SHIFT) +#endif + +#ifndef PAGE_MASK +# define PAGE_MASK (~(PAGE_SIZE - 1)) +#endif + +#define PAGE_PFN(addr) ((addr) / PAGE_SIZE) +#define page_size() sysconf(_SC_PAGESIZE) + +#endif /* __CR_ASM_PAGE_H__ */ diff --git a/arch/aarch64/include/asm/types.h b/arch/aarch64/include/asm/types.h index 6657279d9..6512f679e 100644 --- a/arch/aarch64/include/asm/types.h +++ b/arch/aarch64/include/asm/types.h @@ -6,7 +6,7 @@ #include #include "protobuf/core.pb-c.h" -#include "asm-generic/page.h" +#include "asm/page.h" #include "asm/bitops.h" #include "asm/int.h" diff --git a/include/asm-generic/page.h b/arch/arm/include/asm/page.h similarity index 66% rename from include/asm-generic/page.h rename to arch/arm/include/asm/page.h index 02d90b528..134835556 100644 --- a/include/asm-generic/page.h +++ b/arch/arm/include/asm/page.h @@ -1,5 +1,5 @@ -#ifndef __CR_ASM_GENERIC_PAGE_H__ -#define __CR_ASM_GENERIC_PAGE_H__ +#ifndef __CR_ASM_PAGE_H__ +#define __CR_ASM_PAGE_H__ #ifndef PAGE_SHIFT # define PAGE_SHIFT 12 @@ -14,5 +14,6 @@ #endif #define PAGE_PFN(addr) ((addr) / PAGE_SIZE) +#define page_size() PAGE_SIZE -#endif /* __CR_ASM_GENERIC_PAGE_H__ */ +#endif /* __CR_ASM_PAGE_H__ */ diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index e9aa636dc..4efebddda 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -5,7 +5,7 @@ #include #include "protobuf/core.pb-c.h" -#include "asm-generic/page.h" +#include "asm/page.h" #include "asm/bitops.h" #include "asm/int.h" diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h new file mode 100644 index 000000000..134835556 --- /dev/null +++ b/arch/x86/include/asm/page.h @@ -0,0 +1,19 @@ +#ifndef __CR_ASM_PAGE_H__ +#define __CR_ASM_PAGE_H__ + +#ifndef PAGE_SHIFT +# define PAGE_SHIFT 12 +#endif + +#ifndef PAGE_SIZE +# define PAGE_SIZE (1UL << PAGE_SHIFT) +#endif + +#ifndef PAGE_MASK +# define PAGE_MASK (~(PAGE_SIZE - 1)) +#endif + +#define PAGE_PFN(addr) ((addr) / PAGE_SIZE) +#define page_size() PAGE_SIZE + +#endif /* __CR_ASM_PAGE_H__ */ diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index d7e869a50..9b0db3c0f 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -4,7 +4,7 @@ #include #include -#include "asm-generic/page.h" +#include "asm/page.h" #include "asm/bitops.h" #include "asm/int.h" #include "asm/prlimit.h" diff --git a/bfd.c b/bfd.c index d63b3e0e2..81ac2b010 100644 --- a/bfd.c +++ b/bfd.c @@ -13,7 +13,7 @@ #include "list.h" #include "util.h" #include "xmalloc.h" -#include "asm-generic/page.h" +#include "asm/page.h" #undef LOG_PREFIX #define LOG_PREFIX "bfd: " diff --git a/include/pagemap-cache.h b/include/pagemap-cache.h index 48e366c7f..37291ab27 100644 --- a/include/pagemap-cache.h +++ b/include/pagemap-cache.h @@ -2,7 +2,7 @@ #define __CR_PAGEMAP_H__ #include -#include "asm-generic/page.h" +#include "asm/page.h" #include "asm/int.h" #include "list.h" diff --git a/kerndat.c b/kerndat.c index 63a3da53d..7946ab41f 100644 --- a/kerndat.c +++ b/kerndat.c @@ -42,7 +42,7 @@ static int kerndat_get_shmemdev(void) } sprintf(maps, "/proc/self/map_files/%lx-%lx", - (unsigned long)map, (unsigned long)map + PAGE_SIZE); + (unsigned long)map, (unsigned long)map + page_size()); if (stat(maps, &buf) < 0) { munmap(map, PAGE_SIZE); pr_perror("Can't stat self map_files"); diff --git a/parasite-syscall.c b/parasite-syscall.c index fa4362705..34c4ce375 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -1129,7 +1129,7 @@ int parasite_map_exchange(struct parasite_ctl *ctl, unsigned long size) return -1; } - ctl->map_length = round_up(size, PAGE_SIZE); + ctl->map_length = round_up(size, page_size()); fd = open_proc_rw(ctl->pid.real, "map_files/%p-%p", ctl->remote_map, ctl->remote_map + ctl->map_length); diff --git a/util.c b/util.c index 03dc2f667..36162c437 100644 --- a/util.c +++ b/util.c @@ -657,7 +657,7 @@ int vaddr_to_pfn(unsigned long vaddr, u64 *pfn) if (fd < 0) return -1; - off = (vaddr / PAGE_SIZE) * sizeof(u64); + off = (vaddr / page_size()) * sizeof(u64); if (lseek(fd, off, SEEK_SET) != off) { pr_perror("Failed to seek address %lx", vaddr); goto out;