From b20760c02318fa6da228587c401a8b2bb22a1aab Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 15 Sep 2013 02:00:32 +0000 Subject: [PATCH] support configurable page size on mips, powerpc and microblaze PAGE_SIZE was hardcoded to 4096, which is historically what most systems use, but on several archs it is a kernel config parameter, user space can only know it at execution time from the aux vector. PAGE_SIZE and PAGESIZE are not defined on archs where page size is a runtime parameter, applications should use sysconf(_SC_PAGE_SIZE) to query it. Internally libc code defines PAGE_SIZE to libc.page_size, which is set to aux[AT_PAGESZ] in __init_libc and early in __dynlink as well. (Note that libc.page_size can be accessed without GOT, ie. before relocations are done) Some fpathconf settings are hardcoded to 4096, these should be actually queried from the filesystem using statfs. --- arch/microblaze/bits/limits.h | 1 - arch/microblaze/reloc.h | 2 +- arch/mips/bits/limits.h | 1 - arch/mips/reloc.h | 2 +- arch/powerpc/bits/limits.h | 1 - arch/powerpc/reloc.h | 2 +- include/limits.h | 2 ++ src/aio/aio_readwrite.c | 2 +- src/aio/lio_listio.c | 2 +- src/conf/fpathconf.c | 10 +++++----- src/conf/sysconf.c | 5 ++++- src/env/__libc_start_main.c | 1 + src/internal/libc.h | 6 ++++++ src/ldso/dynlink.c | 1 + src/legacy/getpagesize.c | 2 +- src/legacy/valloc.c | 2 +- src/mman/mprotect.c | 2 +- src/thread/pthread_create.c | 1 + src/thread/pthread_getattr_np.c | 1 + 19 files changed, 29 insertions(+), 17 deletions(-) diff --git a/arch/microblaze/bits/limits.h b/arch/microblaze/bits/limits.h index 65a3dd64..fbc6d238 100644 --- a/arch/microblaze/bits/limits.h +++ b/arch/microblaze/bits/limits.h @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff --git a/arch/microblaze/reloc.h b/arch/microblaze/reloc.h index 60f74225..7bf3a5b0 100644 --- a/arch/microblaze/reloc.h +++ b/arch/microblaze/reloc.h @@ -49,7 +49,7 @@ void __reloc_self(int c, size_t *a, size_t *dynv) for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1]; n = t[DT_RELASZ]; for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12) diff --git a/arch/mips/bits/limits.h b/arch/mips/bits/limits.h index 65a3dd64..fbc6d238 100644 --- a/arch/mips/bits/limits.h +++ b/arch/mips/bits/limits.h @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff --git a/arch/mips/reloc.h b/arch/mips/reloc.h index 4c035f32..07fa10a7 100644 --- a/arch/mips/reloc.h +++ b/arch/mips/reloc.h @@ -51,7 +51,7 @@ void __reloc_self(int c, size_t *a, size_t *dynv, size_t *got) for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a-0x70000000UL<20) t[*a&31] = a[1]; n = t[DT_MIPS_LOCAL_GOTNO - 0x70000000]; for (a=got; n; a++, n--) *a += (size_t)base; diff --git a/arch/powerpc/bits/limits.h b/arch/powerpc/bits/limits.h index 65a3dd64..fbc6d238 100644 --- a/arch/powerpc/bits/limits.h +++ b/arch/powerpc/bits/limits.h @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff --git a/arch/powerpc/reloc.h b/arch/powerpc/reloc.h index 2877ce2a..38034c56 100644 --- a/arch/powerpc/reloc.h +++ b/arch/powerpc/reloc.h @@ -46,7 +46,7 @@ void __reloc_self(int c, size_t *a, size_t *dynv) for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1]; n = t[DT_RELASZ]; for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12) diff --git a/include/limits.h b/include/limits.h index 54d1940b..a8460cc8 100644 --- a/include/limits.h +++ b/include/limits.h @@ -40,7 +40,9 @@ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define PIPE_BUF 4096 +#ifdef PAGE_SIZE #define PAGESIZE PAGE_SIZE +#endif #define FILESIZEBITS 64 #define NAME_MAX 255 #define SYMLINK_MAX 255 diff --git a/src/aio/aio_readwrite.c b/src/aio/aio_readwrite.c index 666372db..0de3d4fb 100644 --- a/src/aio/aio_readwrite.c +++ b/src/aio/aio_readwrite.c @@ -2,8 +2,8 @@ #include #include #include -#include #include "pthread_impl.h" +#include "libc.h" static void dummy(void) { diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c index 07145dd4..61d7f20e 100644 --- a/src/aio/lio_listio.c +++ b/src/aio/lio_listio.c @@ -1,9 +1,9 @@ #include #include -#include #include #include #include "pthread_impl.h" +#include "libc.h" struct lio_state { struct sigevent *sev; diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c index bfbb2742..28c4345c 100644 --- a/src/conf/fpathconf.c +++ b/src/conf/fpathconf.c @@ -19,11 +19,11 @@ long fpathconf(int fd, int name) [_PC_PRIO_IO] = -1, [_PC_SOCK_MAXBUF] = -1, [_PC_FILESIZEBITS] = FILESIZEBITS, - [_PC_REC_INCR_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_MAX_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_MIN_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_XFER_ALIGN] = PAGE_SIZE, - [_PC_ALLOC_SIZE_MIN] = PAGE_SIZE, + [_PC_REC_INCR_XFER_SIZE] = 4096, + [_PC_REC_MAX_XFER_SIZE] = 4096, + [_PC_REC_MIN_XFER_SIZE] = 4096, + [_PC_REC_XFER_ALIGN] = 4096, + [_PC_ALLOC_SIZE_MIN] = 4096, [_PC_SYMLINK_MAX] = SYMLINK_MAX, [_PC_2_SYMLINKS] = 1 }; diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 5dc1e453..97fd4fad 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -3,6 +3,7 @@ #include #include #include "syscall.h" +#include "libc.h" #define VER (-2) #define OFLOW (-3) @@ -42,7 +43,7 @@ long sysconf(int name) [_SC_MQ_OPEN_MAX] = -1, [_SC_MQ_PRIO_MAX] = OFLOW, [_SC_VERSION] = VER, - [_SC_PAGE_SIZE] = PAGE_SIZE, + [_SC_PAGE_SIZE] = OFLOW, [_SC_RTSIG_MAX] = 63, /* ?? */ [_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX, [_SC_SEM_VALUE_MAX] = OFLOW, @@ -222,6 +223,8 @@ long sysconf(int name) if (name == _SC_ARG_MAX) return ARG_MAX; if (name == _SC_SEM_VALUE_MAX) return SEM_VALUE_MAX; if (name == _SC_MQ_PRIO_MAX) return MQ_PRIO_MAX; + /* name == _SC_PAGE_SIZE */ + return PAGE_SIZE; } else if (values[name] == CPUCNT) { unsigned char set[128] = {1}; int i, cnt; diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index 2a8698bb..73d49327 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -26,6 +26,7 @@ void __init_libc(char **envp, char *pn) for (i=0; auxv[i]; i+=2) if (auxv[i] #include +#include struct __libc { void *main_thread; @@ -14,10 +15,15 @@ struct __libc { FILE *ofl_head; int ofl_lock[2]; size_t tls_size; + size_t page_size; }; extern size_t __hwcap; +#ifndef PAGE_SIZE +#define PAGE_SIZE libc.page_size +#endif + #if !defined(__PIC__) || (100*__GNUC__+__GNUC_MINOR__ >= 303 && !defined(__PCC__)) #ifdef __PIC__ diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index a89e7432..a525b3d8 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -980,6 +980,7 @@ void *__dynlink(int argc, char **argv) env_preload = 0; libc.secure = 1; } + libc.page_size = aux[AT_PAGESZ]; /* If the dynamic linker was invoked as a program itself, AT_BASE * will not be set. In that case, we assume the base address is diff --git a/src/legacy/getpagesize.c b/src/legacy/getpagesize.c index 5ede652b..a47995cb 100644 --- a/src/legacy/getpagesize.c +++ b/src/legacy/getpagesize.c @@ -1,5 +1,5 @@ #include -#include +#include "libc.h" int getpagesize(void) { diff --git a/src/legacy/valloc.c b/src/legacy/valloc.c index e48cf214..5af2256a 100644 --- a/src/legacy/valloc.c +++ b/src/legacy/valloc.c @@ -1,6 +1,6 @@ #define _BSD_SOURCE #include -#include +#include "libc.h" void *valloc(size_t size) { diff --git a/src/mman/mprotect.c b/src/mman/mprotect.c index 5ab2d8b0..f488486d 100644 --- a/src/mman/mprotect.c +++ b/src/mman/mprotect.c @@ -1,5 +1,5 @@ #include -#include +#include "libc.h" #include "syscall.h" int mprotect(void *addr, size_t len, int prot) diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 6c841be7..d26f252e 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -1,5 +1,6 @@ #include "pthread_impl.h" #include "stdio_impl.h" +#include "libc.h" #include static void dummy_0() diff --git a/src/thread/pthread_getattr_np.c b/src/thread/pthread_getattr_np.c index 86df1def..10ea5127 100644 --- a/src/thread/pthread_getattr_np.c +++ b/src/thread/pthread_getattr_np.c @@ -1,5 +1,6 @@ #define _GNU_SOURCE #include "pthread_impl.h" +#include "libc.h" #include int pthread_getattr_np(pthread_t t, pthread_attr_t *a) -- 2.25.1