about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2013-09-15 02:00:32 +0000
committerSzabolcs Nagy <nsz@port70.net>2013-09-15 02:00:32 +0000
commitb20760c02318fa6da228587c401a8b2bb22a1aab (patch)
treea9bf139467269eb8a87fa2bb3423259eb59903e3
parent7a34dd3495d4bcd3dadc8b9fe2c89f819c15e7fd (diff)
downloadmusl-b20760c02318fa6da228587c401a8b2bb22a1aab.tar.gz
musl-b20760c02318fa6da228587c401a8b2bb22a1aab.tar.xz
musl-b20760c02318fa6da228587c401a8b2bb22a1aab.zip
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.
-rw-r--r--arch/microblaze/bits/limits.h1
-rw-r--r--arch/microblaze/reloc.h2
-rw-r--r--arch/mips/bits/limits.h1
-rw-r--r--arch/mips/reloc.h2
-rw-r--r--arch/powerpc/bits/limits.h1
-rw-r--r--arch/powerpc/reloc.h2
-rw-r--r--include/limits.h2
-rw-r--r--src/aio/aio_readwrite.c2
-rw-r--r--src/aio/lio_listio.c2
-rw-r--r--src/conf/fpathconf.c10
-rw-r--r--src/conf/sysconf.c5
-rw-r--r--src/env/__libc_start_main.c1
-rw-r--r--src/internal/libc.h6
-rw-r--r--src/ldso/dynlink.c1
-rw-r--r--src/legacy/getpagesize.c2
-rw-r--r--src/legacy/valloc.c2
-rw-r--r--src/mman/mprotect.c2
-rw-r--r--src/thread/pthread_create.c1
-rw-r--r--src/thread/pthread_getattr_np.c1
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 <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
-#include <limits.h>
 #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 <aio.h>
 #include <errno.h>
-#include <limits.h>
 #include <unistd.h>
 #include <string.h>
 #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 <errno.h>
 #include <sys/resource.h>
 #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]<AUX_CNT) aux[auxv[i]] = auxv[i+1];
 	__hwcap = aux[AT_HWCAP];
 	__sysinfo = aux[AT_SYSINFO];
+	libc.page_size = aux[AT_PAGESZ];
 
 	if (pn) {
 		__progname = __progname_full = pn;
diff --git a/src/internal/libc.h b/src/internal/libc.h
index c8fbe3fd..3350b3d1 100644
--- a/src/internal/libc.h
+++ b/src/internal/libc.h
@@ -3,6 +3,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <limits.h>
 
 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 <unistd.h>
-#include <limits.h>
+#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 <stdlib.h>
-#include <limits.h>
+#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 <sys/mman.h>
-#include <limits.h>
+#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 <sys/mman.h>
 
 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 <sys/mman.h>
 
 int pthread_getattr_np(pthread_t t, pthread_attr_t *a)