Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'timers-vdso-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull VDSO updates from Thomas Gleixner:

- Provide the missing 64-bit variant of clock_getres()

This allows the extension of CONFIG_COMPAT_32BIT_TIME to the vDSO and
finally the removal of 32-bit time types from the kernel and UAPI.

- Remove the useless and broken getcpu_cache from the VDSO

The intention was to provide a trivial way to retrieve the CPU number
from the VDSO, but as the VDSO data is per process there is no way to
make it work.

- Switch get/put_unaligned() from packed struct to memcpy()

The packed struct violates strict aliasing rules which requires to
pass -fno-strict-aliasing to the compiler. As this are scalar values
__builtin_memcpy() turns them into simple loads and stores

- Use __typeof_unqual__() for __unqual_scalar_typeof()

The get/put_unaligned() changes triggered a new sparse warning when
__beNN types are used with get/put_unaligned() as sparse builds add a
special 'bitwise' attribute to them which prevents sparse to evaluate
the Generic in __unqual_scalar_typeof().

Newer sparse versions support __typeof_unqual__() which avoids the
problem, but requires a recent sparse install. So this adds a sanity
check to sparse builds, which validates that sparse is available and
capable of handling it.

- Force inline __cvdso_clock_getres_common()

Compilers sometimes un-inline agressively, which results in function
call overhead and problems with automatic stack variable
initialization.

Interestingly enough the force inlining results in smaller code than
the un-inlined variant produced by GCC when optimizing for size.

* tag 'timers-vdso-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
vdso/gettimeofday: Force inlining of __cvdso_clock_getres_common()
x86/percpu: Make CONFIG_USE_X86_SEG_SUPPORT work with sparse
compiler: Use __typeof_unqual__() for __unqual_scalar_typeof()
powerpc/vdso: Provide clock_getres_time64()
tools headers: Remove unneeded ignoring of warnings in unaligned.h
tools headers: Update the linux/unaligned.h copy with the kernel sources
vdso: Switch get/put_unaligned() from packed struct to memcpy()
parisc: Inline a type punning version of get_unaligned_le32()
vdso: Remove struct getcpu_cache
MIPS: vdso: Provide getres_time64() for 32-bit ABIs
arm64: vdso32: Provide clock_getres_time64()
ARM: VDSO: Provide clock_getres_time64()
ARM: VDSO: Patch out __vdso_clock_getres() if unavailable
x86/vdso: Provide clock_getres_time64() for x86-32
selftests: vDSO: vdso_test_abi: Add test for clock_getres_time64()
selftests: vDSO: vdso_test_abi: Use UAPI system call numbers
selftests: vDSO: vdso_config: Add configurations for clock_getres_time64()
vdso: Add prototype for __vdso_clock_getres_time64()

