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

Merge tag 'linux_kselftest-next-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kselftest updates from Shuah Khan:

- fixes, reporting improvements, and cleanup changes to several tests

- add support for DT_GNU_HASH to selftests/vDSO

* tag 'linux_kselftest-next-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
selftests/rseq: Fix handling of glibc without rseq support
selftests/resctrl: Discover SNC kernel support and adjust messages
selftests/resctrl: Adjust effective L3 cache size with SNC enabled
selftests/ftrace: Make uprobe test more robust against binary name
selftests/ftrace: Fix to use remount when testing mount GID option
selftests: tmpfs: Add kselftest support to tmpfs
selftests: tmpfs: Add Test-skip if not run as root
selftests: harness: fix printing of mismatch values in __EXPECT()
selftests/ring-buffer: Add test for out-of-bound pgoff mapping
selftests/run_kselftest.sh: Fix help string for --per-test-log
selftests: acct: Add ksft_exit_skip if not running as root
selftests: kselftest: Fix the wrong format specifier
selftests: timers: clocksource-switch: Adapt progress to kselftest framework
selftests/zram: gitignore output file
selftests/filesystems: Add missing gitignore file
selftests: Warn about skipped tests in result summary
selftests: kselftest: Add ksft_test_result_xpass
selftests/vDSO: support DT_GNU_HASH
selftests/ipc: Remove unused variables
selftest: media_tests: fix trivial UAF typo

