From: Ammar Faizi ammarfaizi2@gnuweeb.org
Hi Willy,
This series is a follow up of our previous discussion about getauxval() and getpagesize() functions.
It will apply cleanly on top of your "20221227-nolibc-weak-4" branch. Base commit: b6887ec8b0b0 ("tools/nolibc: add auxiliary vector retrieval for mips").
I have added a selftest for the getpagesize() function, but I am not sure how to assert the correctness of getauxval(). I think it is fine not to add a selftest for getauxval(). If you think we should, please give some advice on the test mechanism.
Thanks!
Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org ---
Ammar Faizi (3): nolibc/stdlib: Implement `getauxval(3)` function nolibc/sys: Implement `getpagesize(2)` function selftests/nolibc: Add `getpagesize(2)` selftest
tools/include/nolibc/stdlib.h | 27 ++++++++++++++++++ tools/include/nolibc/sys.h | 21 ++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 30 ++++++++++++++++++++ 3 files changed, 78 insertions(+)
base-commit: b6887ec8b0b0c78db414b78e329bf2ce234dedd5
From: Ammar Faizi ammarfaizi2@gnuweeb.org
Previous commits save the address of the auxiliary vector into a global variable @_auxv. This commit creates a new function 'getauxval()' as a helper function to get the auxv value based on the given key.
The behavior of this function is identic with the function documented in 'man 3 getauxval'. This function is also needed to implement 'getpagesize()' function that we will wire up in the next patches.
Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org --- tools/include/nolibc/stdlib.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 92378c4b9660..cdca557c4013 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -12,6 +12,7 @@ #include "types.h" #include "sys.h" #include "string.h" +#include <linux/auxvec.h>
struct nolibc_heap { size_t len; @@ -108,6 +109,32 @@ char *getenv(const char *name) return _getenv(name, environ); }
+static __attribute__((unused)) +unsigned long getauxval(unsigned long type) +{ + const unsigned long *auxv = _auxv; + unsigned long ret; + + if (!auxv) + return 0; + + while (1) { + if (!auxv[0] && !auxv[1]) { + ret = 0; + break; + } + + if (auxv[0] == type) { + ret = auxv[1]; + break; + } + + auxv += 2; + } + + return ret; +} + static __attribute__((unused)) void *malloc(size_t len) {
From: Ammar Faizi ammarfaizi2@gnuweeb.org
This function returns the page size used by the running kernel. The page size value is taken from the auxiliary vector at 'AT_PAGESZ' key.
'getpagesize(2)' is assumed as a syscall becuase the manpage placement of this function is in entry 2 ('man 2 getpagesize') despite there is no real 'getpagesize(2)' syscall in the Linux syscall table. Define this function in 'sys.h'.
Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org ---
Side note: This function calls 'getauxval(3)' function that's defined in 'stdlib.h', but since most functions in 'stdlib.h' needs 'sys.h', the 'sys.h' is always included first. Therefore, we need a forward declaration of 'getauxval(3)' in sys.h.
tools/include/nolibc/sys.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 3db1dd8c74ee..acf7cf438010 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -18,6 +18,7 @@ #include <linux/fs.h> #include <linux/loop.h> #include <linux/time.h> +#include <linux/auxvec.h>
#include "arch.h" #include "errno.h" @@ -498,6 +499,26 @@ pid_t gettid(void) return sys_gettid(); }
+static unsigned long getauxval(unsigned long key); + +/* + * long getpagesize(void); + */ + +static __attribute__((unused)) +long getpagesize(void) +{ + long ret; + + ret = getauxval(AT_PAGESZ); + if (!ret) { + SET_ERRNO(ENOENT); + return -1; + } + + return ret; +} +
/* * int gettimeofday(struct timeval *tv, struct timezone *tz);
From: Ammar Faizi ammarfaizi2@gnuweeb.org
Test the getpagesize() function. Make sure it returns the correct value.
Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org --- tools/testing/selftests/nolibc/nolibc-test.c | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 6da17612251c..3a78399f4624 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -442,6 +442,35 @@ int test_getdents64(const char *dir) return ret; }
+static int test_getpagesize(void) +{ + long x = getpagesize(); + int c; + + if (x < 0) + return x; + +#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) + /* + * x86 family is always 4K page. + */ + c = (x == 4096); +#elif defined(__aarch64__) + /* + * Linux aarch64 supports three values of page size: 4K, 16K, and 64K + * which are selected at kernel compilation time. + */ + c = (x == 4096 || x == (16 * 1024) || x == (64 * 1024)); +#else + /* + * Assuming other architectures must have at least 4K page. + */ + c = (x >= 4096); +#endif + + return !c; +} + /* Run syscall tests between IDs <min> and <max>. * Return 0 on success, non-zero on failure. */ @@ -502,6 +531,7 @@ int run_syscall(int min, int max) CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; #endif + CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break; CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break;
Hi Ammar,
On Sun, Jan 08, 2023 at 08:58:06PM +0700, Ammar Faizi wrote:
From: Ammar Faizi ammarfaizi2@gnuweeb.org
Hi Willy,
This series is a follow up of our previous discussion about getauxval() and getpagesize() functions.
It will apply cleanly on top of your "20221227-nolibc-weak-4" branch. Base commit: b6887ec8b0b0 ("tools/nolibc: add auxiliary vector retrieval for mips").
I have added a selftest for the getpagesize() function, but I am not sure how to assert the correctness of getauxval(). I think it is fine not to add a selftest for getauxval(). If you think we should, please give some advice on the test mechanism.
(...)
Thank you! I've applied it to my local queue (will push soon), and could test it on all supported archs and it works fine. Thus consider it as merged now.
Thanks! Willy
linux-kselftest-mirror@lists.linaro.org