+268 -76
+8
Makefile
··· 1195 1195 # the checker needs the correct machine size 1196 1196 CHECKFLAGS += $(if $(CONFIG_64BIT),-m64,-m32) 1197 1197 1198 + # Validate the checker is available and functional 1199 + ifneq ($(KBUILD_CHECKSRC), 0) 1200 + ifneq ($(shell $(srctree)/scripts/checker-valid.sh $(CHECK) $(CHECKFLAGS)), 1) 1201 + $(warning C=$(KBUILD_CHECKSRC) specified, but $(CHECK) is not available or not up to date) 1202 + KBUILD_CHECKSRC = 0 1203 + endif 1204 + endif 1205 + 1198 1206 # Default kernel image to build when no specific target is given. 1199 1207 # KBUILD_IMAGE may be overruled on the command line or 1200 1208 # set in the environment
+2
arch/arm/kernel/vdso.c
··· 161 161 vdso_nullpatch_one(&einfo, "__vdso_gettimeofday"); 162 162 vdso_nullpatch_one(&einfo, "__vdso_clock_gettime"); 163 163 vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64"); 164 + vdso_nullpatch_one(&einfo, "__vdso_clock_getres"); 165 + vdso_nullpatch_one(&einfo, "__vdso_clock_getres_time64"); 164 166 } 165 167 } 166 168
+1
arch/arm/vdso/vdso.lds.S
··· 74 74 __vdso_gettimeofday; 75 75 __vdso_clock_getres; 76 76 __vdso_clock_gettime64; 77 + __vdso_clock_getres_time64; 77 78 local: *; 78 79 }; 79 80 }
+5
arch/arm/vdso/vgettimeofday.c
··· 34 34 return __cvdso_clock_getres_time32(clock_id, res); 35 35 } 36 36 37 + int __vdso_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec *res) 38 + { 39 + return __cvdso_clock_getres(clock_id, res); 40 + } 41 + 37 42 /* Avoid unresolved references emitted by GCC */ 38 43 39 44 void __aeabi_unwind_cpp_pr0(void)
+1
arch/arm64/kernel/vdso32/vdso.lds.S
··· 86 86 __vdso_gettimeofday; 87 87 __vdso_clock_getres; 88 88 __vdso_clock_gettime64; 89 + __vdso_clock_getres_time64; 89 90 local: *; 90 91 }; 91 92 }
+5
arch/arm64/kernel/vdso32/vgettimeofday.c
··· 32 32 return __cvdso_clock_getres_time32(clock_id, res); 33 33 } 34 34 35 + int __vdso_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec *res) 36 + { 37 + return __cvdso_clock_getres(clock_id, res); 38 + } 39 + 35 40 /* Avoid unresolved references emitted by GCC */ 36 41 37 42 void __aeabi_unwind_cpp_pr0(void)
+2 -3
arch/loongarch/vdso/vgetcpu.c
··· 4 4 */ 5 5 6 6 #include <asm/vdso.h> 7 - #include <linux/getcpu.h> 8 7 9 8 static __always_inline int read_cpu_id(void) 10 9 { ··· 27 28 } 28 29 29 30 extern 30 - int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused); 31 - int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused) 31 + int __vdso_getcpu(unsigned int *cpu, unsigned int *node, void *unused); 32 + int __vdso_getcpu(unsigned int *cpu, unsigned int *node, void *unused) 32 33 { 33 34 int cpu_id; 34 35
+1
arch/mips/vdso/vdso.lds.S
··· 103 103 __vdso_clock_getres; 104 104 #if _MIPS_SIM != _MIPS_SIM_ABI64 105 105 __vdso_clock_gettime64; 106 + __vdso_clock_getres_time64; 106 107 #endif 107 108 #endif 108 109 local: *;
+5
arch/mips/vdso/vgettimeofday.c
··· 46 46 return __cvdso_clock_gettime(clock, ts); 47 47 } 48 48 49 + int __vdso_clock_getres_time64(clockid_t clock, struct __kernel_timespec *ts) 50 + { 51 + return __cvdso_clock_getres(clock, ts); 52 + } 53 + 49 54 #else 50 55 51 56 int __vdso_clock_gettime(clockid_t clock,
+14 -1
arch/parisc/boot/compressed/misc.c
··· 278 278 free(phdrs); 279 279 } 280 280 281 + /* 282 + * The regular get_unaligned_le32 uses __builtin_memcpy which can trigger 283 + * warnings when reading a byte/char output_len as an integer, as the size of a 284 + * char is less than that of an integer. Use type punning and the packed 285 + * attribute, which requires -fno-strict-aliasing, to work around the problem. 286 + */ 287 + static u32 punned_get_unaligned_le32(const void *p) 288 + { 289 + const struct { __le32 x; } __packed * __get_pptr = p; 290 + 291 + return le32_to_cpu(__get_pptr->x); 292 + } 293 + 281 294 asmlinkage unsigned long __visible decompress_kernel(unsigned int started_wide, 282 295 unsigned int command_line, 283 296 const unsigned int rd_start, ··· 322 309 * leave 2 MB for the stack. 323 310 */ 324 311 vmlinux_addr = (unsigned long) &_ebss + 2*1024*1024; 325 - vmlinux_len = get_unaligned_le32(&output_len); 312 + vmlinux_len = punned_get_unaligned_le32(&output_len); 326 313 output = (char *) vmlinux_addr; 327 314 328 315 /*
+2
arch/powerpc/include/asm/vdso/gettimeofday.h
··· 135 135 const struct vdso_time_data *vd); 136 136 int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res, 137 137 const struct vdso_time_data *vd); 138 + int __c_kernel_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec *res, 139 + const struct vdso_time_data *vd); 138 140 #endif 139 141 int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz, 140 142 const struct vdso_time_data *vd);
+12
arch/powerpc/kernel/vdso/gettimeofday.S
··· 103 103 cvdso_call __c_kernel_clock_getres 104 104 V_FUNCTION_END(__kernel_clock_getres) 105 105 106 + /* 107 + * Exact prototype of clock_getres_time64() 108 + * 109 + * int __kernel_clock_getres(clockid_t clock_id, struct __timespec64 *res); 110 + * 111 + */ 112 + #ifndef __powerpc64__ 113 + V_FUNCTION_BEGIN(__kernel_clock_getres_time64) 114 + cvdso_call __c_kernel_clock_getres_time64 115 + V_FUNCTION_END(__kernel_clock_getres_time64) 116 + #endif 117 + 106 118 107 119 /* 108 120 * Exact prototype of time()
+1
arch/powerpc/kernel/vdso/vdso32.lds.S
··· 124 124 __kernel_clock_gettime; 125 125 __kernel_clock_gettime64; 126 126 __kernel_clock_getres; 127 + __kernel_clock_getres_time64; 127 128 __kernel_time; 128 129 __kernel_get_tbfreq; 129 130 __kernel_sync_dicache;
+6
arch/powerpc/kernel/vdso/vgettimeofday.c
··· 35 35 { 36 36 return __cvdso_clock_getres_time32_data(vd, clock_id, res); 37 37 } 38 + 39 + int __c_kernel_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec *res, 40 + const struct vdso_time_data *vd) 41 + { 42 + return __cvdso_clock_getres_data(vd, clock_id, res); 43 + } 38 44 #endif 39 45 40 46 int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
+1 -2
arch/s390/kernel/vdso/getcpu.c
··· 2 2 /* Copyright IBM Corp. 2020 */ 3 3 4 4 #include <linux/compiler.h> 5 - #include <linux/getcpu.h> 6 5 #include <asm/timex.h> 7 6 #include "vdso.h" 8 7 9 - int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) 8 + int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, void *unused) 10 9 { 11 10 union tod_clock clk; 12 11
+1 -3
arch/s390/kernel/vdso/vdso.h
··· 4 4 5 5 #include <vdso/datapage.h> 6 6 7 - struct getcpu_cache; 8 - 9 - int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused); 7 + int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, void *unused); 10 8 int __s390_vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); 11 9 int __s390_vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts); 12 10 int __s390_vdso_clock_getres(clockid_t clock, struct __kernel_timespec *ts);
+8
arch/x86/entry/vdso/vclock_gettime.c
··· 74 74 75 75 int clock_getres(clockid_t, struct old_timespec32 *) 76 76 __attribute__((weak, alias("__vdso_clock_getres"))); 77 + 78 + int __vdso_clock_getres_time64(clockid_t clock, struct __kernel_timespec *ts) 79 + { 80 + return __cvdso_clock_getres(clock, ts); 81 + } 82 + 83 + int clock_getres_time64(clockid_t, struct __kernel_timespec *) 84 + __attribute__((weak, alias("__vdso_clock_getres_time64"))); 77 85 #endif
+1
arch/x86/entry/vdso/vdso32/vdso32.lds.S
··· 28 28 __vdso_time; 29 29 __vdso_clock_getres; 30 30 __vdso_clock_gettime64; 31 + __vdso_clock_getres_time64; 31 32 __vdso_getcpu; 32 33 }; 33 34
+2 -3
arch/x86/entry/vdso/vgetcpu.c
··· 6 6 */ 7 7 8 8 #include <linux/kernel.h> 9 - #include <linux/getcpu.h> 10 9 #include <asm/segment.h> 11 10 #include <vdso/processor.h> 12 11 13 12 notrace long 14 - __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) 13 + __vdso_getcpu(unsigned *cpu, unsigned *node, void *unused) 15 14 { 16 15 vdso_read_cpunode(cpu, node); 17 16 18 17 return 0; 19 18 } 20 19 21 - long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) 20 + long getcpu(unsigned *cpu, unsigned *node, void *tcache) 22 21 __attribute__((weak, alias("__vdso_getcpu")));
+4 -4
arch/x86/include/asm/percpu.h
··· 137 137 138 138 #define __raw_cpu_read(size, qual, pcp) \ 139 139 ({ \ 140 - *(qual __my_cpu_type(pcp) *)__my_cpu_ptr(&(pcp)); \ 140 + *(qual __my_cpu_type(pcp) * __force)__my_cpu_ptr(&(pcp)); \ 141 141 }) 142 142 143 - #define __raw_cpu_write(size, qual, pcp, val) \ 144 - do { \ 145 - *(qual __my_cpu_type(pcp) *)__my_cpu_ptr(&(pcp)) = (val); \ 143 + #define __raw_cpu_write(size, qual, pcp, val) \ 144 + do { \ 145 + *(qual __my_cpu_type(pcp) * __force)__my_cpu_ptr(&(pcp)) = (val); \ 146 146 } while (0) 147 147 148 148 #define __raw_cpu_read_const(pcp) __raw_cpu_read(, , pcp)
+1 -3
arch/x86/include/asm/vdso/processor.h
··· 18 18 native_pause(); 19 19 } 20 20 21 - struct getcpu_cache; 22 - 23 - notrace long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused); 21 + notrace long __vdso_getcpu(unsigned *cpu, unsigned *node, void *unused); 24 22 25 23 #endif /* __ASSEMBLER__ */ 26 24
-10
include/linux/compiler.h
··· 233 233 "must be non-C-string (not NUL-terminated)") 234 234 235 235 /* 236 - * Use __typeof_unqual__() when available. 237 - * 238 - * XXX: Remove test for __CHECKER__ once 239 - * sparse learns about __typeof_unqual__(). 240 - */ 241 - #if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__) 242 - # define USE_TYPEOF_UNQUAL 1 243 - #endif 244 - 245 - /* 246 236 * Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof 247 237 * operator when available, to return an unqualified type of the exp. 248 238 */
+13
include/linux/compiler_types.h
··· 595 595 #define asm_inline asm 596 596 #endif 597 597 598 + #ifndef __ASSEMBLY__ 599 + /* 600 + * Use __typeof_unqual__() when available. 601 + */ 602 + #if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__) 603 + # define USE_TYPEOF_UNQUAL 1 604 + #endif 605 + 598 606 /* Are two types/vars the same type (ignoring qualifiers)? */ 599 607 #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) 600 608 ··· 610 602 * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving 611 603 * non-scalar types unchanged. 612 604 */ 605 + #ifndef USE_TYPEOF_UNQUAL 613 606 /* 614 607 * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char' 615 608 * is not type-compatible with 'signed char', and we define a separate case. ··· 628 619 __scalar_type_to_expr_cases(long), \ 629 620 __scalar_type_to_expr_cases(long long), \ 630 621 default: (x))) 622 + #else 623 + #define __unqual_scalar_typeof(x) __typeof_unqual__(x) 624 + #endif 625 + #endif /* !__ASSEMBLY__ */ 631 626 632 627 /* 633 628 * __signed_scalar_typeof(x) - Declare a signed scalar type, leaving
-19
include/linux/getcpu.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _LINUX_GETCPU_H 3 - #define _LINUX_GETCPU_H 1 4 - 5 - /* Cache for getcpu() to speed it up. Results might be a short time 6 - out of date, but will be faster. 7 - 8 - User programs should not refer to the contents of this structure. 9 - I repeat they should not refer to it. If they do they will break 10 - in future kernels. 11 - 12 - It is only a private cache for vgetcpu(). It will change in future kernels. 13 - The user program must store this information per thread (__thread) 14 - If you want 100% accurate information pass NULL instead. */ 15 - struct getcpu_cache { 16 - unsigned long blob[128 / sizeof(long)]; 17 - }; 18 - 19 - #endif
+1 -2
include/linux/syscalls.h
··· 59 59 struct old_timeval32; 60 60 struct robust_list_head; 61 61 struct futex_waitv; 62 - struct getcpu_cache; 63 62 struct old_linux_dirent; 64 63 struct perf_event_attr; 65 64 struct file_handle; ··· 717 718 asmlinkage long sys_umask(int mask); 718 719 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, 719 720 unsigned long arg4, unsigned long arg5); 720 - asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); 721 + asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, void __user *cache); 721 722 asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, 722 723 struct timezone __user *tz); 723 724 asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv,
+1
include/vdso/gettime.h
··· 20 20 __kernel_old_time_t __vdso_time(__kernel_old_time_t *t); 21 21 int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); 22 22 int __vdso_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts); 23 + int __vdso_clock_getres_time64(clockid_t clock, struct __kernel_timespec *ts); 23 24 24 25 #endif
+35 -6
include/vdso/unaligned.h
··· 2 2 #ifndef __VDSO_UNALIGNED_H 3 3 #define __VDSO_UNALIGNED_H 4 4 5 - #define __get_unaligned_t(type, ptr) ({ \ 6 - const struct { type x; } __packed * __get_pptr = (typeof(__get_pptr))(ptr); \ 7 - __get_pptr->x; \ 5 + #include <linux/compiler_types.h> 6 + 7 + /** 8 + * __get_unaligned_t - read an unaligned value from memory. 9 + * @type: the type to load from the pointer. 10 + * @ptr: the pointer to load from. 11 + * 12 + * Use memcpy to affect an unaligned type sized load avoiding undefined behavior 13 + * from approaches like type punning that require -fno-strict-aliasing in order 14 + * to be correct. As type may be const, use __unqual_scalar_typeof to map to a 15 + * non-const type - you can't memcpy into a const type. The 16 + * __get_unaligned_ctrl_type gives __unqual_scalar_typeof its required 17 + * expression rather than type, a pointer is used to avoid warnings about mixing 18 + * the use of 0 and NULL. The void* cast silences ubsan warnings. 19 + */ 20 + #define __get_unaligned_t(type, ptr) ({ \ 21 + type *__get_unaligned_ctrl_type __always_unused = NULL; \ 22 + __unqual_scalar_typeof(*__get_unaligned_ctrl_type) __get_unaligned_val; \ 23 + __builtin_memcpy(&__get_unaligned_val, (void *)(ptr), \ 24 + sizeof(__get_unaligned_val)); \ 25 + __get_unaligned_val; \ 8 26 }) 9 27 10 - #define __put_unaligned_t(type, val, ptr) do { \ 11 - struct { type x; } __packed * __put_pptr = (typeof(__put_pptr))(ptr); \ 12 - __put_pptr->x = (val); \ 28 + /** 29 + * __put_unaligned_t - write an unaligned value to memory. 30 + * @type: the type of the value to store. 31 + * @val: the value to store. 32 + * @ptr: the pointer to store to. 33 + * 34 + * Use memcpy to affect an unaligned type sized store avoiding undefined 35 + * behavior from approaches like type punning that require -fno-strict-aliasing 36 + * in order to be correct. The void* cast silences ubsan warnings. 37 + */ 38 + #define __put_unaligned_t(type, val, ptr) do { \ 39 + type __put_unaligned_val = (val); \ 40 + __builtin_memcpy((void *)(ptr), &__put_unaligned_val, \ 41 + sizeof(__put_unaligned_val)); \ 13 42 } while (0) 14 43 15 44 #endif /* __VDSO_UNALIGNED_H */
+1 -3
kernel/sys.c
··· 31 31 #include <linux/tty.h> 32 32 #include <linux/signal.h> 33 33 #include <linux/cn_proc.h> 34 - #include <linux/getcpu.h> 35 34 #include <linux/task_io_accounting_ops.h> 36 35 #include <linux/seccomp.h> 37 36 #include <linux/cpu.h> ··· 2881 2882 return error; 2882 2883 } 2883 2884 2884 - SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, 2885 - struct getcpu_cache __user *, unused) 2885 + SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, void __user *, unused) 2886 2886 { 2887 2887 int err = 0; 2888 2888 int cpu = raw_smp_processor_id();
+1 -1
lib/vdso/gettimeofday.c
··· 421 421 #endif /* VDSO_HAS_TIME */ 422 422 423 423 #ifdef VDSO_HAS_CLOCK_GETRES 424 - static __maybe_unused 424 + static __always_inline 425 425 bool __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t clock, 426 426 struct __kernel_timespec *res) 427 427 {
+19
scripts/checker-valid.sh
··· 1 + #!/bin/sh -eu 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + [ ! -x "$(command -v "$1")" ] && exit 1 5 + 6 + tmp_file=$(mktemp) 7 + trap "rm -f $tmp_file" EXIT 8 + 9 + cat << EOF >$tmp_file 10 + static inline int u(const int *q) 11 + { 12 + __typeof_unqual__(*q) v = *q; 13 + return v; 14 + } 15 + EOF 16 + 17 + # sparse happily exits with 0 on error so validate 18 + # there is none on stderr. Use awk as grep is a pain with sh -e 19 + $@ $tmp_file 2>&1 | awk -v c=1 '/error/{c=0}END{print c}'
+22
tools/include/linux/compiler_types.h
··· 24 24 #define asm_goto_output(x...) asm goto(x) 25 25 #endif 26 26 27 + /* 28 + * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving 29 + * non-scalar types unchanged. 30 + */ 31 + /* 32 + * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char' 33 + * is not type-compatible with 'signed char', and we define a separate case. 34 + */ 35 + #define __scalar_type_to_expr_cases(type) \ 36 + unsigned type: (unsigned type)0, \ 37 + signed type: (signed type)0 38 + 39 + #define __unqual_scalar_typeof(x) typeof( \ 40 + _Generic((x), \ 41 + char: (char)0, \ 42 + __scalar_type_to_expr_cases(char), \ 43 + __scalar_type_to_expr_cases(short), \ 44 + __scalar_type_to_expr_cases(int), \ 45 + __scalar_type_to_expr_cases(long), \ 46 + __scalar_type_to_expr_cases(long long), \ 47 + default: (x))) 48 + 27 49 #endif /* __LINUX_COMPILER_TYPES_H */
-4
tools/include/linux/unaligned.h
··· 6 6 * This is the most generic implementation of unaligned accesses 7 7 * and should work almost anywhere. 8 8 */ 9 - #pragma GCC diagnostic push 10 - #pragma GCC diagnostic ignored "-Wpacked" 11 - #pragma GCC diagnostic ignored "-Wattributes" 12 9 #include <vdso/unaligned.h> 13 10 14 11 #define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) ··· 140 143 { 141 144 return __get_unaligned_be48(p); 142 145 } 143 - #pragma GCC diagnostic pop 144 146 145 147 #endif /* __LINUX_UNALIGNED_H */
+35 -6
tools/include/vdso/unaligned.h
··· 2 2 #ifndef __VDSO_UNALIGNED_H 3 3 #define __VDSO_UNALIGNED_H 4 4 5 - #define __get_unaligned_t(type, ptr) ({ \ 6 - const struct { type x; } __packed * __get_pptr = (typeof(__get_pptr))(ptr); \ 7 - __get_pptr->x; \ 5 + #include <linux/compiler_types.h> 6 + 7 + /** 8 + * __get_unaligned_t - read an unaligned value from memory. 9 + * @type: the type to load from the pointer. 10 + * @ptr: the pointer to load from. 11 + * 12 + * Use memcpy to affect an unaligned type sized load avoiding undefined behavior 13 + * from approaches like type punning that require -fno-strict-aliasing in order 14 + * to be correct. As type may be const, use __unqual_scalar_typeof to map to a 15 + * non-const type - you can't memcpy into a const type. The 16 + * __get_unaligned_ctrl_type gives __unqual_scalar_typeof its required 17 + * expression rather than type, a pointer is used to avoid warnings about mixing 18 + * the use of 0 and NULL. The void* cast silences ubsan warnings. 19 + */ 20 + #define __get_unaligned_t(type, ptr) ({ \ 21 + type *__get_unaligned_ctrl_type __always_unused = NULL; \ 22 + __unqual_scalar_typeof(*__get_unaligned_ctrl_type) __get_unaligned_val; \ 23 + __builtin_memcpy(&__get_unaligned_val, (void *)(ptr), \ 24 + sizeof(__get_unaligned_val)); \ 25 + __get_unaligned_val; \ 8 26 }) 9 27 10 - #define __put_unaligned_t(type, val, ptr) do { \ 11 - struct { type x; } __packed * __put_pptr = (typeof(__put_pptr))(ptr); \ 12 - __put_pptr->x = (val); \ 28 + /** 29 + * __put_unaligned_t - write an unaligned value to memory. 30 + * @type: the type of the value to store. 31 + * @val: the value to store. 32 + * @ptr: the pointer to store to. 33 + * 34 + * Use memcpy to affect an unaligned type sized store avoiding undefined 35 + * behavior from approaches like type punning that require -fno-strict-aliasing 36 + * in order to be correct. The void* cast silences ubsan warnings. 37 + */ 38 + #define __put_unaligned_t(type, val, ptr) do { \ 39 + type __put_unaligned_val = (val); \ 40 + __builtin_memcpy((void *)(ptr), &__put_unaligned_val, \ 41 + sizeof(__put_unaligned_val)); \ 13 42 } while (0) 14 43 15 44 #endif /* __VDSO_UNALIGNED_H */
+3 -1
tools/testing/selftests/vDSO/vdso_config.h
··· 66 66 }; 67 67 68 68 __attribute__((unused)) 69 - static const char *names[2][7] = { 69 + static const char *names[2][8] = { 70 70 { 71 71 "__kernel_gettimeofday", 72 72 "__kernel_clock_gettime", ··· 75 75 "__kernel_getcpu", 76 76 "__kernel_clock_gettime64", 77 77 "__kernel_getrandom", 78 + "__kernel_clock_getres_time64", 78 79 }, 79 80 { 80 81 "__vdso_gettimeofday", ··· 85 84 "__vdso_getcpu", 86 85 "__vdso_clock_gettime64", 87 86 "__vdso_getrandom", 87 + "__vdso_clock_getres_time64", 88 88 }, 89 89 }; 90 90
+53 -2
tools/testing/selftests/vDSO/vdso_test_abi.c
··· 36 36 typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts); 37 37 typedef long (*vdso_clock_gettime64_t)(clockid_t clk_id, struct vdso_timespec64 *ts); 38 38 typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts); 39 + typedef long (*vdso_clock_getres_time64_t)(clockid_t clk_id, struct vdso_timespec64 *ts); 39 40 typedef time_t (*vdso_time_t)(time_t *t); 40 41 41 42 static const char * const vdso_clock_name[] = { ··· 180 179 clock_getres_fail++; 181 180 } 182 181 183 - ret = syscall(SYS_clock_getres, clk_id, &sys_ts); 182 + ret = syscall(__NR_clock_getres, clk_id, &sys_ts); 184 183 185 184 ksft_print_msg("The syscall resolution is %lld %lld\n", 186 185 (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec); ··· 197 196 } 198 197 } 199 198 199 + #ifdef __NR_clock_getres_time64 200 + static void vdso_test_clock_getres_time64(clockid_t clk_id) 201 + { 202 + int clock_getres_fail = 0; 203 + 204 + /* Find clock_getres. */ 205 + vdso_clock_getres_time64_t vdso_clock_getres_time64 = 206 + (vdso_clock_getres_time64_t)vdso_sym(version, name[7]); 207 + 208 + if (!vdso_clock_getres_time64) { 209 + ksft_print_msg("Couldn't find %s\n", name[7]); 210 + ksft_test_result_skip("%s %s\n", name[7], 211 + vdso_clock_name[clk_id]); 212 + return; 213 + } 214 + 215 + struct vdso_timespec64 ts, sys_ts; 216 + long ret = VDSO_CALL(vdso_clock_getres_time64, 2, clk_id, &ts); 217 + 218 + if (ret == 0) { 219 + ksft_print_msg("The vdso resolution is %lld %lld\n", 220 + (long long)ts.tv_sec, (long long)ts.tv_nsec); 221 + } else { 222 + clock_getres_fail++; 223 + } 224 + 225 + ret = syscall(__NR_clock_getres_time64, clk_id, &sys_ts); 226 + 227 + ksft_print_msg("The syscall resolution is %lld %lld\n", 228 + (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec); 229 + 230 + if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec)) 231 + clock_getres_fail++; 232 + 233 + if (clock_getres_fail > 0) { 234 + ksft_test_result_fail("%s %s\n", name[7], 235 + vdso_clock_name[clk_id]); 236 + } else { 237 + ksft_test_result_pass("%s %s\n", name[7], 238 + vdso_clock_name[clk_id]); 239 + } 240 + } 241 + #else /* !__NR_clock_getres_time64 */ 242 + static void vdso_test_clock_getres_time64(clockid_t clk_id) 243 + { 244 + ksft_test_result_skip("%s %s\n", name[7], vdso_clock_name[clk_id]); 245 + } 246 + #endif /* __NR_clock_getres_time64 */ 247 + 200 248 /* 201 249 * This function calls vdso_test_clock_gettime and vdso_test_clock_getres 202 250 * with different values for clock_id. ··· 258 208 vdso_test_clock_gettime64(clock_id); 259 209 260 210 vdso_test_clock_getres(clock_id); 211 + vdso_test_clock_getres_time64(clock_id); 261 212 } 262 213 263 - #define VDSO_TEST_PLAN 29 214 + #define VDSO_TEST_PLAN 38 264 215 265 216 int main(int argc, char **argv) 266 217 {
+1 -3
tools/testing/selftests/vDSO/vdso_test_getcpu.c
··· 16 16 #include "vdso_config.h" 17 17 #include "vdso_call.h" 18 18 19 - struct getcpu_cache; 20 - typedef long (*getcpu_t)(unsigned int *, unsigned int *, 21 - struct getcpu_cache *); 19 + typedef long (*getcpu_t)(unsigned int *, unsigned int *, void *); 22 20 23 21 int main(int argc, char **argv) 24 22 {