+371 -86
+1 -1
tools/testing/selftests/acct/acct_syscall.c
··· 24 24 25 25 // Check if test is run a root 26 26 if (geteuid()) { 27 - ksft_test_result_skip("This test needs root to run!\n"); 27 + ksft_exit_skip("This test needs root to run!\n"); 28 28 return 1; 29 29 } 30 30
+1
tools/testing/selftests/filesystems/statmount/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 + statmount_test_ns 2 3 /*_test
+4 -4
tools/testing/selftests/ftrace/test.d/00basic/mount_options.tc
··· 15 15 tac /etc/group | grep -v ":$original_gid:" | head -1 | cut -d: -f3 16 16 } 17 17 18 - mount_tracefs_with_options() { 18 + remount_tracefs_with_options() { 19 19 local mount_point="$1" 20 20 local options="$2" 21 21 22 - mount -t tracefs -o "$options" nodev "$mount_point" 22 + mount -t tracefs -o "remount,$options" nodev "$mount_point" 23 23 24 24 setup 25 25 } ··· 81 81 82 82 # Unmount existing tracefs instance and mount with new GID 83 83 unmount_tracefs "$mount_point" 84 - mount_tracefs_with_options "$mount_point" "$new_options" 84 + remount_tracefs_with_options "$mount_point" "$new_options" 85 85 86 86 check_gid "$mount_point" "$other_group" 87 87 ··· 92 92 93 93 # Unmount and remount with the original GID 94 94 unmount_tracefs "$mount_point" 95 - mount_tracefs_with_options "$mount_point" "$mount_options" 95 + remount_tracefs_with_options "$mount_point" "$mount_options" 96 96 check_gid "$mount_point" "$original_group" 97 97 } 98 98
+3 -1
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
··· 6 6 echo 0 > events/enable 7 7 echo > dynamic_events 8 8 9 + REALBIN=`readlink -f /bin/sh` 10 + 9 11 echo 'cat /proc/$$/maps' | /bin/sh | \ 10 - grep "r-xp .*/bin/.*sh$" | \ 12 + grep "r-xp .*${REALBIN}$" | \ 11 13 awk '{printf "p:myevent %s:0x%s\n", $6,$3 }' >> uprobe_events 12 14 13 15 grep -q myevent uprobe_events
+1 -1
tools/testing/selftests/ipc/msgque.c
··· 194 194 195 195 int main(int argc, char **argv) 196 196 { 197 - int msg, pid, err; 197 + int err; 198 198 struct msgque_data msgque; 199 199 200 200 if (getuid() != 0)
+26 -2
tools/testing/selftests/kselftest.h
··· 18 18 * ksft_print_msg(fmt, ...); 19 19 * ksft_perror(msg); 20 20 * 21 - * and finally report the pass/fail/skip/xfail state of the test with one of: 21 + * and finally report the pass/fail/skip/xfail/xpass state of the test 22 + * with one of: 22 23 * 23 24 * ksft_test_result(condition, fmt, ...); 24 25 * ksft_test_result_report(result, fmt, ...); ··· 27 26 * ksft_test_result_fail(fmt, ...); 28 27 * ksft_test_result_skip(fmt, ...); 29 28 * ksft_test_result_xfail(fmt, ...); 29 + * ksft_test_result_xpass(fmt, ...); 30 30 * ksft_test_result_error(fmt, ...); 31 31 * ksft_test_result_code(exit_code, test_name, fmt, ...); 32 32 * ··· 149 147 150 148 static inline void ksft_print_cnts(void) 151 149 { 150 + if (ksft_cnt.ksft_xskip > 0) 151 + printf( 152 + "# %u skipped test(s) detected. Consider enabling relevant config options to improve coverage.\n", 153 + ksft_cnt.ksft_xskip 154 + ); 152 155 if (ksft_plan != ksft_test_num()) 153 156 printf("# Planned tests != run tests (%u != %u)\n", 154 157 ksft_plan, ksft_test_num()); ··· 229 222 230 223 va_start(args, msg); 231 224 printf("ok %u # XFAIL ", ksft_test_num()); 225 + errno = saved_errno; 226 + vprintf(msg, args); 227 + va_end(args); 228 + } 229 + 230 + static inline __printf(1, 2) void ksft_test_result_xpass(const char *msg, ...) 231 + { 232 + int saved_errno = errno; 233 + va_list args; 234 + 235 + ksft_cnt.ksft_xpass++; 236 + 237 + va_start(args, msg); 238 + printf("ok %u # XPASS ", ksft_test_num()); 232 239 errno = saved_errno; 233 240 vprintf(msg, args); 234 241 va_end(args); ··· 339 318 case KSFT_XFAIL: \ 340 319 ksft_test_result_xfail(fmt, ##__VA_ARGS__); \ 341 320 break; \ 321 + case KSFT_XPASS: \ 322 + ksft_test_result_xpass(fmt, ##__VA_ARGS__); \ 323 + break; \ 342 324 case KSFT_SKIP: \ 343 325 ksft_test_result_skip(fmt, ##__VA_ARGS__); \ 344 326 break; \ ··· 427 403 */ 428 404 if (ksft_plan || ksft_test_num()) { 429 405 ksft_cnt.ksft_xskip++; 430 - printf("ok %d # SKIP ", 1 + ksft_test_num()); 406 + printf("ok %u # SKIP ", 1 + ksft_test_num()); 431 407 } else { 432 408 printf("1..0 # SKIP "); 433 409 }
+3
tools/testing/selftests/kselftest/ksft.py
··· 27 27 28 28 29 29 def print_cnts(): 30 + if ksft_cnt['skip'] > 0: 31 + print(f"# {ksft_cnt['skip']} skipped test(s) detected. Consider enabling relevant config options to improve coverage.") 32 + 30 33 print( 31 34 f"# Totals: pass:{ksft_cnt['pass']} fail:{ksft_cnt['fail']} xfail:0 xpass:0 skip:{ksft_cnt['skip']} error:0" 32 35 )
+4
tools/testing/selftests/kselftest/ktap_helpers.sh
··· 118 118 } 119 119 120 120 ktap_print_totals() { 121 + if [ "$KTAP_CNT_SKIP" -gt 0 ]; then 122 + echo "# $KTAP_CNT_SKIP skipped test(s) detected. " \ 123 + "Consider enabling relevant config options to improve coverage." 124 + fi 121 125 echo "# Totals: pass:$KTAP_CNT_PASS fail:$KTAP_CNT_FAIL xfail:$KTAP_CNT_XFAIL xpass:0 skip:$KTAP_CNT_SKIP error:0" 122 126 }
+12 -12
tools/testing/selftests/kselftest_harness.h
··· 760 760 /* Report with actual signedness to avoid weird output. */ \ 761 761 switch (is_signed_type(__exp) * 2 + is_signed_type(__seen)) { \ 762 762 case 0: { \ 763 - unsigned long long __exp_print = (uintptr_t)__exp; \ 764 - unsigned long long __seen_print = (uintptr_t)__seen; \ 765 - __TH_LOG("Expected %s (%llu) %s %s (%llu)", \ 763 + uintmax_t __exp_print = (uintmax_t)__exp; \ 764 + uintmax_t __seen_print = (uintmax_t)__seen; \ 765 + __TH_LOG("Expected %s (%ju) %s %s (%ju)", \ 766 766 _expected_str, __exp_print, #_t, \ 767 767 _seen_str, __seen_print); \ 768 768 break; \ 769 769 } \ 770 770 case 1: { \ 771 - unsigned long long __exp_print = (uintptr_t)__exp; \ 772 - long long __seen_print = (intptr_t)__seen; \ 773 - __TH_LOG("Expected %s (%llu) %s %s (%lld)", \ 771 + uintmax_t __exp_print = (uintmax_t)__exp; \ 772 + intmax_t __seen_print = (intmax_t)__seen; \ 773 + __TH_LOG("Expected %s (%ju) %s %s (%jd)", \ 774 774 _expected_str, __exp_print, #_t, \ 775 775 _seen_str, __seen_print); \ 776 776 break; \ 777 777 } \ 778 778 case 2: { \ 779 - long long __exp_print = (intptr_t)__exp; \ 780 - unsigned long long __seen_print = (uintptr_t)__seen; \ 781 - __TH_LOG("Expected %s (%lld) %s %s (%llu)", \ 779 + intmax_t __exp_print = (intmax_t)__exp; \ 780 + uintmax_t __seen_print = (uintmax_t)__seen; \ 781 + __TH_LOG("Expected %s (%jd) %s %s (%ju)", \ 782 782 _expected_str, __exp_print, #_t, \ 783 783 _seen_str, __seen_print); \ 784 784 break; \ 785 785 } \ 786 786 case 3: { \ 787 - long long __exp_print = (intptr_t)__exp; \ 788 - long long __seen_print = (intptr_t)__seen; \ 789 - __TH_LOG("Expected %s (%lld) %s %s (%lld)", \ 787 + intmax_t __exp_print = (intmax_t)__exp; \ 788 + intmax_t __seen_print = (intmax_t)__seen; \ 789 + __TH_LOG("Expected %s (%jd) %s %s (%jd)", \ 790 790 _expected_str, __exp_print, #_t, \ 791 791 _seen_str, __seen_print); \ 792 792 break; \
+4 -4
tools/testing/selftests/media_tests/regression_test.txt
··· 1 1 Testing for regressions in Media Controller API register, ioctl, syscall, 2 - and unregister paths. There have a few problems that result in user-after 2 + and unregister paths. There have a few problems that result in use-after 3 3 free on media_device, media_devnode, and cdev pointers when the driver is 4 4 unbound while ioctl is in progress. 5 5 ··· 15 15 cd tools/testing/selftests/media_tests 16 16 make 17 17 18 - Regressions test for cdev user-after free error on /dev/mediaX when driver 18 + Regressions test for cdev use-after-free error on /dev/mediaX when driver 19 19 is unbound: 20 20 21 21 Start media_device_test to regression test media devnode dynamic alloc 22 - and cdev user-after-free fixes. This opens media dev files and sits in 22 + and cdev use-after-free fixes. This opens media dev files and sits in 23 23 a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10 24 24 seconds. The idea is when device file goes away, media devnode and cdev 25 25 should stick around until this test exits. ··· 40 40 Copy bind_unbind_sample.txt and make changes to specify the driver name 41 41 and number to run bind and unbind. Start the bind_unbind.sh 42 42 43 - Run dmesg looking for any user-after free errors or mutex lock errors. 43 + Run dmesg looking for any use-after-free errors or mutex lock errors.
+1
tools/testing/selftests/resctrl/Makefile
··· 8 8 LOCAL_HDRS += $(wildcard *.h) 9 9 10 10 include ../lib.mk 11 + CFLAGS += -I$(top_srcdir)/tools/include 11 12 12 13 $(OUTPUT)/resctrl_tests: $(wildcard *.c)
+2 -2
tools/testing/selftests/resctrl/cmt_test.c
··· 169 169 return ret; 170 170 171 171 ret = check_results(&param, span, n); 172 - if (ret && (get_vendor() == ARCH_INTEL)) 173 - ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n"); 172 + if (ret && (get_vendor() == ARCH_INTEL) && !snc_kernel_support()) 173 + ksft_print_msg("Kernel doesn't support Sub-NUMA Clustering but it is enabled on the system.\n"); 174 174 175 175 return ret; 176 176 }
+2
tools/testing/selftests/resctrl/mba_test.c
··· 201 201 return ret; 202 202 203 203 ret = check_results(); 204 + if (ret && (get_vendor() == ARCH_INTEL) && !snc_kernel_support()) 205 + ksft_print_msg("Kernel doesn't support Sub-NUMA Clustering but it is enabled on the system.\n"); 204 206 205 207 return ret; 206 208 }
+2 -2
tools/testing/selftests/resctrl/mbm_test.c
··· 160 160 return ret; 161 161 162 162 ret = check_results(param.fill_buf ? param.fill_buf->buf_size : 0); 163 - if (ret && (get_vendor() == ARCH_INTEL)) 164 - ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n"); 163 + if (ret && (get_vendor() == ARCH_INTEL) && !snc_kernel_support()) 164 + ksft_print_msg("Kernel doesn't support Sub-NUMA Clustering but it is enabled on the system.\n"); 165 165 166 166 return ret; 167 167 }
+6
tools/testing/selftests/resctrl/resctrl.h
··· 11 11 #include <signal.h> 12 12 #include <dirent.h> 13 13 #include <stdbool.h> 14 + #include <ctype.h> 14 15 #include <sys/stat.h> 15 16 #include <sys/ioctl.h> 16 17 #include <sys/mount.h> ··· 22 21 #include <sys/eventfd.h> 23 22 #include <asm/unistd.h> 24 23 #include <linux/perf_event.h> 24 + #include <linux/compiler.h> 25 25 #include "../kselftest.h" 26 26 27 27 #define MB (1024 * 1024) ··· 158 156 */ 159 157 extern volatile int *value_sink; 160 158 159 + extern int snc_unreliable; 160 + 161 161 extern char llc_occup_path[1024]; 162 162 163 + int snc_nodes_per_l3_cache(void); 163 164 int get_vendor(void); 164 165 bool check_resctrlfs_support(void); 165 166 int filter_dmesg(void); ··· 203 198 int signal_handler_register(const struct resctrl_test *test); 204 199 void signal_handler_unregister(void); 205 200 unsigned int count_bits(unsigned long n); 201 + int snc_kernel_support(void); 206 202 207 203 void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config); 208 204 void perf_event_initialize_read_format(struct perf_event_read *pe_read);
+8 -1
tools/testing/selftests/resctrl/resctrl_tests.c
··· 118 118 119 119 static void run_single_test(const struct resctrl_test *test, const struct user_params *uparams) 120 120 { 121 - int ret; 121 + int ret, snc_mode; 122 122 123 123 if (test->disabled) 124 124 return; ··· 128 128 return; 129 129 } 130 130 131 + snc_mode = snc_nodes_per_l3_cache(); 132 + 131 133 ksft_print_msg("Starting %s test ...\n", test->name); 134 + 135 + if (snc_mode == 1 && snc_unreliable && get_vendor() == ARCH_INTEL) { 136 + ksft_test_result_skip("SNC detection unreliable due to offline CPUs. Test results may not be accurate if SNC enabled.\n"); 137 + return; 138 + } 132 139 133 140 if (test_prepare(test)) { 134 141 ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
+137
tools/testing/selftests/resctrl/resctrlfs.c
··· 13 13 14 14 #include "resctrl.h" 15 15 16 + int snc_unreliable; 17 + 16 18 static int find_resctrl_mount(char *buffer) 17 19 { 18 20 FILE *mounts; ··· 159 157 } 160 158 161 159 /* 160 + * Count number of CPUs in a /sys bitmap 161 + */ 162 + static unsigned int count_sys_bitmap_bits(char *name) 163 + { 164 + FILE *fp = fopen(name, "r"); 165 + int count = 0, c; 166 + 167 + if (!fp) 168 + return 0; 169 + 170 + while ((c = fgetc(fp)) != EOF) { 171 + if (!isxdigit(c)) 172 + continue; 173 + switch (c) { 174 + case 'f': 175 + count++; 176 + fallthrough; 177 + case '7': case 'b': case 'd': case 'e': 178 + count++; 179 + fallthrough; 180 + case '3': case '5': case '6': case '9': case 'a': case 'c': 181 + count++; 182 + fallthrough; 183 + case '1': case '2': case '4': case '8': 184 + count++; 185 + break; 186 + } 187 + } 188 + fclose(fp); 189 + 190 + return count; 191 + } 192 + 193 + static bool cpus_offline_empty(void) 194 + { 195 + char offline_cpus_str[64]; 196 + FILE *fp; 197 + 198 + fp = fopen("/sys/devices/system/cpu/offline", "r"); 199 + if (!fp) { 200 + ksft_perror("Could not open /sys/devices/system/cpu/offline"); 201 + return 0; 202 + } 203 + 204 + if (fscanf(fp, "%63s", offline_cpus_str) < 0) { 205 + if (!errno) { 206 + fclose(fp); 207 + return 1; 208 + } 209 + ksft_perror("Could not read /sys/devices/system/cpu/offline"); 210 + } 211 + 212 + fclose(fp); 213 + 214 + return 0; 215 + } 216 + 217 + /* 218 + * Detect SNC by comparing #CPUs in node0 with #CPUs sharing LLC with CPU0. 219 + * If any CPUs are offline declare the detection as unreliable. 220 + */ 221 + int snc_nodes_per_l3_cache(void) 222 + { 223 + int node_cpus, cache_cpus; 224 + static int snc_mode; 225 + 226 + if (!snc_mode) { 227 + snc_mode = 1; 228 + if (!cpus_offline_empty()) { 229 + ksft_print_msg("Runtime SNC detection unreliable due to offline CPUs.\n"); 230 + ksft_print_msg("Setting SNC mode to disabled.\n"); 231 + snc_unreliable = 1; 232 + return snc_mode; 233 + } 234 + node_cpus = count_sys_bitmap_bits("/sys/devices/system/node/node0/cpumap"); 235 + cache_cpus = count_sys_bitmap_bits("/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_map"); 236 + 237 + if (!node_cpus || !cache_cpus) { 238 + ksft_print_msg("Could not determine Sub-NUMA Cluster mode.\n"); 239 + snc_unreliable = 1; 240 + return snc_mode; 241 + } 242 + snc_mode = cache_cpus / node_cpus; 243 + 244 + if (snc_mode > 1) 245 + ksft_print_msg("SNC-%d mode discovered.\n", snc_mode); 246 + } 247 + 248 + return snc_mode; 249 + } 250 + 251 + /* 162 252 * get_cache_size - Get cache size for a specified CPU 163 253 * @cpu_no: CPU number 164 254 * @cache_type: Cache level L2/L3 ··· 305 211 break; 306 212 } 307 213 214 + /* 215 + * The amount of cache represented by each bit in the masks 216 + * in the schemata file is reduced by a factor equal to SNC 217 + * nodes per L3 cache. 218 + * E.g. on a SNC-2 system with a 100MB L3 cache a test that 219 + * allocates memory from its local SNC node (default behavior 220 + * without using libnuma) will only see 50 MB llc_occupancy 221 + * with a fully populated L3 mask in the schemata file. 222 + */ 223 + if (cache_num == 3) 224 + *cache_size /= snc_nodes_per_l3_cache(); 308 225 return 0; 309 226 } 310 227 ··· 956 851 } 957 852 958 853 return count; 854 + } 855 + 856 + /** 857 + * snc_kernel_support - Check for existence of mon_sub_L3_00 file that indicates 858 + * SNC resctrl support on the kernel side. 859 + * 860 + * Return: 0 if not supported, 1 if SNC is disabled or SNC discovery is 861 + * unreliable or SNC is both enabled and supported. 862 + */ 863 + int snc_kernel_support(void) 864 + { 865 + char node_path[PATH_MAX]; 866 + struct stat statbuf; 867 + int ret; 868 + 869 + ret = snc_nodes_per_l3_cache(); 870 + /* 871 + * If SNC is disabled then its kernel support isn't important. If SNC 872 + * got disabled because the discovery process was unreliable the 873 + * snc_unreliable variable was set. It can be used to verify the SNC 874 + * discovery reliability elsewhere in the selftest. 875 + */ 876 + if (ret == 1) 877 + return ret; 878 + 879 + snprintf(node_path, sizeof(node_path), "%s/%s", RESCTRL_PATH, 880 + "mon_data/mon_L3_00/mon_sub_L3_00"); 881 + 882 + if (!stat(node_path, &statbuf)) 883 + return 1; 884 + 885 + return 0; 959 886 }
+7 -1
tools/testing/selftests/ring-buffer/map_test.c
··· 233 233 ASSERT_NE(data, MAP_FAILED); 234 234 munmap(data, data_len); 235 235 236 - /* Overflow the available subbufs by 1 */ 236 + /* Offset within ring-buffer bounds, mapping size overflow */ 237 237 meta_len += desc->meta->subbuf_size * 2; 238 238 data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, 239 239 desc->cpu_fd, meta_len); 240 + ASSERT_EQ(data, MAP_FAILED); 241 + 242 + /* Offset outside ring-buffer bounds */ 243 + data_len = desc->meta->subbuf_size * desc->meta->nr_subbufs; 244 + data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, 245 + desc->cpu_fd, data_len + (desc->meta->subbuf_size * 2)); 240 246 ASSERT_EQ(data, MAP_FAILED); 241 247 242 248 /* Verify meta-page padding */
+25 -7
tools/testing/selftests/rseq/rseq.c
··· 61 61 unsigned int rseq_flags; 62 62 63 63 static int rseq_ownership; 64 - static int rseq_reg_success; /* At least one rseq registration has succeded. */ 65 64 66 65 /* Allocate a large area for the TLS. */ 67 66 #define RSEQ_THREAD_AREA_ALLOC_SIZE 1024 ··· 151 152 } 152 153 rc = sys_rseq(&__rseq_abi, get_rseq_min_alloc_size(), 0, RSEQ_SIG); 153 154 if (rc) { 154 - if (RSEQ_READ_ONCE(rseq_reg_success)) { 155 + /* 156 + * After at least one thread has registered successfully 157 + * (rseq_size > 0), the registration of other threads should 158 + * never fail. 159 + */ 160 + if (RSEQ_READ_ONCE(rseq_size) > 0) { 155 161 /* Incoherent success/failure within process. */ 156 162 abort(); 157 163 } 158 164 return -1; 159 165 } 160 166 assert(rseq_current_cpu_raw() >= 0); 161 - RSEQ_WRITE_ONCE(rseq_reg_success, 1); 167 + 168 + /* 169 + * The first thread to register sets the rseq_size to mimic the libc 170 + * behavior. 171 + */ 172 + if (RSEQ_READ_ONCE(rseq_size) == 0) { 173 + RSEQ_WRITE_ONCE(rseq_size, get_rseq_kernel_feature_size()); 174 + } 175 + 162 176 return 0; 163 177 } 164 178 ··· 247 235 return; 248 236 } 249 237 rseq_ownership = 1; 250 - if (!rseq_available()) { 251 - rseq_size = 0; 252 - return; 253 - } 238 + 239 + /* Calculate the offset of the rseq area from the thread pointer. */ 254 240 rseq_offset = (void *)&__rseq_abi - rseq_thread_pointer(); 241 + 242 + /* rseq flags are deprecated, always set to 0. */ 255 243 rseq_flags = 0; 244 + 245 + /* 246 + * Set the size to 0 until at least one thread registers to mimic the 247 + * libc behavior. 248 + */ 249 + rseq_size = 0; 256 250 } 257 251 258 252 static __attribute__((destructor))
+8 -1
tools/testing/selftests/rseq/rseq.h
··· 60 60 extern ptrdiff_t rseq_offset; 61 61 62 62 /* 63 - * Size of the registered rseq area. 0 if the registration was 63 + * The rseq ABI is composed of extensible feature fields. The extensions 64 + * are done by appending additional fields at the end of the structure. 65 + * The rseq_size defines the size of the active feature set which can be 66 + * used by the application for the current rseq registration. Features 67 + * starting at offset >= rseq_size are inactive and should not be used. 68 + * 69 + * The rseq_size is the intersection between the available allocation 70 + * size for the rseq area and the feature size supported by the kernel. 64 71 * unsuccessful. 65 72 */ 66 73 extern unsigned int rseq_size;
+1 -1
tools/testing/selftests/run_kselftest.sh
··· 21 21 cat <<EOF 22 22 Usage: $0 [OPTIONS] 23 23 -s | --summary Print summary with detailed log in output.log (conflict with -p) 24 - -p | --per_test_log Print test log in /tmp with each test name (conflict with -s) 24 + -p | --per-test-log Print test log in /tmp with each test name (conflict with -s) 25 25 -t | --test COLLECTION:TEST Run TEST from COLLECTION 26 26 -c | --collection COLLECTION Run all tests from COLLECTION 27 27 -l | --list List the available collection:test entries
+3 -3
tools/testing/selftests/timers/clocksource-switch.c
··· 156 156 /* Check everything is sane before we start switching asynchronously */ 157 157 if (do_sanity_check) { 158 158 for (i = 0; i < count; i++) { 159 - printf("Validating clocksource %s\n", 160 - clocksource_list[i]); 159 + ksft_print_msg("Validating clocksource %s\n", 160 + clocksource_list[i]); 161 161 if (change_clocksource(clocksource_list[i])) { 162 162 status = -1; 163 163 goto out; ··· 169 169 } 170 170 } 171 171 172 - printf("Running Asynchronous Switching Tests...\n"); 172 + ksft_print_msg("Running Asynchronous Switching Tests...\n"); 173 173 pid = fork(); 174 174 if (!pid) 175 175 return run_tests(runtime);
+80 -26
tools/testing/selftests/vDSO/parse_vdso.c
··· 53 53 /* Symbol table */ 54 54 ELF(Sym) *symtab; 55 55 const char *symstrings; 56 + ELF(Word) *gnu_hash; 56 57 ELF_HASH_ENTRY *bucket, *chain; 57 58 ELF_HASH_ENTRY nbucket, nchain; 58 59 ··· 79 78 h ^= g >> 24; 80 79 h &= ~g; 81 80 } 81 + return h; 82 + } 83 + 84 + static uint32_t gnu_hash(const char *name) 85 + { 86 + const unsigned char *s = (void *)name; 87 + uint32_t h = 5381; 88 + 89 + for (; *s; s++) 90 + h += h * 32 + *s; 82 91 return h; 83 92 } 84 93 ··· 134 123 */ 135 124 ELF_HASH_ENTRY *hash = 0; 136 125 vdso_info.symstrings = 0; 126 + vdso_info.gnu_hash = 0; 137 127 vdso_info.symtab = 0; 138 128 vdso_info.versym = 0; 139 129 vdso_info.verdef = 0; ··· 155 143 ((uintptr_t)dyn[i].d_un.d_ptr 156 144 + vdso_info.load_offset); 157 145 break; 146 + case DT_GNU_HASH: 147 + vdso_info.gnu_hash = 148 + (ELF(Word) *)((uintptr_t)dyn[i].d_un.d_ptr + 149 + vdso_info.load_offset); 150 + break; 158 151 case DT_VERSYM: 159 152 vdso_info.versym = (ELF(Versym) *) 160 153 ((uintptr_t)dyn[i].d_un.d_ptr ··· 172 155 break; 173 156 } 174 157 } 175 - if (!vdso_info.symstrings || !vdso_info.symtab || !hash) 158 + if (!vdso_info.symstrings || !vdso_info.symtab || 159 + (!hash && !vdso_info.gnu_hash)) 176 160 return; /* Failed */ 177 161 178 162 if (!vdso_info.verdef) 179 163 vdso_info.versym = 0; 180 164 181 165 /* Parse the hash table header. */ 182 - vdso_info.nbucket = hash[0]; 183 - vdso_info.nchain = hash[1]; 184 - vdso_info.bucket = &hash[2]; 185 - vdso_info.chain = &hash[vdso_info.nbucket + 2]; 166 + if (vdso_info.gnu_hash) { 167 + vdso_info.nbucket = vdso_info.gnu_hash[0]; 168 + /* The bucket array is located after the header (4 uint32) and the bloom 169 + * filter (size_t array of gnu_hash[2] elements). 170 + */ 171 + vdso_info.bucket = vdso_info.gnu_hash + 4 + 172 + sizeof(size_t) / 4 * vdso_info.gnu_hash[2]; 173 + } else { 174 + vdso_info.nbucket = hash[0]; 175 + vdso_info.nchain = hash[1]; 176 + vdso_info.bucket = &hash[2]; 177 + vdso_info.chain = &hash[vdso_info.nbucket + 2]; 178 + } 186 179 187 180 /* That's all we need. */ 188 181 vdso_info.valid = true; ··· 236 209 && !strcmp(name, vdso_info.symstrings + aux->vda_name); 237 210 } 238 211 212 + static bool check_sym(ELF(Sym) *sym, ELF(Word) i, const char *name, 213 + const char *version, unsigned long ver_hash) 214 + { 215 + /* Check for a defined global or weak function w/ right name. */ 216 + if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) 217 + return false; 218 + if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL && 219 + ELF64_ST_BIND(sym->st_info) != STB_WEAK) 220 + return false; 221 + if (strcmp(name, vdso_info.symstrings + sym->st_name)) 222 + return false; 223 + 224 + /* Check symbol version. */ 225 + if (vdso_info.versym && 226 + !vdso_match_version(vdso_info.versym[i], version, ver_hash)) 227 + return false; 228 + 229 + return true; 230 + } 231 + 239 232 void *vdso_sym(const char *version, const char *name) 240 233 { 241 234 unsigned long ver_hash; ··· 263 216 return 0; 264 217 265 218 ver_hash = elf_hash(version); 266 - ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; 219 + ELF(Word) i; 267 220 268 - for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) { 269 - ELF(Sym) *sym = &vdso_info.symtab[chain]; 221 + if (vdso_info.gnu_hash) { 222 + uint32_t h1 = gnu_hash(name), h2, *hashval; 270 223 271 - /* Check for a defined global or weak function w/ right name. */ 272 - if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) 273 - continue; 274 - if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL && 275 - ELF64_ST_BIND(sym->st_info) != STB_WEAK) 276 - continue; 277 - if (sym->st_shndx == SHN_UNDEF) 278 - continue; 279 - if (strcmp(name, vdso_info.symstrings + sym->st_name)) 280 - continue; 281 - 282 - /* Check symbol version. */ 283 - if (vdso_info.versym 284 - && !vdso_match_version(vdso_info.versym[chain], 285 - version, ver_hash)) 286 - continue; 287 - 288 - return (void *)(vdso_info.load_offset + sym->st_value); 224 + i = vdso_info.bucket[h1 % vdso_info.nbucket]; 225 + if (i == 0) 226 + return 0; 227 + h1 |= 1; 228 + hashval = vdso_info.bucket + vdso_info.nbucket + 229 + (i - vdso_info.gnu_hash[1]); 230 + for (;; i++) { 231 + ELF(Sym) *sym = &vdso_info.symtab[i]; 232 + h2 = *hashval++; 233 + if (h1 == (h2 | 1) && 234 + check_sym(sym, i, name, version, ver_hash)) 235 + return (void *)(vdso_info.load_offset + 236 + sym->st_value); 237 + if (h2 & 1) 238 + break; 239 + } 240 + } else { 241 + i = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; 242 + for (; i; i = vdso_info.chain[i]) { 243 + ELF(Sym) *sym = &vdso_info.symtab[i]; 244 + if (sym->st_shndx != SHN_UNDEF && 245 + check_sym(sym, i, name, version, ver_hash)) 246 + return (void *)(vdso_info.load_offset + 247 + sym->st_value); 248 + } 289 249 } 290 250 291 251 return 0;
+2
tools/testing/selftests/zram/.gitignore
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + err.log