summaryrefslogtreecommitdiff
path: root/tools/include
diff options
context:
space:
mode:
Diffstat (limited to 'tools/include')
-rw-r--r--tools/include/linux/compiler-context-analysis.h42
-rw-r--r--tools/include/linux/compiler_types.h40
-rw-r--r--tools/include/linux/mm.h1
-rw-r--r--tools/include/linux/unaligned.h4
-rw-r--r--tools/include/nolibc/Makefile6
-rw-r--r--tools/include/nolibc/arch-s390.h11
-rw-r--r--tools/include/nolibc/compiler.h24
-rw-r--r--tools/include/nolibc/nolibc.h1
-rw-r--r--tools/include/nolibc/poll.h14
-rw-r--r--tools/include/nolibc/std.h2
-rw-r--r--tools/include/nolibc/stdio.h53
-rw-r--r--tools/include/nolibc/sys.h18
-rw-r--r--tools/include/nolibc/sys/ptrace.h33
-rw-r--r--tools/include/nolibc/sys/select.h25
-rw-r--r--tools/include/nolibc/sys/time.h6
-rw-r--r--tools/include/nolibc/sys/timerfd.h32
-rw-r--r--tools/include/nolibc/time.h102
-rw-r--r--tools/include/nolibc/types.h17
-rw-r--r--tools/include/uapi/asm-generic/errno.h2
-rw-r--r--tools/include/uapi/linux/bpf.h28
-rw-r--r--tools/include/uapi/linux/perf_event.h27
-rw-r--r--tools/include/vdso/unaligned.h41
22 files changed, 361 insertions, 168 deletions
diff --git a/tools/include/linux/compiler-context-analysis.h b/tools/include/linux/compiler-context-analysis.h
new file mode 100644
index 000000000000..13a9115e9e58
--- /dev/null
+++ b/tools/include/linux/compiler-context-analysis.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _TOOLS_LINUX_COMPILER_CONTEXT_ANALYSIS_H
+#define _TOOLS_LINUX_COMPILER_CONTEXT_ANALYSIS_H
+
+/*
+ * Macros and attributes for compiler-based static context analysis.
+ * No-op stubs for tools.
+ */
+
+#define __guarded_by(...)
+#define __pt_guarded_by(...)
+
+#define context_lock_struct(name, ...) struct __VA_ARGS__ name
+
+#define __no_context_analysis
+#define __context_unsafe(comment)
+#define context_unsafe(...) ({ __VA_ARGS__; })
+#define context_unsafe_alias(p)
+#define disable_context_analysis()
+#define enable_context_analysis()
+
+#define __must_hold(...)
+#define __must_not_hold(...)
+#define __acquires(...)
+#define __cond_acquires(ret, x)
+#define __releases(...)
+#define __acquire(x) (void)0
+#define __release(x) (void)0
+
+#define __must_hold_shared(...)
+#define __acquires_shared(...)
+#define __cond_acquires_shared(ret, x)
+#define __releases_shared(...)
+#define __acquire_shared(x) (void)0
+#define __release_shared(x) (void)0
+
+#define __acquire_ret(call, expr) (call)
+#define __acquire_shared_ret(call, expr) (call)
+#define __acquires_ret
+#define __acquires_shared_ret
+
+#endif /* _TOOLS_LINUX_COMPILER_CONTEXT_ANALYSIS_H */
diff --git a/tools/include/linux/compiler_types.h b/tools/include/linux/compiler_types.h
index d09f9dc172a4..b3adbf5682f0 100644
--- a/tools/include/linux/compiler_types.h
+++ b/tools/include/linux/compiler_types.h
@@ -13,23 +13,7 @@
#define __has_builtin(x) (0)
#endif
-#ifdef __CHECKER__
-/* context/locking */
-# define __must_hold(x) __attribute__((context(x,1,1)))
-# define __acquires(x) __attribute__((context(x,0,1)))
-# define __releases(x) __attribute__((context(x,1,0)))
-# define __acquire(x) __context__(x,1)
-# define __release(x) __context__(x,-1)
-# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
-#else /* __CHECKER__ */
-/* context/locking */
-# define __must_hold(x)
-# define __acquires(x)
-# define __releases(x)
-# define __acquire(x) (void)0
-# define __release(x) (void)0
-# define __cond_lock(x,c) (c)
-#endif /* __CHECKER__ */
+#include <linux/compiler-context-analysis.h>
/* Compiler specific macros. */
#ifdef __GNUC__
@@ -40,4 +24,26 @@
#define asm_goto_output(x...) asm goto(x)
#endif
+/*
+ * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
+ * non-scalar types unchanged.
+ */
+/*
+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
+ * is not type-compatible with 'signed char', and we define a separate case.
+ */
+#define __scalar_type_to_expr_cases(type) \
+ unsigned type: (unsigned type)0, \
+ signed type: (signed type)0
+
+#define __unqual_scalar_typeof(x) typeof( \
+ _Generic((x), \
+ char: (char)0, \
+ __scalar_type_to_expr_cases(char), \
+ __scalar_type_to_expr_cases(short), \
+ __scalar_type_to_expr_cases(int), \
+ __scalar_type_to_expr_cases(long), \
+ __scalar_type_to_expr_cases(long long), \
+ default: (x)))
+
#endif /* __LINUX_COMPILER_TYPES_H */
diff --git a/tools/include/linux/mm.h b/tools/include/linux/mm.h
index 677c37e4a18c..028f3faf46e7 100644
--- a/tools/include/linux/mm.h
+++ b/tools/include/linux/mm.h
@@ -4,6 +4,7 @@
#include <linux/align.h>
#include <linux/mmzone.h>
+#include <linux/sizes.h>
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
diff --git a/tools/include/linux/unaligned.h b/tools/include/linux/unaligned.h
index 395a4464fe73..d51ddafed138 100644
--- a/tools/include/linux/unaligned.h
+++ b/tools/include/linux/unaligned.h
@@ -6,9 +6,6 @@
* This is the most generic implementation of unaligned accesses
* and should work almost anywhere.
*/
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpacked"
-#pragma GCC diagnostic ignored "-Wattributes"
#include <vdso/unaligned.h>
#define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr))
@@ -143,6 +140,5 @@ static inline u64 get_unaligned_be48(const void *p)
{
return __get_unaligned_be48(p);
}
-#pragma GCC diagnostic pop
#endif /* __LINUX_UNALIGNED_H */
diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile
index 8118e22844f1..1958dda98895 100644
--- a/tools/include/nolibc/Makefile
+++ b/tools/include/nolibc/Makefile
@@ -54,6 +54,7 @@ all_files := \
sys/mman.h \
sys/mount.h \
sys/prctl.h \
+ sys/ptrace.h \
sys/random.h \
sys/reboot.h \
sys/resource.h \
@@ -103,9 +104,12 @@ headers_standalone: headers
$(Q)$(MAKE) -C $(srctree) headers
$(Q)$(MAKE) -C $(srctree) headers_install INSTALL_HDR_PATH=$(OUTPUT)sysroot
+CFLAGS_s390 := -m64
+CFLAGS := $(CFLAGS_$(ARCH))
+
headers_check: headers_standalone
$(Q)for header in $(filter-out crt.h std.h,$(all_files)); do \
- $(CC) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \
+ $(CC) $(CFLAGS) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \
-I$(or $(objtree),$(srctree))/usr/include -include $$header -include $$header || exit 1; \
done
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
index 74125a254ce3..904281e95f99 100644
--- a/tools/include/nolibc/arch-s390.h
+++ b/tools/include/nolibc/arch-s390.h
@@ -5,6 +5,10 @@
#ifndef _NOLIBC_ARCH_S390_H
#define _NOLIBC_ARCH_S390_H
+
+#include "types.h"
+
+#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/unistd.h>
@@ -186,4 +190,11 @@ pid_t sys_fork(void)
}
#define sys_fork sys_fork
+static __attribute__((unused))
+pid_t sys_vfork(void)
+{
+ return my_syscall5(__NR_clone, 0, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0);
+}
+#define sys_vfork sys_vfork
+
#endif /* _NOLIBC_ARCH_S390_H */
diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
index 87090bbc53e0..a8c7619dcdde 100644
--- a/tools/include/nolibc/compiler.h
+++ b/tools/include/nolibc/compiler.h
@@ -47,4 +47,28 @@
# define __nolibc_fallthrough do { } while (0)
#endif /* __nolibc_has_attribute(fallthrough) */
+#define __nolibc_version(_major, _minor, _patch) ((_major) * 10000 + (_minor) * 100 + (_patch))
+
+#ifdef __GNUC__
+# define __nolibc_gnuc_version \
+ __nolibc_version(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define __nolibc_gnuc_version 0
+#endif /* __GNUC__ */
+
+#ifdef __clang__
+# define __nolibc_clang_version \
+ __nolibc_version(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define __nolibc_clang_version 0
+#endif /* __clang__ */
+
+#if __STDC_VERSION__ >= 201112L || \
+ __nolibc_gnuc_version >= __nolibc_version(4, 6, 0) || \
+ __nolibc_clang_version >= __nolibc_version(3, 0, 0)
+# define __nolibc_static_assert(_t) _Static_assert(_t, "")
+#else
+# define __nolibc_static_assert(_t)
+#endif
+
#endif /* _NOLIBC_COMPILER_H */
diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h
index 272dfc961158..9c7f43b9218b 100644
--- a/tools/include/nolibc/nolibc.h
+++ b/tools/include/nolibc/nolibc.h
@@ -101,6 +101,7 @@
#include "sys/mman.h"
#include "sys/mount.h"
#include "sys/prctl.h"
+#include "sys/ptrace.h"
#include "sys/random.h"
#include "sys/reboot.h"
#include "sys/resource.h"
diff --git a/tools/include/nolibc/poll.h b/tools/include/nolibc/poll.h
index 0d053f93ea99..e854c94647b1 100644
--- a/tools/include/nolibc/poll.h
+++ b/tools/include/nolibc/poll.h
@@ -23,24 +23,22 @@
static __attribute__((unused))
int sys_poll(struct pollfd *fds, int nfds, int timeout)
{
-#if defined(__NR_ppoll)
- struct timespec t;
+#if defined(__NR_ppoll_time64)
+ struct __kernel_timespec t;
if (timeout >= 0) {
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
- return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
-#elif defined(__NR_ppoll_time64)
- struct __kernel_timespec t;
+ return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
+#else
+ struct __kernel_old_timespec t;
if (timeout >= 0) {
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
- return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
-#else
- return my_syscall3(__NR_poll, fds, nfds, timeout);
+ return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
#endif
}
diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h
index 392f4dd94158..b9a116123902 100644
--- a/tools/include/nolibc/std.h
+++ b/tools/include/nolibc/std.h
@@ -29,6 +29,6 @@ typedef unsigned long nlink_t;
typedef int64_t off_t;
typedef signed long blksize_t;
typedef signed long blkcnt_t;
-typedef __kernel_time_t time_t;
+typedef __kernel_time64_t time_t;
#endif /* _NOLIBC_STD_H */
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 1f16dab2ac88..233318b0d0f0 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -170,7 +170,7 @@ int putchar(int c)
}
-/* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
+/* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
/* internal fwrite()-like function which only takes a size and returns 0 on
* success or EOF on error. It automatically retries on short writes.
@@ -204,6 +204,38 @@ size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
return written;
}
+/* internal fread()-like function which only takes a size and returns 0 on
+ * success or EOF on error. It automatically retries on short reads.
+ */
+static __attribute__((unused))
+int _fread(void *buf, size_t size, FILE *stream)
+{
+ int fd = fileno(stream);
+ ssize_t ret;
+
+ while (size) {
+ ret = read(fd, buf, size);
+ if (ret <= 0)
+ return EOF;
+ size -= ret;
+ buf += ret;
+ }
+ return 0;
+}
+
+static __attribute__((unused))
+size_t fread(void *s, size_t size, size_t nmemb, FILE *stream)
+{
+ size_t nread;
+
+ for (nread = 0; nread < nmemb; nread++) {
+ if (_fread(s, size, stream) != 0)
+ break;
+ s += size;
+ }
+ return nread;
+}
+
static __attribute__((unused))
int fputs(const char *s, FILE *stream)
{
@@ -240,6 +272,25 @@ char *fgets(char *s, int size, FILE *stream)
}
+/* fseek */
+static __attribute__((unused))
+int fseek(FILE *stream, long offset, int whence)
+{
+ int fd = fileno(stream);
+ off_t ret;
+
+ ret = lseek(fd, offset, whence);
+
+ /* lseek() and fseek() differ in that lseek returns the new
+ * position or -1, fseek() returns either 0 or -1.
+ */
+ if (ret >= 0)
+ return 0;
+
+ return -1;
+}
+
+
/* minimal printf(). It supports the following formats:
* - %[l*]{d,u,c,x,p}
* - %s
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h
index 847af1ccbdc9..403ee9ce8389 100644
--- a/tools/include/nolibc/sys.h
+++ b/tools/include/nolibc/sys.h
@@ -22,7 +22,7 @@
#include <linux/time.h>
#include <linux/auxvec.h>
#include <linux/fcntl.h> /* for O_* and AT_* */
-#include <linux/sched.h> /* for clone_args */
+#include <linux/sched.h> /* for CLONE_* */
#include <linux/stat.h> /* for statx() */
#include "errno.h"
@@ -363,19 +363,11 @@ pid_t fork(void)
static __attribute__((unused))
pid_t sys_vfork(void)
{
-#if defined(__NR_vfork)
+#if defined(__NR_clone)
+ /* See the note in sys_fork(). */
+ return my_syscall5(__NR_clone, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0, 0);
+#elif defined(__NR_vfork)
return my_syscall0(__NR_vfork);
-#else
- /*
- * clone() could be used but has different argument orders per
- * architecture.
- */
- struct clone_args args = {
- .flags = CLONE_VM | CLONE_VFORK,
- .exit_signal = SIGCHLD,
- };
-
- return my_syscall2(__NR_clone3, &args, sizeof(args));
#endif
}
#endif
diff --git a/tools/include/nolibc/sys/ptrace.h b/tools/include/nolibc/sys/ptrace.h
new file mode 100644
index 000000000000..72ca28541633
--- /dev/null
+++ b/tools/include/nolibc/sys/ptrace.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * ptrace for NOLIBC
+ * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
+ * Copyright (C) 2025 Intel Corporation
+ */
+
+/* make sure to include all global symbols */
+#include "../nolibc.h"
+
+#ifndef _NOLIBC_SYS_PTRACE_H
+#define _NOLIBC_SYS_PTRACE_H
+
+#include "../sys.h"
+
+#include <linux/ptrace.h>
+
+/*
+ * long ptrace(int op, pid_t pid, void *addr, void *data);
+ */
+static __attribute__((unused))
+long sys_ptrace(int op, pid_t pid, void *addr, void *data)
+{
+ return my_syscall4(__NR_ptrace, op, pid, addr, data);
+}
+
+static __attribute__((unused))
+ssize_t ptrace(int op, pid_t pid, void *addr, void *data)
+{
+ return __sysret(sys_ptrace(op, pid, addr, data));
+}
+
+#endif /* _NOLIBC_SYS_PTRACE_H */
diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h
index 2a5619c01277..80cb3755ba18 100644
--- a/tools/include/nolibc/sys/select.h
+++ b/tools/include/nolibc/sys/select.h
@@ -63,33 +63,22 @@ typedef struct {
static __attribute__((unused))
int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
{
-#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
- struct sel_arg_struct {
- unsigned long n;
- fd_set *r, *w, *e;
- struct timeval *t;
- } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
- return my_syscall1(__NR_select, &arg);
-#elif defined(__NR__newselect)
- return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
-#elif defined(__NR_select)
- return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout);
-#elif defined(__NR_pselect6)
- struct timespec t;
+#if defined(__NR_pselect6_time64)
+ struct __kernel_timespec t;
if (timeout) {
t.tv_sec = timeout->tv_sec;
- t.tv_nsec = timeout->tv_usec * 1000;
+ t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
}
- return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
+ return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#else
- struct __kernel_timespec t;
+ struct __kernel_old_timespec t;
if (timeout) {
t.tv_sec = timeout->tv_sec;
- t.tv_nsec = timeout->tv_usec * 1000;
+ t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
}
- return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
+ return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#endif
}
diff --git a/tools/include/nolibc/sys/time.h b/tools/include/nolibc/sys/time.h
index 33782a19aae9..afdb7e326df1 100644
--- a/tools/include/nolibc/sys/time.h
+++ b/tools/include/nolibc/sys/time.h
@@ -22,9 +22,6 @@ static int sys_clock_gettime(clockid_t clockid, struct timespec *tp);
static __attribute__((unused))
int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
-#ifdef __NR_gettimeofday
- return my_syscall2(__NR_gettimeofday, tv, tz);
-#else
(void) tz; /* Non-NULL tz is undefined behaviour */
struct timespec tp;
@@ -33,11 +30,10 @@ int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
ret = sys_clock_gettime(CLOCK_REALTIME, &tp);
if (!ret && tv) {
tv->tv_sec = tp.tv_sec;
- tv->tv_usec = tp.tv_nsec / 1000;
+ tv->tv_usec = (uint32_t)tp.tv_nsec / 1000;
}
return ret;
-#endif
}
static __attribute__((unused))
diff --git a/tools/include/nolibc/sys/timerfd.h b/tools/include/nolibc/sys/timerfd.h
index 5dd61030c991..29fd92bd47d2 100644
--- a/tools/include/nolibc/sys/timerfd.h
+++ b/tools/include/nolibc/sys/timerfd.h
@@ -32,16 +32,12 @@ int timerfd_create(int clockid, int flags)
static __attribute__((unused))
int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
{
-#if defined(__NR_timerfd_gettime)
- return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
+#if defined(__NR_timerfd_gettime64)
+ __nolibc_assert_time64_type(curr_value->it_value.tv_sec);
+ return my_syscall2(__NR_timerfd_gettime64, fd, curr_value);
#else
- struct __kernel_itimerspec kcurr_value;
- int ret;
-
- ret = my_syscall2(__NR_timerfd_gettime64, fd, &kcurr_value);
- __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
#endif
}
@@ -56,20 +52,12 @@ static __attribute__((unused))
int sys_timerfd_settime(int fd, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
-#if defined(__NR_timerfd_settime)
- return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
+#if defined(__NR_timerfd_settime64)
+ __nolibc_assert_time64_type(new_value->it_value.tv_sec);
+ return my_syscall4(__NR_timerfd_settime64, fd, flags, new_value, old_value);
#else
- struct __kernel_itimerspec knew_value, kold_value;
- int ret;
-
- __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
- __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
- ret = my_syscall4(__NR_timerfd_settime64, fd, flags, &knew_value, &kold_value);
- if (old_value) {
- __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
- }
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
#endif
}
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index 48e78f8becf9..f9257d6a7878 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -18,19 +18,11 @@
#include <linux/signal.h>
#include <linux/time.h>
-static __inline__
-void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts)
-{
- kts->tv_sec = ts->tv_sec;
- kts->tv_nsec = ts->tv_nsec;
-}
+#define __nolibc_assert_time64_type(t) \
+ __nolibc_static_assert(sizeof(t) == 8)
-static __inline__
-void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struct timespec *ts)
-{
- ts->tv_sec = kts->tv_sec;
- ts->tv_nsec = kts->tv_nsec;
-}
+#define __nolibc_assert_native_time64() \
+ __nolibc_assert_time64_type(__kernel_old_time_t)
/*
* int clock_getres(clockid_t clockid, struct timespec *res);
@@ -43,16 +35,12 @@ void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struc
static __attribute__((unused))
int sys_clock_getres(clockid_t clockid, struct timespec *res)
{
-#if defined(__NR_clock_getres)
- return my_syscall2(__NR_clock_getres, clockid, res);
+#if defined(__NR_clock_getres_time64)
+ __nolibc_assert_time64_type(res->tv_sec);
+ return my_syscall2(__NR_clock_getres_time64, clockid, res);
#else
- struct __kernel_timespec kres;
- int ret;
-
- ret = my_syscall2(__NR_clock_getres_time64, clockid, &kres);
- if (res)
- __nolibc_timespec_kernel_to_user(&kres, res);
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall2(__NR_clock_getres, clockid, res);
#endif
}
@@ -65,16 +53,12 @@ int clock_getres(clockid_t clockid, struct timespec *res)
static __attribute__((unused))
int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
{
-#if defined(__NR_clock_gettime)
- return my_syscall2(__NR_clock_gettime, clockid, tp);
+#if defined(__NR_clock_gettime64)
+ __nolibc_assert_time64_type(tp->tv_sec);
+ return my_syscall2(__NR_clock_gettime64, clockid, tp);
#else
- struct __kernel_timespec ktp;
- int ret;
-
- ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp);
- if (tp)
- __nolibc_timespec_kernel_to_user(&ktp, tp);
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall2(__NR_clock_gettime, clockid, tp);
#endif
}
@@ -87,13 +71,12 @@ int clock_gettime(clockid_t clockid, struct timespec *tp)
static __attribute__((unused))
int sys_clock_settime(clockid_t clockid, struct timespec *tp)
{
-#if defined(__NR_clock_settime)
- return my_syscall2(__NR_clock_settime, clockid, tp);
+#if defined(__NR_clock_settime64)
+ __nolibc_assert_time64_type(tp->tv_sec);
+ return my_syscall2(__NR_clock_settime64, clockid, tp);
#else
- struct __kernel_timespec ktp;
-
- __nolibc_timespec_user_to_kernel(tp, &ktp);
- return my_syscall2(__NR_clock_settime64, clockid, &ktp);
+ __nolibc_assert_native_time64();
+ return my_syscall2(__NR_clock_settime, clockid, tp);
#endif
}
@@ -107,17 +90,12 @@ static __attribute__((unused))
int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
struct timespec *rmtp)
{
-#if defined(__NR_clock_nanosleep)
- return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
+#if defined(__NR_clock_nanosleep_time64)
+ __nolibc_assert_time64_type(rqtp->tv_sec);
+ return my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, rqtp, rmtp);
#else
- struct __kernel_timespec krqtp, krmtp;
- int ret;
-
- __nolibc_timespec_user_to_kernel(rqtp, &krqtp);
- ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp);
- if (rmtp)
- __nolibc_timespec_kernel_to_user(&krmtp, rmtp);
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
#endif
}
@@ -189,16 +167,12 @@ int timer_delete(timer_t timerid)
static __attribute__((unused))
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
{
-#if defined(__NR_timer_gettime)
- return my_syscall2(__NR_timer_gettime, timerid, curr_value);
+#if defined(__NR_timer_gettime64)
+ __nolibc_assert_time64_type(curr_value->it_value.tv_sec);
+ return my_syscall2(__NR_timer_gettime64, timerid, curr_value);
#else
- struct __kernel_itimerspec kcurr_value;
- int ret;
-
- ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value);
- __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall2(__NR_timer_gettime, timerid, curr_value);
#endif
}
@@ -212,20 +186,12 @@ static __attribute__((unused))
int sys_timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
-#if defined(__NR_timer_settime)
- return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
+#if defined(__NR_timer_settime64)
+ __nolibc_assert_time64_type(new_value->it_value.tv_sec);
+ return my_syscall4(__NR_timer_settime64, timerid, flags, new_value, old_value);
#else
- struct __kernel_itimerspec knew_value, kold_value;
- int ret;
-
- __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
- __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
- ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
- if (old_value) {
- __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
- }
- return ret;
+ __nolibc_assert_native_time64();
+ return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
#endif
}
diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
index 470a5f77bc0f..8f3cb18df7f1 100644
--- a/tools/include/nolibc/types.h
+++ b/tools/include/nolibc/types.h
@@ -13,9 +13,24 @@
#include "std.h"
#include <linux/mman.h>
#include <linux/stat.h>
-#include <linux/time.h>
+#include <linux/time_types.h>
#include <linux/wait.h>
+struct timespec {
+ time_t tv_sec;
+ int64_t tv_nsec;
+};
+#define _STRUCT_TIMESPEC
+
+/* Never use with system calls */
+struct timeval {
+ time_t tv_sec;
+ int64_t tv_usec;
+};
+
+#define timeval __nolibc_kernel_timeval
+#include <linux/time.h>
+#undef timeval
/* Only the generic macros and types may be defined here. The arch-specific
* ones such as the O_RDONLY and related macros used by fcntl() and open()
diff --git a/tools/include/uapi/asm-generic/errno.h b/tools/include/uapi/asm-generic/errno.h
index cf9c51ac49f9..92e7ae493ee3 100644
--- a/tools/include/uapi/asm-generic/errno.h
+++ b/tools/include/uapi/asm-generic/errno.h
@@ -55,6 +55,7 @@
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
+#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
@@ -98,6 +99,7 @@
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
+#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index be7d8e060e10..5e38b4887de6 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -119,6 +119,14 @@ enum bpf_cgroup_iter_order {
BPF_CGROUP_ITER_DESCENDANTS_PRE, /* walk descendants in pre-order. */
BPF_CGROUP_ITER_DESCENDANTS_POST, /* walk descendants in post-order. */
BPF_CGROUP_ITER_ANCESTORS_UP, /* walk ancestors upward. */
+ /*
+ * Walks the immediate children of the specified parent
+ * cgroup_subsys_state. Unlike BPF_CGROUP_ITER_DESCENDANTS_PRE,
+ * BPF_CGROUP_ITER_DESCENDANTS_POST, and BPF_CGROUP_ITER_ANCESTORS_UP
+ * the iterator does not include the specified parent as one of the
+ * returned iterator elements.
+ */
+ BPF_CGROUP_ITER_CHILDREN,
};
union bpf_iter_link_info {
@@ -918,6 +926,16 @@ union bpf_iter_link_info {
* Number of bytes read from the stream on success, or -1 if an
* error occurred (in which case, *errno* is set appropriately).
*
+ * BPF_PROG_ASSOC_STRUCT_OPS
+ * Description
+ * Associate a BPF program with a struct_ops map. The struct_ops
+ * map is identified by *map_fd* and the BPF program is
+ * identified by *prog_fd*.
+ *
+ * Return
+ * 0 on success or -1 if an error occurred (in which case,
+ * *errno* is set appropriately).
+ *
* NOTES
* eBPF objects (maps and programs) can be shared between processes.
*
@@ -974,6 +992,7 @@ enum bpf_cmd {
BPF_PROG_BIND_MAP,
BPF_TOKEN_CREATE,
BPF_PROG_STREAM_READ_BY_FD,
+ BPF_PROG_ASSOC_STRUCT_OPS,
__MAX_BPF_CMD,
};
@@ -1134,6 +1153,7 @@ enum bpf_attach_type {
BPF_NETKIT_PEER,
BPF_TRACE_KPROBE_SESSION,
BPF_TRACE_UPROBE_SESSION,
+ BPF_TRACE_FSESSION,
__MAX_BPF_ATTACH_TYPE
};
@@ -1373,6 +1393,8 @@ enum {
BPF_NOEXIST = 1, /* create new element if it didn't exist */
BPF_EXIST = 2, /* update existing element */
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
+ BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
+ BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
};
/* flags for BPF_MAP_CREATE command */
@@ -1894,6 +1916,12 @@ union bpf_attr {
__u32 prog_fd;
} prog_stream_read;
+ struct {
+ __u32 map_fd;
+ __u32 prog_fd;
+ __u32 flags;
+ } prog_assoc_struct_ops;
+
} __attribute__((aligned(8)));
/* The description below is an attempt at providing documentation to eBPF
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 72f03153dd32..76e9d0664d0c 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -1330,14 +1330,16 @@ union perf_mem_data_src {
mem_snoopx : 2, /* Snoop mode, ext */
mem_blk : 3, /* Access blocked */
mem_hops : 3, /* Hop level */
- mem_rsvd : 18;
+ mem_region : 5, /* cache/memory regions */
+ mem_rsvd : 13;
};
};
#elif defined(__BIG_ENDIAN_BITFIELD)
union perf_mem_data_src {
__u64 val;
struct {
- __u64 mem_rsvd : 18,
+ __u64 mem_rsvd : 13,
+ mem_region : 5, /* cache/memory regions */
mem_hops : 3, /* Hop level */
mem_blk : 3, /* Access blocked */
mem_snoopx : 2, /* Snoop mode, ext */
@@ -1394,7 +1396,7 @@ union perf_mem_data_src {
#define PERF_MEM_LVLNUM_L4 0x0004 /* L4 */
#define PERF_MEM_LVLNUM_L2_MHB 0x0005 /* L2 Miss Handling Buffer */
#define PERF_MEM_LVLNUM_MSC 0x0006 /* Memory-side Cache */
-/* 0x007 available */
+#define PERF_MEM_LVLNUM_L0 0x0007 /* L0 */
#define PERF_MEM_LVLNUM_UNC 0x0008 /* Uncached */
#define PERF_MEM_LVLNUM_CXL 0x0009 /* CXL */
#define PERF_MEM_LVLNUM_IO 0x000a /* I/O */
@@ -1447,6 +1449,25 @@ union perf_mem_data_src {
/* 5-7 available */
#define PERF_MEM_HOPS_SHIFT 43
+/* Cache/Memory region */
+#define PERF_MEM_REGION_NA 0x0 /* Invalid */
+#define PERF_MEM_REGION_RSVD 0x01 /* Reserved */
+#define PERF_MEM_REGION_L_SHARE 0x02 /* Local CA shared cache */
+#define PERF_MEM_REGION_L_NON_SHARE 0x03 /* Local CA non-shared cache */
+#define PERF_MEM_REGION_O_IO 0x04 /* Other CA IO agent */
+#define PERF_MEM_REGION_O_SHARE 0x05 /* Other CA shared cache */
+#define PERF_MEM_REGION_O_NON_SHARE 0x06 /* Other CA non-shared cache */
+#define PERF_MEM_REGION_MMIO 0x07 /* MMIO */
+#define PERF_MEM_REGION_MEM0 0x08 /* Memory region 0 */
+#define PERF_MEM_REGION_MEM1 0x09 /* Memory region 1 */
+#define PERF_MEM_REGION_MEM2 0x0a /* Memory region 2 */
+#define PERF_MEM_REGION_MEM3 0x0b /* Memory region 3 */
+#define PERF_MEM_REGION_MEM4 0x0c /* Memory region 4 */
+#define PERF_MEM_REGION_MEM5 0x0d /* Memory region 5 */
+#define PERF_MEM_REGION_MEM6 0x0e /* Memory region 6 */
+#define PERF_MEM_REGION_MEM7 0x0f /* Memory region 7 */
+#define PERF_MEM_REGION_SHIFT 46
+
#define PERF_MEM_S(a, s) \
(((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
diff --git a/tools/include/vdso/unaligned.h b/tools/include/vdso/unaligned.h
index ff0c06b6513e..9076483c9fbb 100644
--- a/tools/include/vdso/unaligned.h
+++ b/tools/include/vdso/unaligned.h
@@ -2,14 +2,43 @@
#ifndef __VDSO_UNALIGNED_H
#define __VDSO_UNALIGNED_H
-#define __get_unaligned_t(type, ptr) ({ \
- const struct { type x; } __packed * __get_pptr = (typeof(__get_pptr))(ptr); \
- __get_pptr->x; \
+#include <linux/compiler_types.h>
+
+/**
+ * __get_unaligned_t - read an unaligned value from memory.
+ * @type: the type to load from the pointer.
+ * @ptr: the pointer to load from.
+ *
+ * Use memcpy to affect an unaligned type sized load avoiding undefined behavior
+ * from approaches like type punning that require -fno-strict-aliasing in order
+ * to be correct. As type may be const, use __unqual_scalar_typeof to map to a
+ * non-const type - you can't memcpy into a const type. The
+ * __get_unaligned_ctrl_type gives __unqual_scalar_typeof its required
+ * expression rather than type, a pointer is used to avoid warnings about mixing
+ * the use of 0 and NULL. The void* cast silences ubsan warnings.
+ */
+#define __get_unaligned_t(type, ptr) ({ \
+ type *__get_unaligned_ctrl_type __always_unused = NULL; \
+ __unqual_scalar_typeof(*__get_unaligned_ctrl_type) __get_unaligned_val; \
+ __builtin_memcpy(&__get_unaligned_val, (void *)(ptr), \
+ sizeof(__get_unaligned_val)); \
+ __get_unaligned_val; \
})
-#define __put_unaligned_t(type, val, ptr) do { \
- struct { type x; } __packed * __put_pptr = (typeof(__put_pptr))(ptr); \
- __put_pptr->x = (val); \
+/**
+ * __put_unaligned_t - write an unaligned value to memory.
+ * @type: the type of the value to store.
+ * @val: the value to store.
+ * @ptr: the pointer to store to.
+ *
+ * Use memcpy to affect an unaligned type sized store avoiding undefined
+ * behavior from approaches like type punning that require -fno-strict-aliasing
+ * in order to be correct. The void* cast silences ubsan warnings.
+ */
+#define __put_unaligned_t(type, val, ptr) do { \
+ type __put_unaligned_val = (val); \
+ __builtin_memcpy((void *)(ptr), &__put_unaligned_val, \
+ sizeof(__put_unaligned_val)); \
} while (0)
#endif /* __VDSO_UNALIGNED_H */