2023-01-08 13:59:52

by Ammar Faizi

[permalink] [raw]
Subject: [RESEND PATCH v1 0/3] nolibc auxiliary vector retrieval support

From: Ammar Faizi <[email protected]>

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 <[email protected]>
---

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
--
Ammar Faizi


2023-01-08 14:00:01

by Ammar Faizi

[permalink] [raw]
Subject: [RESEND PATCH v1 1/3] nolibc/stdlib: Implement `getauxval(3)` function

From: Ammar Faizi <[email protected]>

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 <[email protected]>
---
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)
{
--
Ammar Faizi

2023-01-08 14:00:05

by Ammar Faizi

[permalink] [raw]
Subject: [RESEND PATCH v1 2/3] nolibc/sys: Implement `getpagesize(2)` function

From: Ammar Faizi <[email protected]>

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 <[email protected]>
---

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);
--
Ammar Faizi

2023-01-08 14:53:22

by Ammar Faizi

[permalink] [raw]
Subject: [RESEND PATCH v1 3/3] selftests/nolibc: Add `getpagesize(2)` selftest

From: Ammar Faizi <[email protected]>

Test the getpagesize() function. Make sure it returns the correct
value.

Signed-off-by: Ammar Faizi <[email protected]>
---
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;
--
Ammar Faizi

2023-01-08 17:27:29

by Willy Tarreau

[permalink] [raw]
Subject: Re: [RESEND PATCH v1 0/3] nolibc auxiliary vector retrieval support

Hi Ammar,

On Sun, Jan 08, 2023 at 08:58:06PM +0700, Ammar Faizi wrote:
> From: Ammar Faizi <[email protected]>
>
> 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