mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	linux_kselftest-next-6.10-rc1
This kselftest update for Linux 6.10-rc1 consists of: - changes to make framework and tests reporting KTAP compliant - changes to make ktap_helpers and power_supply test POSIX compliant - adds ksft_exit_fail_perror() to include errono in string form - fixes to avoid clang reporting false positive static analysis errors about functions that exit and never return. ksft_exit* functions are marked __noreturn to address this problem - adds mechanism for reporting a KSFT_ result code - fixes to build warnings related missing headers and unused variables - fixes to clang build failures - cleanups to resctrl test - adds host arch for LLVM builds -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmZCRtQACgkQCwJExA0N QxzHdQ/+KhuP8hFcou0rJpCMum+mATe0fXeqcA+lrjwWI7JeTdFb+YmaSCeoQeg7 uHR/oxr6wk7a8I8Yg1aK4CRZaQhTwf9/zR0/QGxqt/hgGdPBf9BzZZ3oNnNBzccN 2qoB2OT83hS3j7YI944EuimrmXSGwdVbqBHefmTEH6tJ4TeIIC2tZOaQcpItAFAC 0UiibwDFiI3grPtzIkoSNGsJLXaBt2wa7G9j3AB74zVkJ/DCuEw8u/Wv0eG1v9Zt pUHx4w2sTk4QF1Njxzaflply6FCgNzhn8NMSNDp/mjc+SdUgxL1pRYcgvr/GE1Ye qy4TNMui+5iG68bsqja+l8oDXkTNCcwMC6v9dWwzrbTUDp0fJk3aGjchrzKq2Ef7 JSLr8gQm2U17asus4XyCQys7doJG7+iXKzhpDTMFkfDHkWazpL4EeXpFDuRTFyDc zIzcmgBR2xjvQMGyVIhoygGw/RTIYZwpu+r6hnrXMG+DfrTlsv9uMk0CvJioBEwP OZ67qc/dO1UhHSp30g4x5eqWfEX+ndMjw7yKZemwz2h0ltnwob8INIiQm6/eBsHj TZDNLzxWkydSwQwS/q71eYup2BTFjKzF744DjUCePGzLwd0LJfCE/GPKe9Ugf3th IzGx+9EiDRlFKZ3fQyJFcgu06vO8ko1mfg6CqFCReqUpW/8rk/s= =XIu6 -----END PGP SIGNATURE----- Merge tag 'linux_kselftest-next-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest Pull kselftest updates from Shuah Khan: - make framework and tests reporting KTAP compliant - make ktap_helpers and power_supply test POSIX compliant - add ksft_exit_fail_perror() to include errono in string form - avoid clang reporting false positive static analysis errors about functions that exit and never return. ksft_exit* functions are marked __noreturn to address this problem - add mechanism for reporting a KSFT_ result code - fix build warnings related missing headers and unused variables - fix clang build failures - cleanups to resctrl test - add host arch for LLVM builds * tag 'linux_kselftest-next-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (44 commits) selftests/sgx: Include KHDR_INCLUDES in Makefile selftests: Compile kselftest headers with -D_GNU_SOURCE selftests/resctrl: fix clang build warnings related to abs(), labs() calls selftests/ftrace: Fix checkbashisms errors selftests/ftrace: Fix BTFARG testcase to check fprobe is enabled correctly selftests/capabilities: fix warn_unused_result build warnings selftests: filesystems: add missing stddef header selftests: kselftest_deps: fix l5_test() empty variable selftests: default to host arch for LLVM builds selftests/resctrl: fix clang build failure: use LOCAL_HDRS selftests/binderfs: use the Makefile's rules, not Make's implicit rules Documentation: kselftest: fix codeblock selftests: kselftest: Make ksft_exit functions return void instead of int selftests: x86: ksft_exit_pass() does not return selftests: timers: ksft_exit functions do not return selftests: sync: ksft_exit_pass() does not return selftests/resctrl: ksft_exit_skip() does not return selftests: pidfd: ksft_exit functions do not return selftests/mm: ksft_exit functions do not return selftests: membarrier: ksft_exit_pass() does not return ...
This commit is contained in:
		
						commit
						4b95dc8736
					
				
					 72 changed files with 804 additions and 776 deletions
				
			
		| 
						 | 
					@ -183,7 +183,7 @@ expected time it takes to run a test. If you have control over the systems
 | 
				
			||||||
which will run the tests you can configure a test runner on those systems to
 | 
					which will run the tests you can configure a test runner on those systems to
 | 
				
			||||||
use a greater or lower timeout on the command line as with the `-o` or
 | 
					use a greater or lower timeout on the command line as with the `-o` or
 | 
				
			||||||
the `--override-timeout` argument. For example to use 165 seconds instead
 | 
					the `--override-timeout` argument. For example to use 165 seconds instead
 | 
				
			||||||
one would use:
 | 
					one would use::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   $ ./run_kselftest.sh --override-timeout 165
 | 
					   $ ./run_kselftest.sh --override-timeout 165
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,11 +161,11 @@ ifneq ($(KBUILD_OUTPUT),)
 | 
				
			||||||
  # $(realpath ...) resolves symlinks
 | 
					  # $(realpath ...) resolves symlinks
 | 
				
			||||||
  abs_objtree := $(realpath $(abs_objtree))
 | 
					  abs_objtree := $(realpath $(abs_objtree))
 | 
				
			||||||
  BUILD := $(abs_objtree)/kselftest
 | 
					  BUILD := $(abs_objtree)/kselftest
 | 
				
			||||||
  KHDR_INCLUDES := -isystem ${abs_objtree}/usr/include
 | 
					  KHDR_INCLUDES := -D_GNU_SOURCE -isystem ${abs_objtree}/usr/include
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
  BUILD := $(CURDIR)
 | 
					  BUILD := $(CURDIR)
 | 
				
			||||||
  abs_srctree := $(shell cd $(top_srcdir) && pwd)
 | 
					  abs_srctree := $(shell cd $(top_srcdir) && pwd)
 | 
				
			||||||
  KHDR_INCLUDES := -isystem ${abs_srctree}/usr/include
 | 
					  KHDR_INCLUDES := -D_GNU_SOURCE -isystem ${abs_srctree}/usr/include
 | 
				
			||||||
  DEFAULT_INSTALL_HDR_PATH := 1
 | 
					  DEFAULT_INSTALL_HDR_PATH := 1
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ static bool create_and_enter_ns(uid_t inner_uid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uid_t outer_uid;
 | 
						uid_t outer_uid;
 | 
				
			||||||
	gid_t outer_gid;
 | 
						gid_t outer_gid;
 | 
				
			||||||
	int i;
 | 
						int i, ret;
 | 
				
			||||||
	bool have_outer_privilege;
 | 
						bool have_outer_privilege;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	outer_uid = getuid();
 | 
						outer_uid = getuid();
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,10 @@ static bool create_and_enter_ns(uid_t inner_uid)
 | 
				
			||||||
			ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
 | 
								ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Re-enable effective caps
 | 
							// Re-enable effective caps
 | 
				
			||||||
		capng_get_caps_process();
 | 
							ret = capng_get_caps_process();
 | 
				
			||||||
 | 
							if (ret == -1)
 | 
				
			||||||
 | 
								ksft_exit_fail_msg("capng_get_caps_process failed\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < CAP_LAST_CAP; i++)
 | 
							for (i = 0; i < CAP_LAST_CAP; i++)
 | 
				
			||||||
			if (capng_have_capability(CAPNG_PERMITTED, i))
 | 
								if (capng_have_capability(CAPNG_PERMITTED, i))
 | 
				
			||||||
				capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
 | 
									capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
 | 
				
			||||||
| 
						 | 
					@ -207,6 +210,7 @@ static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int do_tests(int uid, const char *our_path)
 | 
					static int do_tests(int uid, const char *our_path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
	bool have_outer_privilege = create_and_enter_ns(uid);
 | 
						bool have_outer_privilege = create_and_enter_ns(uid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
 | 
						int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
 | 
				
			||||||
| 
						 | 
					@ -250,7 +254,9 @@ static int do_tests(int uid, const char *our_path)
 | 
				
			||||||
			ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
 | 
								ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	capng_get_caps_process();
 | 
						ret = capng_get_caps_process();
 | 
				
			||||||
 | 
						if (ret == -1)
 | 
				
			||||||
 | 
							ksft_exit_fail_msg("capng_get_caps_process failed\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure that i starts out clear */
 | 
						/* Make sure that i starts out clear */
 | 
				
			||||||
	capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
 | 
						capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ static bool bool_arg(char **argv, int i)
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *atsec = "";
 | 
						const char *atsec = "";
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Be careful just in case a setgid or setcapped copy of this
 | 
						 * Be careful just in case a setgid or setcapped copy of this
 | 
				
			||||||
| 
						 | 
					@ -44,7 +45,11 @@ int main(int argc, char **argv)
 | 
				
			||||||
		atsec = " (AT_SECURE is not set)";
 | 
							atsec = " (AT_SECURE is not set)";
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	capng_get_caps_process();
 | 
						ret = capng_get_caps_process();
 | 
				
			||||||
 | 
						if (ret == -1) {
 | 
				
			||||||
 | 
							ksft_print_msg("capng_get_caps_process failed\n");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
 | 
						if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
 | 
				
			||||||
		ksft_print_msg("Wrong effective state%s\n", atsec);
 | 
							ksft_print_msg("Wrong effective state%s\n", atsec);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,9 +95,14 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
 | 
				
			||||||
			getpid(), pid);
 | 
								getpid(), pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (waitpid(-1, &status, __WALL) < 0) {
 | 
						if (waitpid(-1, &status, __WALL) < 0) {
 | 
				
			||||||
		ksft_print_msg("Child returned %s\n", strerror(errno));
 | 
							ksft_print_msg("waitpid() returned %s\n", strerror(errno));
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (!WIFEXITED(status)) {
 | 
				
			||||||
 | 
							ksft_print_msg("Child did not exit normally, status 0x%x\n",
 | 
				
			||||||
 | 
								       status);
 | 
				
			||||||
 | 
							return EXIT_FAILURE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (WEXITSTATUS(status))
 | 
						if (WEXITSTATUS(status))
 | 
				
			||||||
		return WEXITSTATUS(status);
 | 
							return WEXITSTATUS(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,5 +120,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_clear_sighand();
 | 
						test_clone3_clear_sighand();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,8 @@ static int call_clone3_set_tid(pid_t *set_tid,
 | 
				
			||||||
	return WEXITSTATUS(status);
 | 
						return WEXITSTATUS(status);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_clone3_set_tid(pid_t *set_tid,
 | 
					static void test_clone3_set_tid(const char *desc,
 | 
				
			||||||
 | 
									pid_t *set_tid,
 | 
				
			||||||
				size_t set_tid_size,
 | 
									size_t set_tid_size,
 | 
				
			||||||
				int flags,
 | 
									int flags,
 | 
				
			||||||
				int expected,
 | 
									int expected,
 | 
				
			||||||
| 
						 | 
					@ -129,17 +130,13 @@ static void test_clone3_set_tid(pid_t *set_tid,
 | 
				
			||||||
	ret = call_clone3_set_tid(set_tid, set_tid_size, flags, expected_pid,
 | 
						ret = call_clone3_set_tid(set_tid, set_tid_size, flags, expected_pid,
 | 
				
			||||||
				  wait_for_it);
 | 
									  wait_for_it);
 | 
				
			||||||
	ksft_print_msg(
 | 
						ksft_print_msg(
 | 
				
			||||||
		"[%d] clone3() with CLONE_SET_TID %d says :%d - expected %d\n",
 | 
							"[%d] clone3() with CLONE_SET_TID %d says: %d - expected %d\n",
 | 
				
			||||||
		getpid(), set_tid[0], ret, expected);
 | 
							getpid(), set_tid[0], ret, expected);
 | 
				
			||||||
	if (ret != expected)
 | 
					
 | 
				
			||||||
		ksft_test_result_fail(
 | 
						ksft_test_result(ret == expected, "%s with %zu TIDs and flags 0x%x\n",
 | 
				
			||||||
			"[%d] Result (%d) is different than expected (%d)\n",
 | 
								 desc, set_tid_size, flags);
 | 
				
			||||||
			getpid(), ret, expected);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ksft_test_result_pass(
 | 
					 | 
				
			||||||
			"[%d] Result (%d) matches expectation (%d)\n",
 | 
					 | 
				
			||||||
			getpid(), ret, expected);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[])
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE *f;
 | 
						FILE *f;
 | 
				
			||||||
| 
						 | 
					@ -172,73 +169,91 @@ int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Try invalid settings */
 | 
						/* Try invalid settings */
 | 
				
			||||||
	memset(&set_tid, 0, sizeof(set_tid));
 | 
						memset(&set_tid, 0, sizeof(set_tid));
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
 | 
						test_clone3_set_tid("invalid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
 | 
				
			||||||
			    -EINVAL, 0, 0);
 | 
								    -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
 | 
						 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
 | 
				
			||||||
	 * nested PID namespace.
 | 
						 * nested PID namespace.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&set_tid, 0xff, sizeof(set_tid));
 | 
						memset(&set_tid, 0xff, sizeof(set_tid));
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, TID all 1s",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, TID all 1s",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
 | 
						test_clone3_set_tid("invalid size, TID all 1s",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
 | 
				
			||||||
			    -EINVAL, 0, 0);
 | 
								    -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, TID all 1s",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
 | 
						 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
 | 
				
			||||||
	 * nested PID namespace.
 | 
						 * nested PID namespace.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("invalid size, TID all 1s",
 | 
				
			||||||
 | 
								    set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&set_tid, 0, sizeof(set_tid));
 | 
						memset(&set_tid, 0, sizeof(set_tid));
 | 
				
			||||||
	/* Try with an invalid PID */
 | 
						/* Try with an invalid PID */
 | 
				
			||||||
	set_tid[0] = 0;
 | 
						set_tid[0] = 0;
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("valid size, 0 TID",
 | 
				
			||||||
 | 
								    set_tid, 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_tid[0] = -1;
 | 
						set_tid[0] = -1;
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("valid size, -1 TID",
 | 
				
			||||||
 | 
								    set_tid, 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Claim that the set_tid array actually contains 2 elements. */
 | 
						/* Claim that the set_tid array actually contains 2 elements. */
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("2 TIDs, -1 and 0",
 | 
				
			||||||
 | 
								    set_tid, 2, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Try it in a new PID namespace */
 | 
						/* Try it in a new PID namespace */
 | 
				
			||||||
	if (uid == 0)
 | 
						if (uid == 0)
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
							test_clone3_set_tid("valid size, -1 TID",
 | 
				
			||||||
 | 
									    set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
							ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Try with a valid PID (1) this should return -EEXIST. */
 | 
						/* Try with a valid PID (1) this should return -EEXIST. */
 | 
				
			||||||
	set_tid[0] = 1;
 | 
						set_tid[0] = 1;
 | 
				
			||||||
	if (uid == 0)
 | 
						if (uid == 0)
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 1, 0, -EEXIST, 0, 0);
 | 
							test_clone3_set_tid("duplicate PID 1",
 | 
				
			||||||
 | 
									    set_tid, 1, 0, -EEXIST, 0, 0);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
							ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Try it in a new PID namespace */
 | 
						/* Try it in a new PID namespace */
 | 
				
			||||||
	if (uid == 0)
 | 
						if (uid == 0)
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, 0, 0, 0);
 | 
							test_clone3_set_tid("duplicate PID 1",
 | 
				
			||||||
 | 
									    set_tid, 1, CLONE_NEWPID, 0, 0, 0);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
							ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* pid_max should fail everywhere */
 | 
						/* pid_max should fail everywhere */
 | 
				
			||||||
	set_tid[0] = pid_max;
 | 
						set_tid[0] = pid_max;
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("set TID to maximum",
 | 
				
			||||||
 | 
								    set_tid, 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (uid == 0)
 | 
						if (uid == 0)
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
							test_clone3_set_tid("set TID to maximum",
 | 
				
			||||||
 | 
									    set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
							ksft_test_result_skip("Clone3() with set_tid requires root\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,10 +277,12 @@ int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* After the child has finished, its PID should be free. */
 | 
						/* After the child has finished, its PID should be free. */
 | 
				
			||||||
	set_tid[0] = pid;
 | 
						set_tid[0] = pid;
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, 0, 0, 0, 0);
 | 
						test_clone3_set_tid("reallocate child TID",
 | 
				
			||||||
 | 
								    set_tid, 1, 0, 0, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This should fail as there is no PID 1 in that namespace */
 | 
						/* This should fail as there is no PID 1 in that namespace */
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("duplicate child TID",
 | 
				
			||||||
 | 
								    set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Creating a process with PID 1 in the newly created most nested
 | 
						 * Creating a process with PID 1 in the newly created most nested
 | 
				
			||||||
| 
						 | 
					@ -274,7 +291,8 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	set_tid[0] = 1;
 | 
						set_tid[0] = 1;
 | 
				
			||||||
	set_tid[1] = pid;
 | 
						set_tid[1] = pid;
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 2, CLONE_NEWPID, 0, pid, 0);
 | 
						test_clone3_set_tid("create PID 1 in new NS",
 | 
				
			||||||
 | 
								    set_tid, 2, CLONE_NEWPID, 0, pid, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_print_msg("unshare PID namespace\n");
 | 
						ksft_print_msg("unshare PID namespace\n");
 | 
				
			||||||
	if (unshare(CLONE_NEWPID) == -1)
 | 
						if (unshare(CLONE_NEWPID) == -1)
 | 
				
			||||||
| 
						 | 
					@ -284,7 +302,8 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	set_tid[0] = pid;
 | 
						set_tid[0] = pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This should fail as there is no PID 1 in that namespace */
 | 
						/* This should fail as there is no PID 1 in that namespace */
 | 
				
			||||||
	test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
 | 
						test_clone3_set_tid("duplicate PID 1",
 | 
				
			||||||
 | 
								    set_tid, 1, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Let's create a PID 1 */
 | 
						/* Let's create a PID 1 */
 | 
				
			||||||
	ns_pid = fork();
 | 
						ns_pid = fork();
 | 
				
			||||||
| 
						 | 
					@ -295,21 +314,25 @@ int main(int argc, char *argv[])
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		set_tid[0] = 43;
 | 
							set_tid[0] = 43;
 | 
				
			||||||
		set_tid[1] = -1;
 | 
							set_tid[1] = -1;
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
 | 
							test_clone3_set_tid("check leak on invalid TID -1",
 | 
				
			||||||
 | 
									    set_tid, 2, 0, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		set_tid[0] = 43;
 | 
							set_tid[0] = 43;
 | 
				
			||||||
		set_tid[1] = pid;
 | 
							set_tid[1] = pid;
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 2, 0, 0, 43, 0);
 | 
							test_clone3_set_tid("check leak on invalid specific TID",
 | 
				
			||||||
 | 
									    set_tid, 2, 0, 0, 43, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ksft_print_msg("Child in PID namespace has PID %d\n", getpid());
 | 
							ksft_print_msg("Child in PID namespace has PID %d\n", getpid());
 | 
				
			||||||
		set_tid[0] = 2;
 | 
							set_tid[0] = 2;
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 1, 0, 0, 2, 0);
 | 
							test_clone3_set_tid("create PID 2 in child NS",
 | 
				
			||||||
 | 
									    set_tid, 1, 0, 0, 2, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		set_tid[0] = 1;
 | 
							set_tid[0] = 1;
 | 
				
			||||||
		set_tid[1] = -1;
 | 
							set_tid[1] = -1;
 | 
				
			||||||
		set_tid[2] = pid;
 | 
							set_tid[2] = pid;
 | 
				
			||||||
		/* This should fail as there is invalid PID at level '1'. */
 | 
							/* This should fail as there is invalid PID at level '1'. */
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
							test_clone3_set_tid("fail due to invalid TID at level 1",
 | 
				
			||||||
 | 
									    set_tid, 3, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		set_tid[0] = 1;
 | 
							set_tid[0] = 1;
 | 
				
			||||||
		set_tid[1] = 42;
 | 
							set_tid[1] = 42;
 | 
				
			||||||
| 
						 | 
					@ -319,13 +342,15 @@ int main(int argc, char *argv[])
 | 
				
			||||||
		 * namespaces. Again assuming this is running in the host's
 | 
							 * namespaces. Again assuming this is running in the host's
 | 
				
			||||||
		 * PID namespace. Not yet nested.
 | 
							 * PID namespace. Not yet nested.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 4, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
							test_clone3_set_tid("fail due to too few active PID NSs",
 | 
				
			||||||
 | 
									    set_tid, 4, CLONE_NEWPID, -EINVAL, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * This should work and from the parent we should see
 | 
							 * This should work and from the parent we should see
 | 
				
			||||||
		 * something like 'NSpid:	pid	42	1'.
 | 
							 * something like 'NSpid:	pid	42	1'.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, 0, 42, true);
 | 
							test_clone3_set_tid("verify that we have 3 PID NSs",
 | 
				
			||||||
 | 
									    set_tid, 3, CLONE_NEWPID, 0, 42, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		child_exit(ksft_cnt.ksft_fail);
 | 
							child_exit(ksft_cnt.ksft_fail);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -380,16 +405,14 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status));
 | 
						ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status));
 | 
				
			||||||
	ksft_cnt.ksft_fail = WEXITSTATUS(status);
 | 
						ksft_cnt.ksft_fail = WEXITSTATUS(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ns3 == pid && ns2 == 42 && ns1 == 1)
 | 
						ksft_print_msg("Expecting PIDs %d, 42, 1\n", pid);
 | 
				
			||||||
		ksft_test_result_pass(
 | 
						ksft_print_msg("Have PIDs in namespaces: %d, %d, %d\n", ns3, ns2, ns1);
 | 
				
			||||||
			"PIDs in all namespaces as expected (%d,%d,%d)\n",
 | 
						ksft_test_result(ns3 == pid && ns2 == 42 && ns1 == 1,
 | 
				
			||||||
			ns3, ns2, ns1);
 | 
								 "PIDs in all namespaces as expected\n");
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ksft_test_result_fail(
 | 
					 | 
				
			||||||
			"PIDs in all namespaces not as expected (%d,%d,%d)\n",
 | 
					 | 
				
			||||||
			ns3, ns2, ns1);
 | 
					 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	ret = 0;
 | 
						ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !ret ? ksft_exit_pass() : ksft_exit_fail();
 | 
						if (ret)
 | 
				
			||||||
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,8 +178,7 @@ cpufreq_basic_tests()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count=$(count_cpufreq_managed_cpus)
 | 
						count=$(count_cpufreq_managed_cpus)
 | 
				
			||||||
	if [ $count = 0 ]; then
 | 
						if [ $count = 0 ]; then
 | 
				
			||||||
		printf "No cpu is managed by cpufreq core, exiting\n"
 | 
							ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting\n"
 | 
				
			||||||
		exit;
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		printf "CPUFreq manages: $count CPUs\n\n"
 | 
							printf "CPUFreq manages: $count CPUs\n\n"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,15 +7,15 @@ source governor.sh
 | 
				
			||||||
source module.sh
 | 
					source module.sh
 | 
				
			||||||
source special-tests.sh
 | 
					source special-tests.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DIR="$(dirname $(readlink -f "$0"))"
 | 
				
			||||||
 | 
					source "${DIR}"/../kselftest/ktap_helpers.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FUNC=basic	# do basic tests by default
 | 
					FUNC=basic	# do basic tests by default
 | 
				
			||||||
OUTFILE=cpufreq_selftest
 | 
					OUTFILE=cpufreq_selftest
 | 
				
			||||||
SYSFS=
 | 
					SYSFS=
 | 
				
			||||||
CPUROOT=
 | 
					CPUROOT=
 | 
				
			||||||
CPUFREQROOT=
 | 
					CPUFREQROOT=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Kselftest framework requirement - SKIP code is 4.
 | 
					 | 
				
			||||||
ksft_skip=4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
helpme()
 | 
					helpme()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	printf "Usage: $0 [-h] [-todg args]
 | 
						printf "Usage: $0 [-h] [-todg args]
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ helpme()
 | 
				
			||||||
	[-d <driver's module name: only with \"-t modtest>\"]
 | 
						[-d <driver's module name: only with \"-t modtest>\"]
 | 
				
			||||||
	[-g <governor's module name: only with \"-t modtest>\"]
 | 
						[-g <governor's module name: only with \"-t modtest>\"]
 | 
				
			||||||
	\n"
 | 
						\n"
 | 
				
			||||||
	exit 2
 | 
						exit "${KSFT_FAIL}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
prerequisite()
 | 
					prerequisite()
 | 
				
			||||||
| 
						 | 
					@ -40,8 +40,8 @@ prerequisite()
 | 
				
			||||||
	msg="skip all tests:"
 | 
						msg="skip all tests:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if [ $UID != 0 ]; then
 | 
						if [ $UID != 0 ]; then
 | 
				
			||||||
		echo $msg must be run as root >&2
 | 
							ktap_skip_all "$msg must be run as root"
 | 
				
			||||||
		exit $ksft_skip
 | 
							exit "${KSFT_SKIP}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	taskset -p 01 $$
 | 
						taskset -p 01 $$
 | 
				
			||||||
| 
						 | 
					@ -49,21 +49,21 @@ prerequisite()
 | 
				
			||||||
	SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
 | 
						SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if [ ! -d "$SYSFS" ]; then
 | 
						if [ ! -d "$SYSFS" ]; then
 | 
				
			||||||
		echo $msg sysfs is not mounted >&2
 | 
							ktap_skip_all "$msg sysfs is not mounted"
 | 
				
			||||||
		exit 2
 | 
							exit "${KSFT_SKIP}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CPUROOT=$SYSFS/devices/system/cpu
 | 
						CPUROOT=$SYSFS/devices/system/cpu
 | 
				
			||||||
	CPUFREQROOT="$CPUROOT/cpufreq"
 | 
						CPUFREQROOT="$CPUROOT/cpufreq"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
 | 
						if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
 | 
				
			||||||
		echo $msg cpus not available in sysfs >&2
 | 
							ktap_skip_all "$msg cpus not available in sysfs"
 | 
				
			||||||
		exit 2
 | 
							exit "${KSFT_SKIP}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
 | 
						if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
 | 
				
			||||||
		echo $msg cpufreq directory not available in sysfs >&2
 | 
							ktap_skip_all "$msg cpufreq directory not available in sysfs"
 | 
				
			||||||
		exit 2
 | 
							exit "${KSFT_SKIP}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,7 @@ do_test()
 | 
				
			||||||
	count=$(count_cpufreq_managed_cpus)
 | 
						count=$(count_cpufreq_managed_cpus)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if [ $count = 0 -a $FUNC != "modtest" ]; then
 | 
						if [ $count = 0 -a $FUNC != "modtest" ]; then
 | 
				
			||||||
		echo "No cpu is managed by cpufreq core, exiting"
 | 
							ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting"
 | 
				
			||||||
		exit 2;
 | 
					 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "$FUNC" in
 | 
						case "$FUNC" in
 | 
				
			||||||
| 
						 | 
					@ -125,8 +124,7 @@ do_test()
 | 
				
			||||||
		"modtest")
 | 
							"modtest")
 | 
				
			||||||
		# Do we have modules in place?
 | 
							# Do we have modules in place?
 | 
				
			||||||
		if [ -z $DRIVER_MOD ] && [ -z $GOVERNOR_MOD ]; then
 | 
							if [ -z $DRIVER_MOD ] && [ -z $GOVERNOR_MOD ]; then
 | 
				
			||||||
			echo "No driver or governor module passed with -d or -g"
 | 
								ktap_exit_fail_msg "No driver or governor module passed with -d or -g"
 | 
				
			||||||
			exit 2;
 | 
					 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if [ $DRIVER_MOD ]; then
 | 
							if [ $DRIVER_MOD ]; then
 | 
				
			||||||
| 
						 | 
					@ -137,8 +135,7 @@ do_test()
 | 
				
			||||||
			fi
 | 
								fi
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			if [ $count = 0 ]; then
 | 
								if [ $count = 0 ]; then
 | 
				
			||||||
				echo "No cpu is managed by cpufreq core, exiting"
 | 
									ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting"
 | 
				
			||||||
				exit 2;
 | 
					 | 
				
			||||||
			fi
 | 
								fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			module_governor_test $GOVERNOR_MOD
 | 
								module_governor_test $GOVERNOR_MOD
 | 
				
			||||||
| 
						 | 
					@ -162,7 +159,7 @@ do_test()
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*)
 | 
							*)
 | 
				
			||||||
		echo "Invalid [-f] function type"
 | 
							ktap_print_msg "Invalid [-f] function type"
 | 
				
			||||||
		helpme
 | 
							helpme
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
	esac
 | 
						esac
 | 
				
			||||||
| 
						 | 
					@ -186,13 +183,25 @@ dmesg_dumps()
 | 
				
			||||||
	dmesg >> $1.dmesg_full.txt
 | 
						dmesg >> $1.dmesg_full.txt
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ktap_print_header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Parse arguments
 | 
					# Parse arguments
 | 
				
			||||||
parse_arguments $@
 | 
					parse_arguments $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ktap_set_plan 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Make sure all requirements are met
 | 
					# Make sure all requirements are met
 | 
				
			||||||
prerequisite
 | 
					prerequisite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Run requested functions
 | 
					# Run requested functions
 | 
				
			||||||
clear_dumps $OUTFILE
 | 
					clear_dumps $OUTFILE
 | 
				
			||||||
do_test | tee -a $OUTFILE.txt
 | 
					do_test | tee -a $OUTFILE.txt
 | 
				
			||||||
 | 
					if [ "${PIPESTATUS[0]}" -ne 0 ]; then
 | 
				
			||||||
 | 
					    exit ${PIPESTATUS[0]};
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
dmesg_dumps $OUTFILE
 | 
					dmesg_dumps $OUTFILE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ktap_test_pass "Completed successfully"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ktap_print_totals
 | 
				
			||||||
 | 
					exit "${KSFT_PASS}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,16 +24,14 @@ test_basic_insmod_rmmod()
 | 
				
			||||||
	# insert module
 | 
						# insert module
 | 
				
			||||||
	insmod $1
 | 
						insmod $1
 | 
				
			||||||
	if [ $? != 0 ]; then
 | 
						if [ $? != 0 ]; then
 | 
				
			||||||
		printf "Insmod $1 failed\n"
 | 
							ktap_exit_fail_msg "Insmod $1 failed\n"
 | 
				
			||||||
		exit;
 | 
					 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf "Removing $1 module\n"
 | 
						printf "Removing $1 module\n"
 | 
				
			||||||
	# remove module
 | 
						# remove module
 | 
				
			||||||
	rmmod $1
 | 
						rmmod $1
 | 
				
			||||||
	if [ $? != 0 ]; then
 | 
						if [ $? != 0 ]; then
 | 
				
			||||||
		printf "rmmod $1 failed\n"
 | 
							ktap_exit_fail_msg "rmmod $1 failed\n"
 | 
				
			||||||
		exit;
 | 
					 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf "\n"
 | 
						printf "\n"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include <linux/dma-buf.h>
 | 
					#include <linux/dma-buf.h>
 | 
				
			||||||
#include <linux/dma-heap.h>
 | 
					#include <linux/dma-heap.h>
 | 
				
			||||||
#include <drm/drm.h>
 | 
					#include <drm/drm.h>
 | 
				
			||||||
 | 
					#include "../kselftest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEVPATH "/dev/dma_heap"
 | 
					#define DEVPATH "/dev/dma_heap"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,14 +91,13 @@ static int dmabuf_heap_open(char *name)
 | 
				
			||||||
	char buf[256];
 | 
						char buf[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = snprintf(buf, 256, "%s/%s", DEVPATH, name);
 | 
						ret = snprintf(buf, 256, "%s/%s", DEVPATH, name);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0)
 | 
				
			||||||
		printf("snprintf failed!\n");
 | 
							ksft_exit_fail_msg("snprintf failed! %d\n", ret);
 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fd = open(buf, O_RDWR);
 | 
						fd = open(buf, O_RDWR);
 | 
				
			||||||
	if (fd < 0)
 | 
						if (fd < 0)
 | 
				
			||||||
		printf("open %s failed!\n", buf);
 | 
							ksft_exit_fail_msg("open %s failed: %s\n", buf, strerror(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return fd;
 | 
						return fd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,7 @@ static int dmabuf_sync(int fd, int start_stop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ONE_MEG (1024 * 1024)
 | 
					#define ONE_MEG (1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_alloc_and_import(char *heap_name)
 | 
					static void test_alloc_and_import(char *heap_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
 | 
						int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
 | 
				
			||||||
	uint32_t handle = 0;
 | 
						uint32_t handle = 0;
 | 
				
			||||||
| 
						 | 
					@ -148,27 +148,19 @@ static int test_alloc_and_import(char *heap_name)
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	heap_fd = dmabuf_heap_open(heap_name);
 | 
						heap_fd = dmabuf_heap_open(heap_name);
 | 
				
			||||||
	if (heap_fd < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("  Testing allocation and importing:  ");
 | 
						ksft_print_msg("Testing allocation and importing:\n");
 | 
				
			||||||
	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
						ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		printf("FAIL (Allocation Failed!)\n");
 | 
							ksft_test_result_fail("FAIL (Allocation Failed!) %d\n", ret);
 | 
				
			||||||
		ret = -1;
 | 
							return;
 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* mmap and write a simple pattern */
 | 
						/* mmap and write a simple pattern */
 | 
				
			||||||
	p = mmap(NULL,
 | 
						p = mmap(NULL, ONE_MEG, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd, 0);
 | 
				
			||||||
		 ONE_MEG,
 | 
					 | 
				
			||||||
		 PROT_READ | PROT_WRITE,
 | 
					 | 
				
			||||||
		 MAP_SHARED,
 | 
					 | 
				
			||||||
		 dmabuf_fd,
 | 
					 | 
				
			||||||
		 0);
 | 
					 | 
				
			||||||
	if (p == MAP_FAILED) {
 | 
						if (p == MAP_FAILED) {
 | 
				
			||||||
		printf("FAIL (mmap() failed)\n");
 | 
							ksft_test_result_fail("FAIL (mmap() failed): %s\n", strerror(errno));
 | 
				
			||||||
		ret = -1;
 | 
							goto close_and_return;
 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
 | 
						dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
 | 
				
			||||||
| 
						 | 
					@ -178,71 +170,64 @@ static int test_alloc_and_import(char *heap_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	importer_fd = open_vgem();
 | 
						importer_fd = open_vgem();
 | 
				
			||||||
	if (importer_fd < 0) {
 | 
						if (importer_fd < 0) {
 | 
				
			||||||
		ret = importer_fd;
 | 
							ksft_test_result_skip("Could not open vgem %d\n", importer_fd);
 | 
				
			||||||
		printf("(Could not open vgem - skipping):  ");
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
 | 
							ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
 | 
				
			||||||
		if (ret < 0) {
 | 
							ksft_test_result(ret >= 0, "Import buffer %d\n", ret);
 | 
				
			||||||
			printf("FAIL (Failed to import buffer)\n");
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
 | 
						ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		printf("FAIL (DMA_BUF_SYNC_START failed!)\n");
 | 
							ksft_print_msg("FAIL (DMA_BUF_SYNC_START failed!) %d\n", ret);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(p, 0xff, ONE_MEG);
 | 
						memset(p, 0xff, ONE_MEG);
 | 
				
			||||||
	ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
 | 
						ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		printf("FAIL (DMA_BUF_SYNC_END failed!)\n");
 | 
							ksft_print_msg("FAIL (DMA_BUF_SYNC_END failed!) %d\n", ret);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close_handle(importer_fd, handle);
 | 
						close_handle(importer_fd, handle);
 | 
				
			||||||
	ret = 0;
 | 
						ksft_test_result_pass("%s dmabuf sync succeeded\n", __func__);
 | 
				
			||||||
	printf(" OK\n");
 | 
						return;
 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	if (p)
 | 
					 | 
				
			||||||
		munmap(p, ONE_MEG);
 | 
					 | 
				
			||||||
	if (importer_fd >= 0)
 | 
					 | 
				
			||||||
		close(importer_fd);
 | 
					 | 
				
			||||||
	if (dmabuf_fd >= 0)
 | 
					 | 
				
			||||||
		close(dmabuf_fd);
 | 
					 | 
				
			||||||
	if (heap_fd >= 0)
 | 
					 | 
				
			||||||
		close(heap_fd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
					out:
 | 
				
			||||||
 | 
						ksft_test_result_fail("%s dmabuf sync failed\n", __func__);
 | 
				
			||||||
 | 
						munmap(p, ONE_MEG);
 | 
				
			||||||
 | 
						close(importer_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					close_and_return:
 | 
				
			||||||
 | 
						close(dmabuf_fd);
 | 
				
			||||||
 | 
						close(heap_fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_alloc_zeroed(char *heap_name, size_t size)
 | 
					static void test_alloc_zeroed(char *heap_name, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int heap_fd = -1, dmabuf_fd[32];
 | 
						int heap_fd = -1, dmabuf_fd[32];
 | 
				
			||||||
	int i, j, ret;
 | 
						int i, j, k, ret;
 | 
				
			||||||
	void *p = NULL;
 | 
						void *p = NULL;
 | 
				
			||||||
	char *c;
 | 
						char *c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("  Testing alloced %ldk buffers are zeroed:  ", size / 1024);
 | 
						ksft_print_msg("Testing alloced %ldk buffers are zeroed:\n", size / 1024);
 | 
				
			||||||
	heap_fd = dmabuf_heap_open(heap_name);
 | 
						heap_fd = dmabuf_heap_open(heap_name);
 | 
				
			||||||
	if (heap_fd < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate and fill a bunch of buffers */
 | 
						/* Allocate and fill a bunch of buffers */
 | 
				
			||||||
	for (i = 0; i < 32; i++) {
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
		ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
 | 
							ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret) {
 | 
				
			||||||
			printf("FAIL (Allocation (%i) failed)\n", i);
 | 
								ksft_test_result_fail("FAIL (Allocation (%i) failed) %d\n", i, ret);
 | 
				
			||||||
			goto out;
 | 
								goto close_and_return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* mmap and fill with simple pattern */
 | 
							/* mmap and fill with simple pattern */
 | 
				
			||||||
		p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
 | 
							p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
 | 
				
			||||||
		if (p == MAP_FAILED) {
 | 
							if (p == MAP_FAILED) {
 | 
				
			||||||
			printf("FAIL (mmap() failed!)\n");
 | 
								ksft_test_result_fail("FAIL (mmap() failed!): %s\n", strerror(errno));
 | 
				
			||||||
			ret = -1;
 | 
								goto close_and_return;
 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
 | 
							dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
 | 
				
			||||||
		memset(p, 0xff, size);
 | 
							memset(p, 0xff, size);
 | 
				
			||||||
		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
 | 
							dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
 | 
				
			||||||
| 
						 | 
					@ -251,48 +236,47 @@ static int test_alloc_zeroed(char *heap_name, size_t size)
 | 
				
			||||||
	/* close them all */
 | 
						/* close them all */
 | 
				
			||||||
	for (i = 0; i < 32; i++)
 | 
						for (i = 0; i < 32; i++)
 | 
				
			||||||
		close(dmabuf_fd[i]);
 | 
							close(dmabuf_fd[i]);
 | 
				
			||||||
 | 
						ksft_test_result_pass("Allocate and fill a bunch of buffers\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate and validate all buffers are zeroed */
 | 
						/* Allocate and validate all buffers are zeroed */
 | 
				
			||||||
	for (i = 0; i < 32; i++) {
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
		ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
 | 
							ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			printf("FAIL (Allocation (%i) failed)\n", i);
 | 
								ksft_test_result_fail("FAIL (Allocation (%i) failed) %d\n", i, ret);
 | 
				
			||||||
			goto out;
 | 
								goto close_and_return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* mmap and validate everything is zero */
 | 
							/* mmap and validate everything is zero */
 | 
				
			||||||
		p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
 | 
							p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
 | 
				
			||||||
		if (p == MAP_FAILED) {
 | 
							if (p == MAP_FAILED) {
 | 
				
			||||||
			printf("FAIL (mmap() failed!)\n");
 | 
								ksft_test_result_fail("FAIL (mmap() failed!): %s\n", strerror(errno));
 | 
				
			||||||
			ret = -1;
 | 
								goto close_and_return;
 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
 | 
							dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
 | 
				
			||||||
		c = (char *)p;
 | 
							c = (char *)p;
 | 
				
			||||||
		for (j = 0; j < size; j++) {
 | 
							for (j = 0; j < size; j++) {
 | 
				
			||||||
			if (c[j] != 0) {
 | 
								if (c[j] != 0) {
 | 
				
			||||||
				printf("FAIL (Allocated buffer not zeroed @ %i)\n", j);
 | 
									ksft_print_msg("FAIL (Allocated buffer not zeroed @ %i)\n", j);
 | 
				
			||||||
				break;
 | 
									dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
 | 
				
			||||||
 | 
									munmap(p, size);
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
 | 
							dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
 | 
				
			||||||
		munmap(p, size);
 | 
							munmap(p, size);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* close them all */
 | 
					 | 
				
			||||||
	for (i = 0; i < 32; i++)
 | 
					 | 
				
			||||||
		close(dmabuf_fd[i]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close(heap_fd);
 | 
					 | 
				
			||||||
	printf("OK\n");
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	while (i > 0) {
 | 
						ksft_test_result(i == 32, "Allocate and validate all buffers are zeroed\n");
 | 
				
			||||||
		close(dmabuf_fd[i]);
 | 
					
 | 
				
			||||||
		i--;
 | 
					close_and_return:
 | 
				
			||||||
	}
 | 
						/* close them all */
 | 
				
			||||||
 | 
						for (k = 0; k < i; k++)
 | 
				
			||||||
 | 
							close(dmabuf_fd[k]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close(heap_fd);
 | 
						close(heap_fd);
 | 
				
			||||||
	return ret;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Test the ioctl version compatibility w/ a smaller structure then expected */
 | 
					/* Test the ioctl version compatibility w/ a smaller structure then expected */
 | 
				
			||||||
| 
						 | 
					@ -360,126 +344,97 @@ static int dmabuf_heap_alloc_newer(int fd, size_t len, unsigned int flags,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_alloc_compat(char *heap_name)
 | 
					static void test_alloc_compat(char *heap_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int heap_fd = -1, dmabuf_fd = -1;
 | 
						int ret, heap_fd = -1, dmabuf_fd = -1;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	heap_fd = dmabuf_heap_open(heap_name);
 | 
						heap_fd = dmabuf_heap_open(heap_name);
 | 
				
			||||||
	if (heap_fd < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("  Testing (theoretical)older alloc compat:  ");
 | 
						ksft_print_msg("Testing (theoretical) older alloc compat:\n");
 | 
				
			||||||
	ret = dmabuf_heap_alloc_older(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
						ret = dmabuf_heap_alloc_older(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		printf("FAIL (Older compat allocation failed!)\n");
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	close(dmabuf_fd);
 | 
					 | 
				
			||||||
	printf("OK\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printf("  Testing (theoretical)newer alloc compat:  ");
 | 
					 | 
				
			||||||
	ret = dmabuf_heap_alloc_newer(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		printf("FAIL (Newer compat allocation failed!)\n");
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	printf("OK\n");
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	if (dmabuf_fd >= 0)
 | 
						if (dmabuf_fd >= 0)
 | 
				
			||||||
		close(dmabuf_fd);
 | 
							close(dmabuf_fd);
 | 
				
			||||||
	if (heap_fd >= 0)
 | 
						ksft_test_result(!ret, "dmabuf_heap_alloc_older\n");
 | 
				
			||||||
		close(heap_fd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						ksft_print_msg("Testing (theoretical) newer alloc compat:\n");
 | 
				
			||||||
 | 
						ret = dmabuf_heap_alloc_newer(heap_fd, ONE_MEG, 0, &dmabuf_fd);
 | 
				
			||||||
 | 
						if (dmabuf_fd >= 0)
 | 
				
			||||||
 | 
							close(dmabuf_fd);
 | 
				
			||||||
 | 
						ksft_test_result(!ret, "dmabuf_heap_alloc_newer\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close(heap_fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_alloc_errors(char *heap_name)
 | 
					static void test_alloc_errors(char *heap_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int heap_fd = -1, dmabuf_fd = -1;
 | 
						int heap_fd = -1, dmabuf_fd = -1;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	heap_fd = dmabuf_heap_open(heap_name);
 | 
						heap_fd = dmabuf_heap_open(heap_name);
 | 
				
			||||||
	if (heap_fd < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("  Testing expected error cases:  ");
 | 
						ksft_print_msg("Testing expected error cases:\n");
 | 
				
			||||||
	ret = dmabuf_heap_alloc(0, ONE_MEG, 0x111111, &dmabuf_fd);
 | 
						ret = dmabuf_heap_alloc(0, ONE_MEG, 0x111111, &dmabuf_fd);
 | 
				
			||||||
	if (!ret) {
 | 
						ksft_test_result(ret, "Error expected on invalid fd %d\n", ret);
 | 
				
			||||||
		printf("FAIL (Did not see expected error (invalid fd)!)\n");
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0x111111, &dmabuf_fd);
 | 
						ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0x111111, &dmabuf_fd);
 | 
				
			||||||
	if (!ret) {
 | 
						ksft_test_result(ret, "Error expected on invalid heap flags %d\n", ret);
 | 
				
			||||||
		printf("FAIL (Did not see expected error (invalid heap flags)!)\n");
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dmabuf_heap_alloc_fdflags(heap_fd, ONE_MEG,
 | 
						ret = dmabuf_heap_alloc_fdflags(heap_fd, ONE_MEG,
 | 
				
			||||||
					~(O_RDWR | O_CLOEXEC), 0, &dmabuf_fd);
 | 
										~(O_RDWR | O_CLOEXEC), 0, &dmabuf_fd);
 | 
				
			||||||
	if (!ret) {
 | 
						ksft_test_result(ret, "Error expected on invalid heap flags %d\n", ret);
 | 
				
			||||||
		printf("FAIL (Did not see expected error (invalid fd flags)!)\n");
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("OK\n");
 | 
					 | 
				
			||||||
	ret = 0;
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	if (dmabuf_fd >= 0)
 | 
						if (dmabuf_fd >= 0)
 | 
				
			||||||
		close(dmabuf_fd);
 | 
							close(dmabuf_fd);
 | 
				
			||||||
	if (heap_fd >= 0)
 | 
					 | 
				
			||||||
	close(heap_fd);
 | 
						close(heap_fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
					static int numer_of_heaps(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DIR *d = opendir(DEVPATH);
 | 
				
			||||||
 | 
						struct dirent *dir;
 | 
				
			||||||
 | 
						int heaps = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((dir = readdir(d))) {
 | 
				
			||||||
 | 
							if (!strncmp(dir->d_name, ".", 2))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (!strncmp(dir->d_name, "..", 3))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							heaps++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return heaps;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	DIR *d;
 | 
					 | 
				
			||||||
	struct dirent *dir;
 | 
						struct dirent *dir;
 | 
				
			||||||
	int ret = -1;
 | 
						DIR *d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_header();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d = opendir(DEVPATH);
 | 
						d = opendir(DEVPATH);
 | 
				
			||||||
	if (!d) {
 | 
						if (!d) {
 | 
				
			||||||
		printf("No %s directory?\n", DEVPATH);
 | 
							ksft_print_msg("No %s directory?\n", DEVPATH);
 | 
				
			||||||
		return -1;
 | 
							return KSFT_SKIP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((dir = readdir(d)) != NULL) {
 | 
						ksft_set_plan(11 * numer_of_heaps());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((dir = readdir(d))) {
 | 
				
			||||||
		if (!strncmp(dir->d_name, ".", 2))
 | 
							if (!strncmp(dir->d_name, ".", 2))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (!strncmp(dir->d_name, "..", 3))
 | 
							if (!strncmp(dir->d_name, "..", 3))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		printf("Testing heap: %s\n", dir->d_name);
 | 
							ksft_print_msg("Testing heap: %s\n", dir->d_name);
 | 
				
			||||||
		printf("=======================================\n");
 | 
							ksft_print_msg("=======================================\n");
 | 
				
			||||||
		ret = test_alloc_and_import(dir->d_name);
 | 
							test_alloc_and_import(dir->d_name);
 | 
				
			||||||
		if (ret)
 | 
							test_alloc_zeroed(dir->d_name, 4 * 1024);
 | 
				
			||||||
			break;
 | 
							test_alloc_zeroed(dir->d_name, ONE_MEG);
 | 
				
			||||||
 | 
							test_alloc_compat(dir->d_name);
 | 
				
			||||||
		ret = test_alloc_zeroed(dir->d_name, 4 * 1024);
 | 
							test_alloc_errors(dir->d_name);
 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = test_alloc_zeroed(dir->d_name, ONE_MEG);
 | 
					 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = test_alloc_compat(dir->d_name);
 | 
					 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = test_alloc_errors(dir->d_name);
 | 
					 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	closedir(d);
 | 
						closedir(d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						ksft_finished();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,25 +37,25 @@ int main(void)
 | 
				
			||||||
			ksft_test_result_skip("error: unshare, errno %d\n", errno);
 | 
								ksft_test_result_skip("error: unshare, errno %d\n", errno);
 | 
				
			||||||
			ksft_finished();
 | 
								ksft_finished();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ksft_exit_fail_msg("error: unshare, errno %d\n", errno);
 | 
							ksft_exit_fail_perror("error: unshare");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) == -1)
 | 
						if (mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) == -1)
 | 
				
			||||||
		ksft_exit_fail_msg("error: mount '/', errno %d\n", errno);
 | 
							ksft_exit_fail_perror("error: mount '/'");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Require "exec" filesystem. */
 | 
						/* Require "exec" filesystem. */
 | 
				
			||||||
	if (mount(NULL, "/tmp", "ramfs", 0, NULL) == -1)
 | 
						if (mount(NULL, "/tmp", "ramfs", 0, NULL) == -1)
 | 
				
			||||||
		ksft_exit_fail_msg("error: mount ramfs, errno %d\n", errno);
 | 
							ksft_exit_fail_perror("error: mount ramfs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FILENAME "/tmp/1"
 | 
					#define FILENAME "/tmp/1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fd = creat(FILENAME, 0700);
 | 
						fd = creat(FILENAME, 0700);
 | 
				
			||||||
	if (fd == -1)
 | 
						if (fd == -1)
 | 
				
			||||||
		ksft_exit_fail_msg("error: creat, errno %d\n", errno);
 | 
							ksft_exit_fail_perror("error: creat");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define S "#!" FILENAME "\n"
 | 
					#define S "#!" FILENAME "\n"
 | 
				
			||||||
	if (write(fd, S, strlen(S)) != strlen(S))
 | 
						if (write(fd, S, strlen(S)) != strlen(S))
 | 
				
			||||||
		ksft_exit_fail_msg("error: write, errno %d\n", errno);
 | 
							ksft_exit_fail_perror("error: write");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close(fd);
 | 
						close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,4 @@
 | 
				
			||||||
CFLAGS += $(KHDR_INCLUDES) -pthread
 | 
					CFLAGS += $(KHDR_INCLUDES) -pthread
 | 
				
			||||||
TEST_GEN_PROGS := binderfs_test
 | 
					TEST_GEN_PROGS := binderfs_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
binderfs_test: binderfs_test.c ../../kselftest.h ../../kselftest_harness.h
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include ../../lib.mk
 | 
					include ../../lib.mk
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#define _GNU_SOURCE
 | 
					#define _GNU_SOURCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <sched.h>
 | 
					#include <sched.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,13 @@ prlog() { # messages
 | 
				
			||||||
  [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE
 | 
					  [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
catlog() { #file
 | 
					catlog() { #file
 | 
				
			||||||
 | 
					  if [ "${KTAP}" = "1" ]; then
 | 
				
			||||||
 | 
					    cat $1 | while read line ; do
 | 
				
			||||||
 | 
					      echo "# $line"
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
    cat $1
 | 
					    cat $1
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
  [ "$LOG_FILE" ] && cat $1 | strip_esc >> $LOG_FILE
 | 
					  [ "$LOG_FILE" ] && cat $1 | strip_esc >> $LOG_FILE
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
prlog "=== Ftrace unit tests ==="
 | 
					prlog "=== Ftrace unit tests ==="
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,4 +5,4 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Copyright (C) Arm Ltd., 2023
 | 
					# Copyright (C) Arm Ltd., 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
./ftracetest -K
 | 
					./ftracetest -K -v
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo > dynamic_events
 | 
					echo > dynamic_events
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ "$FIELDS" ] ; then
 | 
					if [ "$FIELDS" -a "$FPROBES" ] ; then
 | 
				
			||||||
echo "t:tpevent ${TP2} obj_size=s->object_size" >> dynamic_events
 | 
					echo "t:tpevent ${TP2} obj_size=s->object_size" >> dynamic_events
 | 
				
			||||||
echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events
 | 
					echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events
 | 
				
			||||||
echo "t:tpevent2 ${TP4} p->se.group_node.next->prev" >> dynamic_events
 | 
					echo "t:tpevent2 ${TP4} p->se.group_node.next->prev" >> dynamic_events
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ echo 1 > events/tests/enable
 | 
				
			||||||
echo > trace
 | 
					echo > trace
 | 
				
			||||||
cat trace > /dev/null
 | 
					cat trace > /dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function streq() {
 | 
					streq() {
 | 
				
			||||||
	test $1 = $2
 | 
						test $1 = $2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ echo 1 > events/kprobes/enable
 | 
				
			||||||
echo > trace
 | 
					echo > trace
 | 
				
			||||||
cat trace > /dev/null
 | 
					cat trace > /dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function streq() {
 | 
					streq() {
 | 
				
			||||||
	test $1 = $2
 | 
						test $1 = $2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,13 +198,12 @@ int main(int argc, char **argv)
 | 
				
			||||||
	struct msgque_data msgque;
 | 
						struct msgque_data msgque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (getuid() != 0)
 | 
						if (getuid() != 0)
 | 
				
			||||||
		return ksft_exit_skip(
 | 
							ksft_exit_skip("Please run the test as root - Exiting.\n");
 | 
				
			||||||
				"Please run the test as root - Exiting.\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msgque.key = ftok(argv[0], 822155650);
 | 
						msgque.key = ftok(argv[0], 822155650);
 | 
				
			||||||
	if (msgque.key == -1) {
 | 
						if (msgque.key == -1) {
 | 
				
			||||||
		printf("Can't make key: %d\n", -errno);
 | 
							printf("Can't make key: %d\n", -errno);
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
 | 
						msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
 | 
				
			||||||
| 
						 | 
					@ -243,13 +242,13 @@ int main(int argc, char **argv)
 | 
				
			||||||
		printf("Failed to test queue: %d\n", err);
 | 
							printf("Failed to test queue: %d\n", err);
 | 
				
			||||||
		goto err_out;
 | 
							goto err_out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_destroy:
 | 
					err_destroy:
 | 
				
			||||||
	if (msgctl(msgque.msq_id, IPC_RMID, NULL)) {
 | 
						if (msgctl(msgque.msq_id, IPC_RMID, NULL)) {
 | 
				
			||||||
		printf("Failed to destroy queue: %d\n", -errno);
 | 
							printf("Failed to destroy queue: %d\n", -errno);
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
err_out:
 | 
					err_out:
 | 
				
			||||||
	return ksft_exit_fail();
 | 
						ksft_exit_fail();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,10 +16,12 @@
 | 
				
			||||||
 * For each test, report any progress, debugging, etc with:
 | 
					 * For each test, report any progress, debugging, etc with:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *     ksft_print_msg(fmt, ...);
 | 
					 *     ksft_print_msg(fmt, ...);
 | 
				
			||||||
 | 
					 *     ksft_perror(msg);
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * and finally report the pass/fail/skip/xfail state of the test with one of:
 | 
					 * and finally report the pass/fail/skip/xfail state of the test with one of:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *     ksft_test_result(condition, fmt, ...);
 | 
					 *     ksft_test_result(condition, fmt, ...);
 | 
				
			||||||
 | 
					 *     ksft_test_result_report(result, fmt, ...);
 | 
				
			||||||
 *     ksft_test_result_pass(fmt, ...);
 | 
					 *     ksft_test_result_pass(fmt, ...);
 | 
				
			||||||
 *     ksft_test_result_fail(fmt, ...);
 | 
					 *     ksft_test_result_fail(fmt, ...);
 | 
				
			||||||
 *     ksft_test_result_skip(fmt, ...);
 | 
					 *     ksft_test_result_skip(fmt, ...);
 | 
				
			||||||
| 
						 | 
					@ -39,6 +41,7 @@
 | 
				
			||||||
 * the program is aborting before finishing all tests):
 | 
					 * the program is aborting before finishing all tests):
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *    ksft_exit_fail_msg(fmt, ...);
 | 
					 *    ksft_exit_fail_msg(fmt, ...);
 | 
				
			||||||
 | 
					 *    ksft_exit_fail_perror(msg);
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifndef __KSELFTEST_H
 | 
					#ifndef __KSELFTEST_H
 | 
				
			||||||
| 
						 | 
					@ -305,13 +308,34 @@ void ksft_test_result_code(int exit_code, const char *test_name,
 | 
				
			||||||
	printf("\n");
 | 
						printf("\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn int ksft_exit_pass(void)
 | 
					/**
 | 
				
			||||||
 | 
					 * ksft_test_result() - Report test success based on truth of condition
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @condition: if true, report test success, otherwise failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ksft_test_result_report(result, fmt, ...) do {		\
 | 
				
			||||||
 | 
						switch (result) {					\
 | 
				
			||||||
 | 
						case KSFT_PASS:						\
 | 
				
			||||||
 | 
							ksft_test_result_pass(fmt, ##__VA_ARGS__);	\
 | 
				
			||||||
 | 
							break;						\
 | 
				
			||||||
 | 
						case KSFT_FAIL:						\
 | 
				
			||||||
 | 
							ksft_test_result_fail(fmt, ##__VA_ARGS__);	\
 | 
				
			||||||
 | 
							break;						\
 | 
				
			||||||
 | 
						case KSFT_XFAIL:					\
 | 
				
			||||||
 | 
							ksft_test_result_xfail(fmt, ##__VA_ARGS__);	\
 | 
				
			||||||
 | 
							break;						\
 | 
				
			||||||
 | 
						case KSFT_SKIP:						\
 | 
				
			||||||
 | 
							ksft_test_result_skip(fmt, ##__VA_ARGS__);	\
 | 
				
			||||||
 | 
							break;						\
 | 
				
			||||||
 | 
						} } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline __noreturn void ksft_exit_pass(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ksft_print_cnts();
 | 
						ksft_print_cnts();
 | 
				
			||||||
	exit(KSFT_PASS);
 | 
						exit(KSFT_PASS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn int ksft_exit_fail(void)
 | 
					static inline __noreturn void ksft_exit_fail(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ksft_print_cnts();
 | 
						ksft_print_cnts();
 | 
				
			||||||
	exit(KSFT_FAIL);
 | 
						exit(KSFT_FAIL);
 | 
				
			||||||
| 
						 | 
					@ -338,7 +362,7 @@ static inline __noreturn int ksft_exit_fail(void)
 | 
				
			||||||
		  ksft_cnt.ksft_xfail +	\
 | 
							  ksft_cnt.ksft_xfail +	\
 | 
				
			||||||
		  ksft_cnt.ksft_xskip)
 | 
							  ksft_cnt.ksft_xskip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
 | 
					static inline __noreturn __printf(1, 2) void ksft_exit_fail_msg(const char *msg, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int saved_errno = errno;
 | 
						int saved_errno = errno;
 | 
				
			||||||
	va_list args;
 | 
						va_list args;
 | 
				
			||||||
| 
						 | 
					@ -353,19 +377,32 @@ static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg,
 | 
				
			||||||
	exit(KSFT_FAIL);
 | 
						exit(KSFT_FAIL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn int ksft_exit_xfail(void)
 | 
					static inline __noreturn void ksft_exit_fail_perror(const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef NOLIBC
 | 
				
			||||||
 | 
						ksft_exit_fail_msg("%s: %s (%d)\n", msg, strerror(errno), errno);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * nolibc doesn't provide strerror() and it seems
 | 
				
			||||||
 | 
						 * inappropriate to add one, just print the errno.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						ksft_exit_fail_msg("%s: %d)\n", msg, errno);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline __noreturn void ksft_exit_xfail(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ksft_print_cnts();
 | 
						ksft_print_cnts();
 | 
				
			||||||
	exit(KSFT_XFAIL);
 | 
						exit(KSFT_XFAIL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn int ksft_exit_xpass(void)
 | 
					static inline __noreturn void ksft_exit_xpass(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ksft_print_cnts();
 | 
						ksft_print_cnts();
 | 
				
			||||||
	exit(KSFT_XPASS);
 | 
						exit(KSFT_XPASS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
 | 
					static inline __noreturn __printf(1, 2) void ksft_exit_skip(const char *msg, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int saved_errno = errno;
 | 
						int saved_errno = errno;
 | 
				
			||||||
	va_list args;
 | 
						va_list args;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ __ktap_test() {
 | 
				
			||||||
	directive="$3" # optional
 | 
						directive="$3" # optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local directive_str=
 | 
						local directive_str=
 | 
				
			||||||
	[[ ! -z "$directive" ]] && directive_str="# $directive"
 | 
						[ ! -z "$directive" ] && directive_str="# $directive"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	echo $result $KTAP_TESTNO $description $directive_str
 | 
						echo $result $KTAP_TESTNO $description $directive_str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ ktap_exit_fail_msg() {
 | 
				
			||||||
ktap_finished() {
 | 
					ktap_finished() {
 | 
				
			||||||
	ktap_print_totals
 | 
						ktap_print_totals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if [ $(("$KTAP_CNT_PASS" + "$KTAP_CNT_SKIP")) -eq "$KSFT_NUM_TESTS" ]; then
 | 
						if [ $((KTAP_CNT_PASS + KTAP_CNT_SKIP)) -eq "$KSFT_NUM_TESTS" ]; then
 | 
				
			||||||
		exit "$KSFT_PASS"
 | 
							exit "$KSFT_PASS"
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		exit "$KSFT_FAIL"
 | 
							exit "$KSFT_FAIL"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,6 +244,7 @@ l4_test()
 | 
				
			||||||
l5_test()
 | 
					l5_test()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tests=$(find $(dirname "$test") -type f -name "*.mk")
 | 
						tests=$(find $(dirname "$test") -type f -name "*.mk")
 | 
				
			||||||
 | 
						[[ -z "${tests// }" ]] && return
 | 
				
			||||||
	test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \
 | 
						test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \
 | 
				
			||||||
			cut -d "=" -f 2)
 | 
								cut -d "=" -f 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@
 | 
				
			||||||
#define __KSELFTEST_HARNESS_H
 | 
					#define __KSELFTEST_HARNESS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _GNU_SOURCE
 | 
					#ifndef _GNU_SOURCE
 | 
				
			||||||
#define _GNU_SOURCE
 | 
					static_assert(0, "kselftest harness requires _GNU_SOURCE to be defined");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <asm/types.h>
 | 
					#include <asm/types.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,8 @@ else ifneq ($(filter -%,$(LLVM)),)
 | 
				
			||||||
LLVM_SUFFIX := $(LLVM)
 | 
					LLVM_SUFFIX := $(LLVM)
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CLANG := $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CLANG_TARGET_FLAGS_arm          := arm-linux-gnueabi
 | 
					CLANG_TARGET_FLAGS_arm          := arm-linux-gnueabi
 | 
				
			||||||
CLANG_TARGET_FLAGS_arm64        := aarch64-linux-gnu
 | 
					CLANG_TARGET_FLAGS_arm64        := aarch64-linux-gnu
 | 
				
			||||||
CLANG_TARGET_FLAGS_hexagon      := hexagon-linux-musl
 | 
					CLANG_TARGET_FLAGS_hexagon      := hexagon-linux-musl
 | 
				
			||||||
| 
						 | 
					@ -18,7 +20,13 @@ CLANG_TARGET_FLAGS_riscv        := riscv64-linux-gnu
 | 
				
			||||||
CLANG_TARGET_FLAGS_s390         := s390x-linux-gnu
 | 
					CLANG_TARGET_FLAGS_s390         := s390x-linux-gnu
 | 
				
			||||||
CLANG_TARGET_FLAGS_x86          := x86_64-linux-gnu
 | 
					CLANG_TARGET_FLAGS_x86          := x86_64-linux-gnu
 | 
				
			||||||
CLANG_TARGET_FLAGS_x86_64       := x86_64-linux-gnu
 | 
					CLANG_TARGET_FLAGS_x86_64       := x86_64-linux-gnu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Default to host architecture if ARCH is not explicitly given.
 | 
				
			||||||
 | 
					ifeq ($(ARCH),)
 | 
				
			||||||
 | 
					CLANG_TARGET_FLAGS := $(shell $(CLANG) -print-target-triple)
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
 | 
					CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(CROSS_COMPILE),)
 | 
					ifeq ($(CROSS_COMPILE),)
 | 
				
			||||||
ifeq ($(CLANG_TARGET_FLAGS),)
 | 
					ifeq ($(CLANG_TARGET_FLAGS),)
 | 
				
			||||||
| 
						 | 
					@ -30,7 +38,7 @@ else
 | 
				
			||||||
CLANG_FLAGS     += --target=$(notdir $(CROSS_COMPILE:%-=%))
 | 
					CLANG_FLAGS     += --target=$(notdir $(CROSS_COMPILE:%-=%))
 | 
				
			||||||
endif # CROSS_COMPILE
 | 
					endif # CROSS_COMPILE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as
 | 
					CC := $(CLANG) $(CLANG_FLAGS) -fintegrated-as
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
CC := $(CROSS_COMPILE)gcc
 | 
					CC := $(CROSS_COMPILE)gcc
 | 
				
			||||||
endif # LLVM
 | 
					endif # LLVM
 | 
				
			||||||
| 
						 | 
					@ -45,7 +53,7 @@ selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
 | 
				
			||||||
top_srcdir = $(selfdir)/../../..
 | 
					top_srcdir = $(selfdir)/../../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(KHDR_INCLUDES),)
 | 
					ifeq ($(KHDR_INCLUDES),)
 | 
				
			||||||
KHDR_INCLUDES := -isystem $(top_srcdir)/usr/include
 | 
					KHDR_INCLUDES := -D_GNU_SOURCE -isystem $(top_srcdir)/usr/include
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The following are built by lib.mk common compile rules.
 | 
					# The following are built by lib.mk common compile rules.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,5 +69,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	/* Multi-threaded */
 | 
						/* Multi-threaded */
 | 
				
			||||||
	test_mt_membarrier();
 | 
						test_mt_membarrier();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,5 +24,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_membarrier_get_registrations(/*cmd=*/0);
 | 
						test_membarrier_get_registrations(/*cmd=*/0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
	ksft_print_header();
 | 
						ksft_print_header();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (prereq() || geteuid())
 | 
						if (prereq() || geteuid())
 | 
				
			||||||
		return ksft_exit_skip("Prerequisites unsatisfied\n");
 | 
							ksft_exit_skip("Prerequisites unsatisfied\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_set_plan(1);
 | 
						ksft_set_plan(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -225,7 +225,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_compaction(mem_free, hugepage_size) == 0)
 | 
						if (check_compaction(mem_free, hugepage_size) == 0)
 | 
				
			||||||
		return ksft_exit_pass();
 | 
							ksft_exit_pass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_fail();
 | 
						ksft_exit_fail();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1779,5 +1779,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
				
			||||||
				   err, ksft_test_num());
 | 
									   err, ksft_test_num());
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,5 +456,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
				
			||||||
				   err, ksft_test_num());
 | 
									   err, ksft_test_num());
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,7 +228,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ksft_test_result_skip("Please run this test as root\n");
 | 
							ksft_test_result_skip("Please run this test as root\n");
 | 
				
			||||||
		return ksft_exit_pass();
 | 
							ksft_exit_pass();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, filed, 0);
 | 
						p = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, filed, 0);
 | 
				
			||||||
| 
						 | 
					@ -267,5 +267,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(tid);
 | 
						free(tid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -646,5 +646,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
				
			||||||
				   err, ksft_test_num());
 | 
									   err, ksft_test_num());
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,5 +307,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
				
			||||||
				   err, ksft_test_num());
 | 
									   err, ksft_test_num());
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -375,5 +375,5 @@ int main(void)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d tests failed\n",
 | 
				
			||||||
				   err, ksft_test_num());
 | 
									   err, ksft_test_num());
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1484,7 +1484,7 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	ksft_print_header();
 | 
						ksft_print_header();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (init_uffd())
 | 
						if (init_uffd())
 | 
				
			||||||
		return ksft_exit_pass();
 | 
							ksft_exit_pass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_set_plan(115);
 | 
						ksft_set_plan(115);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1660,5 +1660,5 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	userfaultfd_tests();
 | 
						userfaultfd_tests();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close(pagemap_fd);
 | 
						close(pagemap_fd);
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,5 +209,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close(pagemap_fd);
 | 
						close(pagemap_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,5 +307,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	test_pidfd_fdinfo_nspid();
 | 
						test_pidfd_fdinfo_nspid();
 | 
				
			||||||
	test_pidfd_dead_fdinfo();
 | 
						test_pidfd_dead_fdinfo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,5 +159,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
	if (pidfd >= 0)
 | 
						if (pidfd >= 0)
 | 
				
			||||||
		close(pidfd);
 | 
							close(pidfd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !ret ? ksft_exit_pass() : ksft_exit_fail();
 | 
						if (ret)
 | 
				
			||||||
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,5 +112,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_test_result_pass("pidfd poll test: pass\n");
 | 
						ksft_test_result_pass("pidfd poll test: pass\n");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -572,5 +572,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	test_pidfd_send_signal_exited_fail();
 | 
						test_pidfd_send_signal_exited_fail();
 | 
				
			||||||
	test_pidfd_send_signal_recycled_pid_fail();
 | 
						test_pidfd_send_signal_recycled_pid_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ count_tests() {
 | 
				
			||||||
	total_tests=0
 | 
						total_tests=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i in $SUPPLIES; do
 | 
						for i in $SUPPLIES; do
 | 
				
			||||||
		total_tests=$(("$total_tests" + "$NUM_TESTS"))
 | 
							total_tests=$((total_tests + NUM_TESTS))
 | 
				
			||||||
	done
 | 
						done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	echo "$total_tests"
 | 
						echo "$total_tests"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,8 @@ CFLAGS += $(KHDR_INCLUDES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_GEN_PROGS := resctrl_tests
 | 
					TEST_GEN_PROGS := resctrl_tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCAL_HDRS += $(wildcard *.h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ../lib.mk
 | 
					include ../lib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(OUTPUT)/resctrl_tests: $(wildcard *.[ch])
 | 
					$(OUTPUT)/resctrl_tests: $(wildcard *.c)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ static int check_results(struct resctrl_val_param *param, const char *cache_type
 | 
				
			||||||
	return fail;
 | 
						return fail;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cat_test_cleanup(void)
 | 
					static void cat_test_cleanup(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	remove(RESULT_FILE_NAME);
 | 
						remove(RESULT_FILE_NAME);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -284,13 +284,10 @@ static int cat_run_test(const struct resctrl_test *test, const struct user_param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = cat_test(test, uparams, ¶m, span, start_mask);
 | 
						ret = cat_test(test, uparams, ¶m, span, start_mask);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = check_results(¶m, test->resource,
 | 
						ret = check_results(¶m, test->resource,
 | 
				
			||||||
			    cache_total_size, full_cache_mask, start_mask);
 | 
								    cache_total_size, full_cache_mask, start_mask);
 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	cat_test_cleanup();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -373,6 +370,7 @@ struct resctrl_test l3_cat_test = {
 | 
				
			||||||
	.resource = "L3",
 | 
						.resource = "L3",
 | 
				
			||||||
	.feature_check = test_resource_feature_check,
 | 
						.feature_check = test_resource_feature_check,
 | 
				
			||||||
	.run_test = cat_run_test,
 | 
						.run_test = cat_run_test,
 | 
				
			||||||
 | 
						.cleanup = cat_test_cleanup,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct resctrl_test l3_noncont_cat_test = {
 | 
					struct resctrl_test l3_noncont_cat_test = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,11 +40,11 @@ static int show_results_info(unsigned long sum_llc_val, int no_of_bits,
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	avg_llc_val = sum_llc_val / num_of_runs;
 | 
						avg_llc_val = sum_llc_val / num_of_runs;
 | 
				
			||||||
	avg_diff = (long)abs(cache_span - avg_llc_val);
 | 
						avg_diff = (long)(cache_span - avg_llc_val);
 | 
				
			||||||
	diff_percent = ((float)cache_span - avg_llc_val) / cache_span * 100;
 | 
						diff_percent = ((float)cache_span - avg_llc_val) / cache_span * 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = platform && abs((int)diff_percent) > max_diff_percent &&
 | 
						ret = platform && abs((int)diff_percent) > max_diff_percent &&
 | 
				
			||||||
	      abs(avg_diff) > max_diff;
 | 
						      labs(avg_diff) > max_diff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_print_msg("%s Check cache miss rate within %lu%%\n",
 | 
						ksft_print_msg("%s Check cache miss rate within %lu%%\n",
 | 
				
			||||||
		       ret ? "Fail:" : "Pass:", max_diff_percent);
 | 
							       ret ? "Fail:" : "Pass:", max_diff_percent);
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ static int check_results(struct resctrl_val_param *param, size_t span, int no_of
 | 
				
			||||||
				 MAX_DIFF, MAX_DIFF_PERCENT, runs - 1, true);
 | 
									 MAX_DIFF, MAX_DIFF_PERCENT, runs - 1, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmt_test_cleanup(void)
 | 
					static void cmt_test_cleanup(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	remove(RESULT_FILE_NAME);
 | 
						remove(RESULT_FILE_NAME);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -161,7 +161,6 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param
 | 
				
			||||||
		ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
 | 
							ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	cmt_test_cleanup();
 | 
					 | 
				
			||||||
	free(span_str);
 | 
						free(span_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -178,4 +177,5 @@ struct resctrl_test cmt_test = {
 | 
				
			||||||
	.resource = "L3",
 | 
						.resource = "L3",
 | 
				
			||||||
	.feature_check = cmt_feature_check,
 | 
						.feature_check = cmt_feature_check,
 | 
				
			||||||
	.run_test = cmt_run_test,
 | 
						.run_test = cmt_run_test,
 | 
				
			||||||
 | 
						.cleanup = cmt_test_cleanup,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,8 +60,8 @@ static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
 | 
				
			||||||
	/* Memory bandwidth from 100% down to 10% */
 | 
						/* Memory bandwidth from 100% down to 10% */
 | 
				
			||||||
	for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
 | 
						for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
 | 
				
			||||||
	     allocation++) {
 | 
						     allocation++) {
 | 
				
			||||||
		unsigned long avg_bw_imc, avg_bw_resc;
 | 
					 | 
				
			||||||
		unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
 | 
							unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
 | 
				
			||||||
 | 
							long avg_bw_imc, avg_bw_resc;
 | 
				
			||||||
		int avg_diff_per;
 | 
							int avg_diff_per;
 | 
				
			||||||
		float avg_diff;
 | 
							float avg_diff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,7 +137,7 @@ static int check_results(void)
 | 
				
			||||||
	return show_mba_info(bw_imc, bw_resc);
 | 
						return show_mba_info(bw_imc, bw_resc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mba_test_cleanup(void)
 | 
					static void mba_test_cleanup(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	remove(RESULT_FILE_NAME);
 | 
						remove(RESULT_FILE_NAME);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -158,13 +158,10 @@ static int mba_run_test(const struct resctrl_test *test, const struct user_param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = resctrl_val(test, uparams, uparams->benchmark_cmd, ¶m);
 | 
						ret = resctrl_val(test, uparams, uparams->benchmark_cmd, ¶m);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = check_results();
 | 
						ret = check_results();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	mba_test_cleanup();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,4 +177,5 @@ struct resctrl_test mba_test = {
 | 
				
			||||||
	.vendor_specific = ARCH_INTEL,
 | 
						.vendor_specific = ARCH_INTEL,
 | 
				
			||||||
	.feature_check = mba_feature_check,
 | 
						.feature_check = mba_feature_check,
 | 
				
			||||||
	.run_test = mba_run_test,
 | 
						.run_test = mba_run_test,
 | 
				
			||||||
 | 
						.cleanup = mba_test_cleanup,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,8 +17,8 @@
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
show_bw_info(unsigned long *bw_imc, unsigned long *bw_resc, size_t span)
 | 
					show_bw_info(unsigned long *bw_imc, unsigned long *bw_resc, size_t span)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long avg_bw_imc = 0, avg_bw_resc = 0;
 | 
					 | 
				
			||||||
	unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
 | 
						unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
 | 
				
			||||||
 | 
						long avg_bw_imc = 0, avg_bw_resc = 0;
 | 
				
			||||||
	int runs, ret, avg_diff_per;
 | 
						int runs, ret, avg_diff_per;
 | 
				
			||||||
	float avg_diff = 0;
 | 
						float avg_diff = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ static int mbm_setup(const struct resctrl_test *test,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mbm_test_cleanup(void)
 | 
					static void mbm_test_cleanup(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	remove(RESULT_FILE_NAME);
 | 
						remove(RESULT_FILE_NAME);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -126,15 +126,12 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = resctrl_val(test, uparams, uparams->benchmark_cmd, ¶m);
 | 
						ret = resctrl_val(test, uparams, uparams->benchmark_cmd, ¶m);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = check_results(DEFAULT_SPAN);
 | 
						ret = check_results(DEFAULT_SPAN);
 | 
				
			||||||
	if (ret && (get_vendor() == ARCH_INTEL))
 | 
						if (ret && (get_vendor() == ARCH_INTEL))
 | 
				
			||||||
		ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
 | 
							ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	mbm_test_cleanup();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,4 +147,5 @@ struct resctrl_test mbm_test = {
 | 
				
			||||||
	.vendor_specific = ARCH_INTEL,
 | 
						.vendor_specific = ARCH_INTEL,
 | 
				
			||||||
	.feature_check = mbm_feature_check,
 | 
						.feature_check = mbm_feature_check,
 | 
				
			||||||
	.run_test = mbm_run_test,
 | 
						.run_test = mbm_run_test,
 | 
				
			||||||
 | 
						.cleanup = mbm_test_cleanup,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,6 +72,7 @@ struct user_params {
 | 
				
			||||||
 * @disabled:		Test is disabled
 | 
					 * @disabled:		Test is disabled
 | 
				
			||||||
 * @feature_check:	Callback to check required resctrl features
 | 
					 * @feature_check:	Callback to check required resctrl features
 | 
				
			||||||
 * @run_test:		Callback to run the test
 | 
					 * @run_test:		Callback to run the test
 | 
				
			||||||
 | 
					 * @cleanup:		Callback to cleanup after the test
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct resctrl_test {
 | 
					struct resctrl_test {
 | 
				
			||||||
	const char	*name;
 | 
						const char	*name;
 | 
				
			||||||
| 
						 | 
					@ -82,6 +83,7 @@ struct resctrl_test {
 | 
				
			||||||
	bool		(*feature_check)(const struct resctrl_test *test);
 | 
						bool		(*feature_check)(const struct resctrl_test *test);
 | 
				
			||||||
	int		(*run_test)(const struct resctrl_test *test,
 | 
						int		(*run_test)(const struct resctrl_test *test,
 | 
				
			||||||
				    const struct user_params *uparams);
 | 
									    const struct user_params *uparams);
 | 
				
			||||||
 | 
						void		(*cleanup)(void);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -156,9 +158,6 @@ int resctrl_val(const struct resctrl_test *test,
 | 
				
			||||||
		const struct user_params *uparams,
 | 
							const struct user_params *uparams,
 | 
				
			||||||
		const char * const *benchmark_cmd,
 | 
							const char * const *benchmark_cmd,
 | 
				
			||||||
		struct resctrl_val_param *param);
 | 
							struct resctrl_val_param *param);
 | 
				
			||||||
void tests_cleanup(void);
 | 
					 | 
				
			||||||
void mbm_test_cleanup(void);
 | 
					 | 
				
			||||||
void mba_test_cleanup(void);
 | 
					 | 
				
			||||||
unsigned long create_bit_mask(unsigned int start, unsigned int len);
 | 
					unsigned long create_bit_mask(unsigned int start, unsigned int len);
 | 
				
			||||||
unsigned int count_contiguous_bits(unsigned long val, unsigned int *start);
 | 
					unsigned int count_contiguous_bits(unsigned long val, unsigned int *start);
 | 
				
			||||||
int get_full_cbm(const char *cache_type, unsigned long *mask);
 | 
					int get_full_cbm(const char *cache_type, unsigned long *mask);
 | 
				
			||||||
| 
						 | 
					@ -166,11 +165,9 @@ int get_mask_no_shareable(const char *cache_type, unsigned long *mask);
 | 
				
			||||||
int get_cache_size(int cpu_no, const char *cache_type, unsigned long *cache_size);
 | 
					int get_cache_size(int cpu_no, const char *cache_type, unsigned long *cache_size);
 | 
				
			||||||
int resource_info_unsigned_get(const char *resource, const char *filename, unsigned int *val);
 | 
					int resource_info_unsigned_get(const char *resource, const char *filename, unsigned int *val);
 | 
				
			||||||
void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
 | 
					void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
 | 
				
			||||||
int signal_handler_register(void);
 | 
					int signal_handler_register(const struct resctrl_test *test);
 | 
				
			||||||
void signal_handler_unregister(void);
 | 
					void signal_handler_unregister(void);
 | 
				
			||||||
void cat_test_cleanup(void);
 | 
					 | 
				
			||||||
unsigned int count_bits(unsigned long n);
 | 
					unsigned int count_bits(unsigned long n);
 | 
				
			||||||
void cmt_test_cleanup(void);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config);
 | 
					void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config);
 | 
				
			||||||
void perf_event_initialize_read_format(struct perf_event_read *pe_read);
 | 
					void perf_event_initialize_read_format(struct perf_event_read *pe_read);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,19 +81,11 @@ static void cmd_help(void)
 | 
				
			||||||
	printf("\t-h: help\n");
 | 
						printf("\t-h: help\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void tests_cleanup(void)
 | 
					static int test_prepare(const struct resctrl_test *test)
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	mbm_test_cleanup();
 | 
					 | 
				
			||||||
	mba_test_cleanup();
 | 
					 | 
				
			||||||
	cmt_test_cleanup();
 | 
					 | 
				
			||||||
	cat_test_cleanup();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int test_prepare(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res = signal_handler_register();
 | 
						res = signal_handler_register(test);
 | 
				
			||||||
	if (res) {
 | 
						if (res) {
 | 
				
			||||||
		ksft_print_msg("Failed to register signal handler\n");
 | 
							ksft_print_msg("Failed to register signal handler\n");
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
| 
						 | 
					@ -108,8 +100,10 @@ static int test_prepare(void)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_cleanup(void)
 | 
					static void test_cleanup(const struct resctrl_test *test)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (test->cleanup)
 | 
				
			||||||
 | 
							test->cleanup();
 | 
				
			||||||
	umount_resctrlfs();
 | 
						umount_resctrlfs();
 | 
				
			||||||
	signal_handler_unregister();
 | 
						signal_handler_unregister();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -136,7 +130,7 @@ static void run_single_test(const struct resctrl_test *test, const struct user_p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_print_msg("Starting %s test ...\n", test->name);
 | 
						ksft_print_msg("Starting %s test ...\n", test->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (test_prepare()) {
 | 
						if (test_prepare(test)) {
 | 
				
			||||||
		ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
 | 
							ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -151,7 +145,7 @@ static void run_single_test(const struct resctrl_test *test, const struct user_p
 | 
				
			||||||
	ksft_test_result(!ret, "%s: test\n", test->name);
 | 
						ksft_test_result(!ret, "%s: test\n", test->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cleanup:
 | 
					cleanup:
 | 
				
			||||||
	test_cleanup();
 | 
						test_cleanup(test);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_user_params(struct user_params *uparams)
 | 
					static void init_user_params(struct user_params *uparams)
 | 
				
			||||||
| 
						 | 
					@ -253,13 +247,13 @@ int main(int argc, char **argv)
 | 
				
			||||||
	 * 2. We execute perf commands
 | 
						 * 2. We execute perf commands
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (geteuid() != 0)
 | 
						if (geteuid() != 0)
 | 
				
			||||||
		return ksft_exit_skip("Not running as root. Skipping...\n");
 | 
							ksft_exit_skip("Not running as root. Skipping...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!check_resctrlfs_support())
 | 
						if (!check_resctrlfs_support())
 | 
				
			||||||
		return ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n");
 | 
							ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (umount_resctrlfs())
 | 
						if (umount_resctrlfs())
 | 
				
			||||||
		return ksft_exit_skip("resctrl FS unmount failed.\n");
 | 
							ksft_exit_skip("resctrl FS unmount failed.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filter_dmesg();
 | 
						filter_dmesg();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,7 @@ struct imc_counter_config {
 | 
				
			||||||
static char mbm_total_path[1024];
 | 
					static char mbm_total_path[1024];
 | 
				
			||||||
static int imcs;
 | 
					static int imcs;
 | 
				
			||||||
static struct imc_counter_config imc_counters_config[MAX_IMCS][2];
 | 
					static struct imc_counter_config imc_counters_config[MAX_IMCS][2];
 | 
				
			||||||
 | 
					static const struct resctrl_test *current_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void membw_initialize_perf_event_attr(int i, int j)
 | 
					void membw_initialize_perf_event_attr(int i, int j)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -472,7 +473,8 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
 | 
				
			||||||
	if (bm_pid)
 | 
						if (bm_pid)
 | 
				
			||||||
		kill(bm_pid, SIGKILL);
 | 
							kill(bm_pid, SIGKILL);
 | 
				
			||||||
	umount_resctrlfs();
 | 
						umount_resctrlfs();
 | 
				
			||||||
	tests_cleanup();
 | 
						if (current_test && current_test->cleanup)
 | 
				
			||||||
 | 
							current_test->cleanup();
 | 
				
			||||||
	ksft_print_msg("Ending\n\n");
 | 
						ksft_print_msg("Ending\n\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exit(EXIT_SUCCESS);
 | 
						exit(EXIT_SUCCESS);
 | 
				
			||||||
| 
						 | 
					@ -482,13 +484,14 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
 | 
				
			||||||
 * Register CTRL-C handler for parent, as it has to kill
 | 
					 * Register CTRL-C handler for parent, as it has to kill
 | 
				
			||||||
 * child process before exiting.
 | 
					 * child process before exiting.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int signal_handler_register(void)
 | 
					int signal_handler_register(const struct resctrl_test *test)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sigaction sigact = {};
 | 
						struct sigaction sigact = {};
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bm_pid = 0;
 | 
						bm_pid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_test = test;
 | 
				
			||||||
	sigact.sa_sigaction = ctrlc_handler;
 | 
						sigact.sa_sigaction = ctrlc_handler;
 | 
				
			||||||
	sigemptyset(&sigact.sa_mask);
 | 
						sigemptyset(&sigact.sa_mask);
 | 
				
			||||||
	sigact.sa_flags = SA_SIGINFO;
 | 
						sigact.sa_flags = SA_SIGINFO;
 | 
				
			||||||
| 
						 | 
					@ -510,6 +513,7 @@ void signal_handler_unregister(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sigaction sigact = {};
 | 
						struct sigaction sigact = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_test = NULL;
 | 
				
			||||||
	sigact.sa_handler = SIG_DFL;
 | 
						sigact.sa_handler = SIG_DFL;
 | 
				
			||||||
	sigemptyset(&sigact.sa_mask);
 | 
						sigemptyset(&sigact.sa_mask);
 | 
				
			||||||
	if (sigaction(SIGINT, &sigact, NULL) ||
 | 
						if (sigaction(SIGINT, &sigact, NULL) ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INCLUDES := -I$(top_srcdir)/tools/include
 | 
					INCLUDES := -I$(top_srcdir)/tools/include
 | 
				
			||||||
HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC
 | 
					HOST_CFLAGS := -Wall -Werror $(KHDR_INCLUDES) -g $(INCLUDES) -fPIC
 | 
				
			||||||
HOST_LDFLAGS := -z noexecstack -lcrypto
 | 
					HOST_LDFLAGS := -z noexecstack -lcrypto
 | 
				
			||||||
ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \
 | 
					ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \
 | 
				
			||||||
	       -fno-stack-protector -mrdrnd $(INCLUDES)
 | 
						       -fno-stack-protector -mrdrnd $(INCLUDES)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0
 | 
					// SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
/*  Copyright(c) 2016-20 Intel Corporation. */
 | 
					/*  Copyright(c) 2016-20 Intel Corporation. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _GNU_SOURCE
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <getopt.h>
 | 
					#include <getopt.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +109,5 @@ int main(void)
 | 
				
			||||||
		ksft_exit_fail_msg("%d out of %d sync tests failed\n",
 | 
							ksft_exit_fail_msg("%d out of %d sync tests failed\n",
 | 
				
			||||||
					err, ksft_test_num());
 | 
										err, ksft_test_num());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* need this return to keep gcc happy */
 | 
						ksft_exit_pass();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,7 +205,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
	adjtimex(&tx1);
 | 
						adjtimex(&tx1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,6 +173,6 @@ int main(void)
 | 
				
			||||||
		timer_delete(tm1);
 | 
							timer_delete(tm1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (final_ret)
 | 
						if (final_ret)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,8 +89,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		printf("[FAIL]");
 | 
							printf("[FAIL]");
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("[OK]");
 | 
						printf("[OK]");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,7 +257,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
	set_frequency(0.0);
 | 
						set_frequency(0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fails)
 | 
						if (fails)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,7 +268,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
 | 
								printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
 | 
				
			||||||
							time_state_str(ret));
 | 
												time_state_str(ret));
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Validate STA_INS was set */
 | 
							/* Validate STA_INS was set */
 | 
				
			||||||
| 
						 | 
					@ -277,7 +277,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
		if (tx.status != STA_INS && tx.status != STA_DEL) {
 | 
							if (tx.status != STA_INS && tx.status != STA_DEL) {
 | 
				
			||||||
			printf("Error: STA_INS/STA_DEL not set!: %s\n",
 | 
								printf("Error: STA_INS/STA_DEL not set!: %s\n",
 | 
				
			||||||
							time_state_str(ret));
 | 
												time_state_str(ret));
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tai_time) {
 | 
							if (tai_time) {
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
		se.sigev_value.sival_int = 0;
 | 
							se.sigev_value.sival_int = 0;
 | 
				
			||||||
		if (timer_create(CLOCK_REALTIME, &se, &tm1) == -1) {
 | 
							if (timer_create(CLOCK_REALTIME, &se, &tm1) == -1) {
 | 
				
			||||||
			printf("Error: timer_create failed\n");
 | 
								printf("Error: timer_create failed\n");
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		its1.it_value.tv_sec = next_leap;
 | 
							its1.it_value.tv_sec = next_leap;
 | 
				
			||||||
		its1.it_value.tv_nsec = 0;
 | 
							its1.it_value.tv_nsec = 0;
 | 
				
			||||||
| 
						 | 
					@ -366,7 +366,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
		if (error_found) {
 | 
							if (error_found) {
 | 
				
			||||||
			printf("Errors observed\n");
 | 
								printf("Errors observed\n");
 | 
				
			||||||
			clear_time_state();
 | 
								clear_time_state();
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		printf("\n");
 | 
							printf("\n");
 | 
				
			||||||
		if ((iterations != -1) && !(--iterations))
 | 
							if ((iterations != -1) && !(--iterations))
 | 
				
			||||||
| 
						 | 
					@ -374,5 +374,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clear_time_state();
 | 
						clear_time_state();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ int main(void)
 | 
				
			||||||
		tv.tv_usec = 0;
 | 
							tv.tv_usec = 0;
 | 
				
			||||||
		if (settimeofday(&tv, NULL)) {
 | 
							if (settimeofday(&tv, NULL)) {
 | 
				
			||||||
			printf("Error: You're likely not running with proper (ie: root) permissions\n");
 | 
								printf("Error: You're likely not running with proper (ie: root) permissions\n");
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		tx.modes = 0;
 | 
							tx.modes = 0;
 | 
				
			||||||
		adjtimex(&tx);
 | 
							adjtimex(&tx);
 | 
				
			||||||
| 
						 | 
					@ -104,5 +104,5 @@ int main(void)
 | 
				
			||||||
		fflush(stdout);
 | 
							fflush(stdout);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("[OK]\n");
 | 
						printf("[OK]\n");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,8 +107,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
	ret = mqueue_lat_test();
 | 
						ret = mqueue_lat_test();
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		printf("[FAILED]\n");
 | 
							printf("[FAILED]\n");
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("[OK]\n");
 | 
						printf("[OK]\n");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,16 +260,16 @@ int main(int argc, char **argv)
 | 
				
			||||||
	ksft_print_msg("based timers if other threads run on the CPU...\n");
 | 
						ksft_print_msg("based timers if other threads run on the CPU...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_itimer(ITIMER_VIRTUAL) < 0)
 | 
						if (check_itimer(ITIMER_VIRTUAL) < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_itimer(ITIMER_PROF) < 0)
 | 
						if (check_itimer(ITIMER_PROF) < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_itimer(ITIMER_REAL) < 0)
 | 
						if (check_itimer(ITIMER_REAL) < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0)
 | 
						if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * It's unfortunately hard to reliably test a timer expiration
 | 
						 * It's unfortunately hard to reliably test a timer expiration
 | 
				
			||||||
| 
						 | 
					@ -281,10 +281,10 @@ int main(int argc, char **argv)
 | 
				
			||||||
	 * find a better solution.
 | 
						 * find a better solution.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
 | 
						if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_timer_distribution() < 0)
 | 
						if (check_timer_distribution() < 0)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_finished();
 | 
						ksft_finished();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,11 +137,11 @@ int main(int argc, char **argv)
 | 
				
			||||||
		if (tx1.offset || tx2.offset ||
 | 
							if (tx1.offset || tx2.offset ||
 | 
				
			||||||
		    tx1.freq != tx2.freq || tx1.tick != tx2.tick) {
 | 
							    tx1.freq != tx2.freq || tx1.tick != tx2.tick) {
 | 
				
			||||||
			printf("	[SKIP]\n");
 | 
								printf("	[SKIP]\n");
 | 
				
			||||||
			return ksft_exit_skip("The clock was adjusted externally. Shutdown NTPd or other time sync daemons\n");
 | 
								ksft_exit_skip("The clock was adjusted externally. Shutdown NTPd or other time sync daemons\n");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		printf("	[FAILED]\n");
 | 
							printf("	[FAILED]\n");
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("	[OK]\n");
 | 
						printf("	[OK]\n");
 | 
				
			||||||
	return  ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,6 +128,6 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	/* restore clock */
 | 
						/* restore clock */
 | 
				
			||||||
	settime(start);
 | 
						settime(start);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,9 +61,9 @@ int main(int argc, char **argv)
 | 
				
			||||||
		ret = get_tai();
 | 
							ret = get_tai();
 | 
				
			||||||
		if (ret != i) {
 | 
							if (ret != i) {
 | 
				
			||||||
			printf("[FAILED] expected: %i got %i\n", i, ret);
 | 
								printf("[FAILED] expected: %i got %i\n", i, ret);
 | 
				
			||||||
			return ksft_exit_fail();
 | 
								ksft_exit_fail();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("[OK]\n");
 | 
						printf("[OK]\n");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -278,6 +278,6 @@ int main(void)
 | 
				
			||||||
		ret |= do_timer_oneshot(clock_id, 0);
 | 
							ret |= do_timer_oneshot(clock_id, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,9 +102,9 @@ int main(int argc, char **argv)
 | 
				
			||||||
	printf("[OK]\n");
 | 
						printf("[OK]\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_tz(min, dst);
 | 
						set_tz(min, dst);
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	set_tz(min, dst);
 | 
						set_tz(min, dst);
 | 
				
			||||||
	return ksft_exit_fail();
 | 
						ksft_exit_fail();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,8 +70,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		printf("[FAILED]\n");
 | 
							printf("[FAILED]\n");
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("[OK]\n");
 | 
						printf("[OK]\n");
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -189,5 +189,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
	/* die */
 | 
						/* die */
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,10 +320,10 @@ int validate_set_offset(void)
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (validate_freq())
 | 
						if (validate_freq())
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (validate_set_offset())
 | 
						if (validate_set_offset())
 | 
				
			||||||
		return ksft_exit_fail();
 | 
							ksft_exit_fail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,42 +47,60 @@ int main(int argc, char **argv)
 | 
				
			||||||
	int r;
 | 
						int r;
 | 
				
			||||||
	char tty[PATH_MAX] = {};
 | 
						char tty[PATH_MAX] = {};
 | 
				
			||||||
	struct stat st1, st2;
 | 
						struct stat st1, st2;
 | 
				
			||||||
 | 
						int result = KSFT_FAIL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_print_header();
 | 
						ksft_print_header();
 | 
				
			||||||
	ksft_set_plan(1);
 | 
						ksft_set_plan(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = readlink("/proc/self/fd/0", tty, PATH_MAX);
 | 
						r = readlink("/proc/self/fd/0", tty, PATH_MAX);
 | 
				
			||||||
	if (r < 0)
 | 
						if (r < 0) {
 | 
				
			||||||
		ksft_exit_fail_msg("readlink on /proc/self/fd/0 failed: %m\n");
 | 
							ksft_print_msg("readlink on /proc/self/fd/0 failed: %m\n");
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!tty_valid(tty))
 | 
						if (!tty_valid(tty)) {
 | 
				
			||||||
		ksft_exit_skip("invalid tty path '%s'\n", tty);
 | 
							ksft_print_msg("invalid tty path '%s'\n", tty);
 | 
				
			||||||
 | 
							result = KSFT_SKIP;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = stat(tty, &st1);
 | 
						r = stat(tty, &st1);
 | 
				
			||||||
	if (r < 0)
 | 
						if (r < 0) {
 | 
				
			||||||
		ksft_exit_fail_msg("stat failed on tty path '%s': %m\n", tty);
 | 
							ksft_print_msg("stat failed on tty path '%s': %m\n", tty);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We need to wait at least 8 seconds in order to observe timestamp change */
 | 
						/* We need to wait at least 8 seconds in order to observe timestamp change */
 | 
				
			||||||
	/* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fbf47635315ab308c9b58a1ea0906e711a9228de */
 | 
						/* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fbf47635315ab308c9b58a1ea0906e711a9228de */
 | 
				
			||||||
	sleep(10);
 | 
						sleep(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = write_dev_tty();
 | 
						r = write_dev_tty();
 | 
				
			||||||
	if (r < 0)
 | 
						if (r < 0) {
 | 
				
			||||||
		ksft_exit_fail_msg("failed to write to /dev/tty: %s\n",
 | 
							ksft_print_msg("failed to write to /dev/tty: %s\n",
 | 
				
			||||||
			       strerror(-r));
 | 
								       strerror(-r));
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = stat(tty, &st2);
 | 
						r = stat(tty, &st2);
 | 
				
			||||||
	if (r < 0)
 | 
						if (r < 0) {
 | 
				
			||||||
		ksft_exit_fail_msg("stat failed on tty path '%s': %m\n", tty);
 | 
							ksft_print_msg("stat failed on tty path '%s': %m\n", tty);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We wrote to the terminal so timestamps should have been updated */
 | 
						/* We wrote to the terminal so timestamps should have been updated */
 | 
				
			||||||
	if (st1.st_atim.tv_sec == st2.st_atim.tv_sec &&
 | 
						if (st1.st_atim.tv_sec == st2.st_atim.tv_sec &&
 | 
				
			||||||
	    st1.st_mtim.tv_sec == st2.st_mtim.tv_sec) {
 | 
						    st1.st_mtim.tv_sec == st2.st_mtim.tv_sec) {
 | 
				
			||||||
		ksft_test_result_fail("tty timestamps not updated\n");
 | 
							ksft_print_msg("tty timestamps not updated\n");
 | 
				
			||||||
		ksft_exit_fail();
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_test_result_pass(
 | 
						ksft_print_msg(
 | 
				
			||||||
		"timestamps of terminal '%s' updated after write to /dev/tty\n", tty);
 | 
							"timestamps of terminal '%s' updated after write to /dev/tty\n", tty);
 | 
				
			||||||
	return EXIT_SUCCESS;
 | 
						result = KSFT_PASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						ksft_test_result_report(result, "tty_tstamp_update\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_finished();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1237,5 +1237,5 @@ int main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ksft_set_plan(tests_cnt);
 | 
						ksft_set_plan(tests_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ksft_exit_pass();
 | 
						ksft_exit_pass();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@
 | 
				
			||||||
#include <sys/auxv.h>
 | 
					#include <sys/auxv.h>
 | 
				
			||||||
#include <sys/syscall.h>
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
 | 
					#include "../kselftest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PAGE_SIZE	4096
 | 
					#define PAGE_SIZE	4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,11 +30,11 @@ static int try_to_remap(void *vdso_addr, unsigned long size)
 | 
				
			||||||
	/* Searching for memory location where to remap */
 | 
						/* Searching for memory location where to remap */
 | 
				
			||||||
	dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
 | 
						dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
 | 
				
			||||||
	if (dest_addr == MAP_FAILED) {
 | 
						if (dest_addr == MAP_FAILED) {
 | 
				
			||||||
		printf("[WARN]\tmmap failed (%d): %m\n", errno);
 | 
							ksft_print_msg("WARN: mmap failed (%d): %m\n", errno);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
 | 
						ksft_print_msg("Moving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
 | 
				
			||||||
		       vdso_addr, (unsigned long)vdso_addr + size,
 | 
							       vdso_addr, (unsigned long)vdso_addr + size,
 | 
				
			||||||
		       dest_addr, (unsigned long)dest_addr + size);
 | 
							       dest_addr, (unsigned long)dest_addr + size);
 | 
				
			||||||
	fflush(stdout);
 | 
						fflush(stdout);
 | 
				
			||||||
| 
						 | 
					@ -43,10 +44,10 @@ static int try_to_remap(void *vdso_addr, unsigned long size)
 | 
				
			||||||
	if ((unsigned long)new_addr == (unsigned long)-1) {
 | 
						if ((unsigned long)new_addr == (unsigned long)-1) {
 | 
				
			||||||
		munmap(dest_addr, size);
 | 
							munmap(dest_addr, size);
 | 
				
			||||||
		if (errno == EINVAL) {
 | 
							if (errno == EINVAL) {
 | 
				
			||||||
			printf("[NOTE]\tvDSO partial move failed, will try with bigger size\n");
 | 
								ksft_print_msg("vDSO partial move failed, will try with bigger size\n");
 | 
				
			||||||
			return -1; /* Retry with larger */
 | 
								return -1; /* Retry with larger */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		printf("[FAIL]\tmremap failed (%d): %m\n", errno);
 | 
							ksft_print_msg("[FAIL]\tmremap failed (%d): %m\n", errno);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,11 +59,12 @@ int main(int argc, char **argv, char **envp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pid_t child;
 | 
						pid_t child;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_header();
 | 
				
			||||||
 | 
						ksft_set_plan(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	child = fork();
 | 
						child = fork();
 | 
				
			||||||
	if (child == -1) {
 | 
						if (child == -1)
 | 
				
			||||||
		printf("[WARN]\tfailed to fork (%d): %m\n", errno);
 | 
							ksft_exit_fail_msg("failed to fork (%d): %m\n", errno);
 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (child == 0) {
 | 
						if (child == 0) {
 | 
				
			||||||
		unsigned long vdso_size = PAGE_SIZE;
 | 
							unsigned long vdso_size = PAGE_SIZE;
 | 
				
			||||||
| 
						 | 
					@ -70,9 +72,9 @@ int main(int argc, char **argv, char **envp)
 | 
				
			||||||
		int ret = -1;
 | 
							int ret = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auxval = getauxval(AT_SYSINFO_EHDR);
 | 
							auxval = getauxval(AT_SYSINFO_EHDR);
 | 
				
			||||||
		printf("\tAT_SYSINFO_EHDR is %#lx\n", auxval);
 | 
							ksft_print_msg("AT_SYSINFO_EHDR is %#lx\n", auxval);
 | 
				
			||||||
		if (!auxval || auxval == -ENOENT) {
 | 
							if (!auxval || auxval == -ENOENT) {
 | 
				
			||||||
			printf("[WARN]\tgetauxval failed\n");
 | 
								ksft_print_msg("WARN: getauxval failed\n");
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,16 +94,13 @@ int main(int argc, char **argv, char **envp)
 | 
				
			||||||
		int status;
 | 
							int status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (waitpid(child, &status, 0) != child ||
 | 
							if (waitpid(child, &status, 0) != child ||
 | 
				
			||||||
			!WIFEXITED(status)) {
 | 
								!WIFEXITED(status))
 | 
				
			||||||
			printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n");
 | 
								ksft_test_result_fail("mremap() of the vDSO does not work on this kernel!\n");
 | 
				
			||||||
			return 1;
 | 
							else if (WEXITSTATUS(status) != 0)
 | 
				
			||||||
		} else if (WEXITSTATUS(status) != 0) {
 | 
								ksft_test_result_fail("Child failed with %d\n", WEXITSTATUS(status));
 | 
				
			||||||
			printf("[FAIL]\tChild failed with %d\n",
 | 
							else
 | 
				
			||||||
					WEXITSTATUS(status));
 | 
								ksft_test_result_pass("%s\n", __func__);
 | 
				
			||||||
			return 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		printf("[OK]\n");
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						ksft_finished();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,13 @@
 | 
				
			||||||
#include <sys/uio.h>
 | 
					#include <sys/uio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "helpers.h"
 | 
					#include "helpers.h"
 | 
				
			||||||
 | 
					#include "../kselftest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __x86_64__
 | 
				
			||||||
 | 
					#define TOTAL_TESTS 13
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define TOTAL_TESTS 8
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __x86_64__
 | 
					#ifdef __x86_64__
 | 
				
			||||||
# define VSYS(x) (x)
 | 
					# define VSYS(x) (x)
 | 
				
			||||||
| 
						 | 
					@ -39,18 +46,6 @@
 | 
				
			||||||
/* max length of lines in /proc/self/maps - anything longer is skipped here */
 | 
					/* max length of lines in /proc/self/maps - anything longer is skipped here */
 | 
				
			||||||
#define MAPS_LINE_LEN 128
 | 
					#define MAPS_LINE_LEN 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 | 
					 | 
				
			||||||
		       int flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sigaction sa;
 | 
					 | 
				
			||||||
	memset(&sa, 0, sizeof(sa));
 | 
					 | 
				
			||||||
	sa.sa_sigaction = handler;
 | 
					 | 
				
			||||||
	sa.sa_flags = SA_SIGINFO | flags;
 | 
					 | 
				
			||||||
	sigemptyset(&sa.sa_mask);
 | 
					 | 
				
			||||||
	if (sigaction(sig, &sa, 0))
 | 
					 | 
				
			||||||
		err(1, "sigaction");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* vsyscalls and vDSO */
 | 
					/* vsyscalls and vDSO */
 | 
				
			||||||
bool vsyscall_map_r = false, vsyscall_map_x = false;
 | 
					bool vsyscall_map_r = false, vsyscall_map_x = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,83 +70,25 @@ static void init_vdso(void)
 | 
				
			||||||
	if (!vdso)
 | 
						if (!vdso)
 | 
				
			||||||
		vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
 | 
							vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
 | 
				
			||||||
	if (!vdso) {
 | 
						if (!vdso) {
 | 
				
			||||||
		printf("[WARN]\tfailed to find vDSO\n");
 | 
							ksft_print_msg("[WARN] failed to find vDSO\n");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vdso_gtod = (gtod_t)dlsym(vdso, "__vdso_gettimeofday");
 | 
						vdso_gtod = (gtod_t)dlsym(vdso, "__vdso_gettimeofday");
 | 
				
			||||||
	if (!vdso_gtod)
 | 
						if (!vdso_gtod)
 | 
				
			||||||
		printf("[WARN]\tfailed to find gettimeofday in vDSO\n");
 | 
							ksft_print_msg("[WARN] failed to find gettimeofday in vDSO\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vdso_gettime = (vgettime_t)dlsym(vdso, "__vdso_clock_gettime");
 | 
						vdso_gettime = (vgettime_t)dlsym(vdso, "__vdso_clock_gettime");
 | 
				
			||||||
	if (!vdso_gettime)
 | 
						if (!vdso_gettime)
 | 
				
			||||||
		printf("[WARN]\tfailed to find clock_gettime in vDSO\n");
 | 
							ksft_print_msg("[WARN] failed to find clock_gettime in vDSO\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vdso_time = (time_func_t)dlsym(vdso, "__vdso_time");
 | 
						vdso_time = (time_func_t)dlsym(vdso, "__vdso_time");
 | 
				
			||||||
	if (!vdso_time)
 | 
						if (!vdso_time)
 | 
				
			||||||
		printf("[WARN]\tfailed to find time in vDSO\n");
 | 
							ksft_print_msg("[WARN] failed to find time in vDSO\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
 | 
						vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
 | 
				
			||||||
	if (!vdso_getcpu)
 | 
						if (!vdso_getcpu)
 | 
				
			||||||
		printf("[WARN]\tfailed to find getcpu in vDSO\n");
 | 
							ksft_print_msg("[WARN] failed to find getcpu in vDSO\n");
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int init_vsys(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef __x86_64__
 | 
					 | 
				
			||||||
	int nerrs = 0;
 | 
					 | 
				
			||||||
	FILE *maps;
 | 
					 | 
				
			||||||
	char line[MAPS_LINE_LEN];
 | 
					 | 
				
			||||||
	bool found = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	maps = fopen("/proc/self/maps", "r");
 | 
					 | 
				
			||||||
	if (!maps) {
 | 
					 | 
				
			||||||
		printf("[WARN]\tCould not open /proc/self/maps -- assuming vsyscall is r-x\n");
 | 
					 | 
				
			||||||
		vsyscall_map_r = true;
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (fgets(line, MAPS_LINE_LEN, maps)) {
 | 
					 | 
				
			||||||
		char r, x;
 | 
					 | 
				
			||||||
		void *start, *end;
 | 
					 | 
				
			||||||
		char name[MAPS_LINE_LEN];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* sscanf() is safe here as strlen(name) >= strlen(line) */
 | 
					 | 
				
			||||||
		if (sscanf(line, "%p-%p %c-%cp %*x %*x:%*x %*u %s",
 | 
					 | 
				
			||||||
			   &start, &end, &r, &x, name) != 5)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (strcmp(name, "[vsyscall]"))
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		printf("\tvsyscall map: %s", line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (start != (void *)0xffffffffff600000 ||
 | 
					 | 
				
			||||||
		    end != (void *)0xffffffffff601000) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\taddress range is nonsense\n");
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		printf("\tvsyscall permissions are %c-%c\n", r, x);
 | 
					 | 
				
			||||||
		vsyscall_map_r = (r == 'r');
 | 
					 | 
				
			||||||
		vsyscall_map_x = (x == 'x');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		found = true;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fclose(maps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!found) {
 | 
					 | 
				
			||||||
		printf("\tno vsyscall map in /proc/self/maps\n");
 | 
					 | 
				
			||||||
		vsyscall_map_r = false;
 | 
					 | 
				
			||||||
		vsyscall_map_x = false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nerrs;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* syscalls */
 | 
					/* syscalls */
 | 
				
			||||||
| 
						 | 
					@ -176,9 +113,221 @@ static inline long sys_getcpu(unsigned * cpu, unsigned * node,
 | 
				
			||||||
	return syscall(SYS_getcpu, cpu, node, cache);
 | 
						return syscall(SYS_getcpu, cpu, node, cache);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static double tv_diff(const struct timeval *a, const struct timeval *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (double)(a->tv_sec - b->tv_sec) +
 | 
				
			||||||
 | 
							(double)((int)a->tv_usec - (int)b->tv_usec) * 1e-6;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void check_gtod(const struct timeval *tv_sys1,
 | 
				
			||||||
 | 
							       const struct timeval *tv_sys2,
 | 
				
			||||||
 | 
							       const struct timezone *tz_sys,
 | 
				
			||||||
 | 
							       const char *which,
 | 
				
			||||||
 | 
							       const struct timeval *tv_other,
 | 
				
			||||||
 | 
							       const struct timezone *tz_other)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						double d1, d2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tz_other && (tz_sys->tz_minuteswest != tz_other->tz_minuteswest ||
 | 
				
			||||||
 | 
								 tz_sys->tz_dsttime != tz_other->tz_dsttime))
 | 
				
			||||||
 | 
							ksft_print_msg("%s tz mismatch\n", which);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						d1 = tv_diff(tv_other, tv_sys1);
 | 
				
			||||||
 | 
						d2 = tv_diff(tv_sys2, tv_other); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_msg("%s time offsets: %lf %lf\n", which, d1, d2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_test_result(!(d1 < 0 || d2 < 0), "%s gettimeofday()'s timeval\n", which);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_gtod(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct timeval tv_sys1, tv_sys2, tv_vdso, tv_vsys;
 | 
				
			||||||
 | 
						struct timezone tz_sys, tz_vdso, tz_vsys;
 | 
				
			||||||
 | 
						long ret_vdso = -1;
 | 
				
			||||||
 | 
						long ret_vsys = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_msg("test gettimeofday()\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sys_gtod(&tv_sys1, &tz_sys) != 0)
 | 
				
			||||||
 | 
							ksft_exit_fail_msg("syscall gettimeofday: %s\n", strerror(errno));
 | 
				
			||||||
 | 
						if (vdso_gtod)
 | 
				
			||||||
 | 
							ret_vdso = vdso_gtod(&tv_vdso, &tz_vdso);
 | 
				
			||||||
 | 
						if (vsyscall_map_x)
 | 
				
			||||||
 | 
							ret_vsys = vgtod(&tv_vsys, &tz_vsys);
 | 
				
			||||||
 | 
						if (sys_gtod(&tv_sys2, &tz_sys) != 0)
 | 
				
			||||||
 | 
							ksft_exit_fail_msg("syscall gettimeofday: %s\n", strerror(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vdso_gtod) {
 | 
				
			||||||
 | 
							if (ret_vdso == 0)
 | 
				
			||||||
 | 
								check_gtod(&tv_sys1, &tv_sys2, &tz_sys, "vDSO", &tv_vdso, &tz_vdso);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ksft_test_result_fail("vDSO gettimeofday() failed: %ld\n", ret_vdso);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_gtod isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vsyscall_map_x) {
 | 
				
			||||||
 | 
							if (ret_vsys == 0)
 | 
				
			||||||
 | 
								check_gtod(&tv_sys1, &tv_sys2, &tz_sys, "vsyscall", &tv_vsys, &tz_vsys);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ksft_test_result_fail("vsys gettimeofday() failed: %ld\n", ret_vsys);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vsyscall_map_x isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_time(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						long t_sys1, t_sys2, t_vdso = 0, t_vsys = 0;
 | 
				
			||||||
 | 
						long t2_sys1 = -1, t2_sys2 = -1, t2_vdso = -1, t2_vsys = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_msg("test time()\n");
 | 
				
			||||||
 | 
						t_sys1 = sys_time(&t2_sys1);
 | 
				
			||||||
 | 
						if (vdso_time)
 | 
				
			||||||
 | 
							t_vdso = vdso_time(&t2_vdso);
 | 
				
			||||||
 | 
						if (vsyscall_map_x)
 | 
				
			||||||
 | 
							t_vsys = vtime(&t2_vsys);
 | 
				
			||||||
 | 
						t_sys2 = sys_time(&t2_sys2);
 | 
				
			||||||
 | 
						if (t_sys1 < 0 || t_sys1 != t2_sys1 || t_sys2 < 0 || t_sys2 != t2_sys2) {
 | 
				
			||||||
 | 
							ksft_print_msg("syscall failed (ret1:%ld output1:%ld ret2:%ld output2:%ld)\n",
 | 
				
			||||||
 | 
								       t_sys1, t2_sys1, t_sys2, t2_sys2);
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_time\n");
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_time\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vdso_time) {
 | 
				
			||||||
 | 
							if (t_vdso < 0 || t_vdso != t2_vdso)
 | 
				
			||||||
 | 
								ksft_test_result_fail("vDSO failed (ret:%ld output:%ld)\n",
 | 
				
			||||||
 | 
										      t_vdso, t2_vdso);
 | 
				
			||||||
 | 
							else if (t_vdso < t_sys1 || t_vdso > t_sys2)
 | 
				
			||||||
 | 
								ksft_test_result_fail("vDSO returned the wrong time (%ld %ld %ld)\n",
 | 
				
			||||||
 | 
										      t_sys1, t_vdso, t_sys2);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ksft_test_result_pass("vDSO time() is okay\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_time isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vsyscall_map_x) {
 | 
				
			||||||
 | 
							if (t_vsys < 0 || t_vsys != t2_vsys)
 | 
				
			||||||
 | 
								ksft_test_result_fail("vsyscall failed (ret:%ld output:%ld)\n",
 | 
				
			||||||
 | 
										      t_vsys, t2_vsys);
 | 
				
			||||||
 | 
							else if (t_vsys < t_sys1 || t_vsys > t_sys2)
 | 
				
			||||||
 | 
								ksft_test_result_fail("vsyscall returned the wrong time (%ld %ld %ld)\n",
 | 
				
			||||||
 | 
										      t_sys1, t_vsys, t_sys2);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ksft_test_result_pass("vsyscall time() is okay\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vsyscall_map_x isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_getcpu(int cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int cpu_sys, cpu_vdso, cpu_vsys, node_sys, node_vdso, node_vsys;
 | 
				
			||||||
 | 
						long ret_sys, ret_vdso = -1, ret_vsys = -1;
 | 
				
			||||||
 | 
						unsigned int node = 0;
 | 
				
			||||||
 | 
						bool have_node = false;
 | 
				
			||||||
 | 
						cpu_set_t cpuset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_msg("getcpu() on CPU %d\n", cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CPU_ZERO(&cpuset);
 | 
				
			||||||
 | 
						CPU_SET(cpu, &cpuset);
 | 
				
			||||||
 | 
						if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
 | 
				
			||||||
 | 
							ksft_print_msg("failed to force CPU %d\n", cpu);
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_getcpu\n");
 | 
				
			||||||
 | 
							ksft_test_result_skip("vsyscall_map_x\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret_sys = sys_getcpu(&cpu_sys, &node_sys, 0);
 | 
				
			||||||
 | 
						if (vdso_getcpu)
 | 
				
			||||||
 | 
							ret_vdso = vdso_getcpu(&cpu_vdso, &node_vdso, 0);
 | 
				
			||||||
 | 
						if (vsyscall_map_x)
 | 
				
			||||||
 | 
							ret_vsys = vgetcpu(&cpu_vsys, &node_vsys, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret_sys == 0) {
 | 
				
			||||||
 | 
							if (cpu_sys != cpu)
 | 
				
			||||||
 | 
								ksft_print_msg("syscall reported CPU %hu but should be %d\n",
 | 
				
			||||||
 | 
									       cpu_sys, cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							have_node = true;
 | 
				
			||||||
 | 
							node = node_sys;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vdso_getcpu) {
 | 
				
			||||||
 | 
							if (ret_vdso) {
 | 
				
			||||||
 | 
								ksft_test_result_fail("vDSO getcpu() failed\n");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (!have_node) {
 | 
				
			||||||
 | 
									have_node = true;
 | 
				
			||||||
 | 
									node = node_vdso;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cpu_vdso != cpu || node_vdso != node) {
 | 
				
			||||||
 | 
									if (cpu_vdso != cpu)
 | 
				
			||||||
 | 
										ksft_print_msg("vDSO reported CPU %hu but should be %d\n",
 | 
				
			||||||
 | 
											       cpu_vdso, cpu);
 | 
				
			||||||
 | 
									if (node_vdso != node)
 | 
				
			||||||
 | 
										ksft_print_msg("vDSO reported node %hu but should be %hu\n",
 | 
				
			||||||
 | 
											       node_vdso, node);
 | 
				
			||||||
 | 
									ksft_test_result_fail("Wrong values\n");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									ksft_test_result_pass("vDSO reported correct CPU and node\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vdso_getcpu isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vsyscall_map_x) {
 | 
				
			||||||
 | 
							if (ret_vsys) {
 | 
				
			||||||
 | 
								ksft_test_result_fail("vsyscall getcpu() failed\n");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (!have_node) {
 | 
				
			||||||
 | 
									have_node = true;
 | 
				
			||||||
 | 
									node = node_vsys;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cpu_vsys != cpu || node_vsys != node) {
 | 
				
			||||||
 | 
									if (cpu_vsys != cpu)
 | 
				
			||||||
 | 
										ksft_print_msg("vsyscall reported CPU %hu but should be %d\n",
 | 
				
			||||||
 | 
											       cpu_vsys, cpu);
 | 
				
			||||||
 | 
									if (node_vsys != node)
 | 
				
			||||||
 | 
										ksft_print_msg("vsyscall reported node %hu but should be %hu\n",
 | 
				
			||||||
 | 
											       node_vsys, node);
 | 
				
			||||||
 | 
									ksft_test_result_fail("Wrong values\n");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									ksft_test_result_pass("vsyscall reported correct CPU and node\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ksft_test_result_skip("vsyscall_map_x isn't set\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __x86_64__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static jmp_buf jmpbuf;
 | 
					static jmp_buf jmpbuf;
 | 
				
			||||||
static volatile unsigned long segv_err;
 | 
					static volatile unsigned long segv_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 | 
				
			||||||
 | 
							       int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sigaction sa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&sa, 0, sizeof(sa));
 | 
				
			||||||
 | 
						sa.sa_sigaction = handler;
 | 
				
			||||||
 | 
						sa.sa_flags = SA_SIGINFO | flags;
 | 
				
			||||||
 | 
						sigemptyset(&sa.sa_mask);
 | 
				
			||||||
 | 
						if (sigaction(sig, &sa, 0))
 | 
				
			||||||
 | 
							ksft_exit_fail_msg("sigaction failed\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
 | 
					static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ucontext_t *ctx = (ucontext_t *)ctx_void;
 | 
						ucontext_t *ctx = (ucontext_t *)ctx_void;
 | 
				
			||||||
| 
						 | 
					@ -187,219 +336,9 @@ static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
 | 
				
			||||||
	siglongjmp(jmpbuf, 1);
 | 
						siglongjmp(jmpbuf, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static double tv_diff(const struct timeval *a, const struct timeval *b)
 | 
					static void test_vsys_r(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (double)(a->tv_sec - b->tv_sec) +
 | 
						ksft_print_msg("Checking read access to the vsyscall page\n");
 | 
				
			||||||
		(double)((int)a->tv_usec - (int)b->tv_usec) * 1e-6;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int check_gtod(const struct timeval *tv_sys1,
 | 
					 | 
				
			||||||
		      const struct timeval *tv_sys2,
 | 
					 | 
				
			||||||
		      const struct timezone *tz_sys,
 | 
					 | 
				
			||||||
		      const char *which,
 | 
					 | 
				
			||||||
		      const struct timeval *tv_other,
 | 
					 | 
				
			||||||
		      const struct timezone *tz_other)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int nerrs = 0;
 | 
					 | 
				
			||||||
	double d1, d2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tz_other && (tz_sys->tz_minuteswest != tz_other->tz_minuteswest || tz_sys->tz_dsttime != tz_other->tz_dsttime)) {
 | 
					 | 
				
			||||||
		printf("[FAIL] %s tz mismatch\n", which);
 | 
					 | 
				
			||||||
		nerrs++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	d1 = tv_diff(tv_other, tv_sys1);
 | 
					 | 
				
			||||||
	d2 = tv_diff(tv_sys2, tv_other); 
 | 
					 | 
				
			||||||
	printf("\t%s time offsets: %lf %lf\n", which, d1, d2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (d1 < 0 || d2 < 0) {
 | 
					 | 
				
			||||||
		printf("[FAIL]\t%s time was inconsistent with the syscall\n", which);
 | 
					 | 
				
			||||||
		nerrs++;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		printf("[OK]\t%s gettimeofday()'s timeval was okay\n", which);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nerrs;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int test_gtod(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct timeval tv_sys1, tv_sys2, tv_vdso, tv_vsys;
 | 
					 | 
				
			||||||
	struct timezone tz_sys, tz_vdso, tz_vsys;
 | 
					 | 
				
			||||||
	long ret_vdso = -1;
 | 
					 | 
				
			||||||
	long ret_vsys = -1;
 | 
					 | 
				
			||||||
	int nerrs = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printf("[RUN]\ttest gettimeofday()\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sys_gtod(&tv_sys1, &tz_sys) != 0)
 | 
					 | 
				
			||||||
		err(1, "syscall gettimeofday");
 | 
					 | 
				
			||||||
	if (vdso_gtod)
 | 
					 | 
				
			||||||
		ret_vdso = vdso_gtod(&tv_vdso, &tz_vdso);
 | 
					 | 
				
			||||||
	if (vsyscall_map_x)
 | 
					 | 
				
			||||||
		ret_vsys = vgtod(&tv_vsys, &tz_vsys);
 | 
					 | 
				
			||||||
	if (sys_gtod(&tv_sys2, &tz_sys) != 0)
 | 
					 | 
				
			||||||
		err(1, "syscall gettimeofday");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vdso_gtod) {
 | 
					 | 
				
			||||||
		if (ret_vdso == 0) {
 | 
					 | 
				
			||||||
			nerrs += check_gtod(&tv_sys1, &tv_sys2, &tz_sys, "vDSO", &tv_vdso, &tz_vdso);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvDSO gettimeofday() failed: %ld\n", ret_vdso);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vsyscall_map_x) {
 | 
					 | 
				
			||||||
		if (ret_vsys == 0) {
 | 
					 | 
				
			||||||
			nerrs += check_gtod(&tv_sys1, &tv_sys2, &tz_sys, "vsyscall", &tv_vsys, &tz_vsys);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvsys gettimeofday() failed: %ld\n", ret_vsys);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nerrs;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int test_time(void) {
 | 
					 | 
				
			||||||
	int nerrs = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printf("[RUN]\ttest time()\n");
 | 
					 | 
				
			||||||
	long t_sys1, t_sys2, t_vdso = 0, t_vsys = 0;
 | 
					 | 
				
			||||||
	long t2_sys1 = -1, t2_sys2 = -1, t2_vdso = -1, t2_vsys = -1;
 | 
					 | 
				
			||||||
	t_sys1 = sys_time(&t2_sys1);
 | 
					 | 
				
			||||||
	if (vdso_time)
 | 
					 | 
				
			||||||
		t_vdso = vdso_time(&t2_vdso);
 | 
					 | 
				
			||||||
	if (vsyscall_map_x)
 | 
					 | 
				
			||||||
		t_vsys = vtime(&t2_vsys);
 | 
					 | 
				
			||||||
	t_sys2 = sys_time(&t2_sys2);
 | 
					 | 
				
			||||||
	if (t_sys1 < 0 || t_sys1 != t2_sys1 || t_sys2 < 0 || t_sys2 != t2_sys2) {
 | 
					 | 
				
			||||||
		printf("[FAIL]\tsyscall failed (ret1:%ld output1:%ld ret2:%ld output2:%ld)\n", t_sys1, t2_sys1, t_sys2, t2_sys2);
 | 
					 | 
				
			||||||
		nerrs++;
 | 
					 | 
				
			||||||
		return nerrs;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vdso_time) {
 | 
					 | 
				
			||||||
		if (t_vdso < 0 || t_vdso != t2_vdso) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvDSO failed (ret:%ld output:%ld)\n", t_vdso, t2_vdso);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else if (t_vdso < t_sys1 || t_vdso > t_sys2) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvDSO returned the wrong time (%ld %ld %ld)\n", t_sys1, t_vdso, t_sys2);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			printf("[OK]\tvDSO time() is okay\n");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vsyscall_map_x) {
 | 
					 | 
				
			||||||
		if (t_vsys < 0 || t_vsys != t2_vsys) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvsyscall failed (ret:%ld output:%ld)\n", t_vsys, t2_vsys);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else if (t_vsys < t_sys1 || t_vsys > t_sys2) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvsyscall returned the wrong time (%ld %ld %ld)\n", t_sys1, t_vsys, t_sys2);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			printf("[OK]\tvsyscall time() is okay\n");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nerrs;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int test_getcpu(int cpu)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int nerrs = 0;
 | 
					 | 
				
			||||||
	long ret_sys, ret_vdso = -1, ret_vsys = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printf("[RUN]\tgetcpu() on CPU %d\n", cpu);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cpu_set_t cpuset;
 | 
					 | 
				
			||||||
	CPU_ZERO(&cpuset);
 | 
					 | 
				
			||||||
	CPU_SET(cpu, &cpuset);
 | 
					 | 
				
			||||||
	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
 | 
					 | 
				
			||||||
		printf("[SKIP]\tfailed to force CPU %d\n", cpu);
 | 
					 | 
				
			||||||
		return nerrs;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unsigned cpu_sys, cpu_vdso, cpu_vsys, node_sys, node_vdso, node_vsys;
 | 
					 | 
				
			||||||
	unsigned node = 0;
 | 
					 | 
				
			||||||
	bool have_node = false;
 | 
					 | 
				
			||||||
	ret_sys = sys_getcpu(&cpu_sys, &node_sys, 0);
 | 
					 | 
				
			||||||
	if (vdso_getcpu)
 | 
					 | 
				
			||||||
		ret_vdso = vdso_getcpu(&cpu_vdso, &node_vdso, 0);
 | 
					 | 
				
			||||||
	if (vsyscall_map_x)
 | 
					 | 
				
			||||||
		ret_vsys = vgetcpu(&cpu_vsys, &node_vsys, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret_sys == 0) {
 | 
					 | 
				
			||||||
		if (cpu_sys != cpu) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tsyscall reported CPU %hu but should be %d\n", cpu_sys, cpu);
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		have_node = true;
 | 
					 | 
				
			||||||
		node = node_sys;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vdso_getcpu) {
 | 
					 | 
				
			||||||
		if (ret_vdso) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvDSO getcpu() failed\n");
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (!have_node) {
 | 
					 | 
				
			||||||
				have_node = true;
 | 
					 | 
				
			||||||
				node = node_vdso;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (cpu_vdso != cpu) {
 | 
					 | 
				
			||||||
				printf("[FAIL]\tvDSO reported CPU %hu but should be %d\n", cpu_vdso, cpu);
 | 
					 | 
				
			||||||
				nerrs++;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				printf("[OK]\tvDSO reported correct CPU\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (node_vdso != node) {
 | 
					 | 
				
			||||||
				printf("[FAIL]\tvDSO reported node %hu but should be %hu\n", node_vdso, node);
 | 
					 | 
				
			||||||
				nerrs++;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				printf("[OK]\tvDSO reported correct node\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vsyscall_map_x) {
 | 
					 | 
				
			||||||
		if (ret_vsys) {
 | 
					 | 
				
			||||||
			printf("[FAIL]\tvsyscall getcpu() failed\n");
 | 
					 | 
				
			||||||
			nerrs++;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (!have_node) {
 | 
					 | 
				
			||||||
				have_node = true;
 | 
					 | 
				
			||||||
				node = node_vsys;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (cpu_vsys != cpu) {
 | 
					 | 
				
			||||||
				printf("[FAIL]\tvsyscall reported CPU %hu but should be %d\n", cpu_vsys, cpu);
 | 
					 | 
				
			||||||
				nerrs++;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				printf("[OK]\tvsyscall reported correct CPU\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (node_vsys != node) {
 | 
					 | 
				
			||||||
				printf("[FAIL]\tvsyscall reported node %hu but should be %hu\n", node_vsys, node);
 | 
					 | 
				
			||||||
				nerrs++;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				printf("[OK]\tvsyscall reported correct node\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nerrs;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int test_vsys_r(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef __x86_64__
 | 
					 | 
				
			||||||
	printf("[RUN]\tChecking read access to the vsyscall page\n");
 | 
					 | 
				
			||||||
	bool can_read;
 | 
						bool can_read;
 | 
				
			||||||
	if (sigsetjmp(jmpbuf, 1) == 0) {
 | 
						if (sigsetjmp(jmpbuf, 1) == 0) {
 | 
				
			||||||
		*(volatile int *)0xffffffffff600000;
 | 
							*(volatile int *)0xffffffffff600000;
 | 
				
			||||||
| 
						 | 
					@ -408,32 +347,25 @@ static int test_vsys_r(void)
 | 
				
			||||||
		can_read = false;
 | 
							can_read = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (can_read && !vsyscall_map_r) {
 | 
						if (can_read && !vsyscall_map_r)
 | 
				
			||||||
		printf("[FAIL]\tWe have read access, but we shouldn't\n");
 | 
							ksft_test_result_fail("We have read access, but we shouldn't\n");
 | 
				
			||||||
		return 1;
 | 
						else if (!can_read && vsyscall_map_r)
 | 
				
			||||||
	} else if (!can_read && vsyscall_map_r) {
 | 
							ksft_test_result_fail("We don't have read access, but we should\n");
 | 
				
			||||||
		printf("[FAIL]\tWe don't have read access, but we should\n");
 | 
						else if (can_read)
 | 
				
			||||||
		return 1;
 | 
							ksft_test_result_pass("We have read access\n");
 | 
				
			||||||
	} else if (can_read) {
 | 
						else
 | 
				
			||||||
		printf("[OK]\tWe have read access\n");
 | 
							ksft_test_result_pass("We do not have read access: #PF(0x%lx)\n", segv_err);
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		printf("[OK]\tWe do not have read access: #PF(0x%lx)\n",
 | 
					 | 
				
			||||||
		       segv_err);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_vsys_x(void)
 | 
					static void test_vsys_x(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef __x86_64__
 | 
					 | 
				
			||||||
	if (vsyscall_map_x) {
 | 
						if (vsyscall_map_x) {
 | 
				
			||||||
		/* We already tested this adequately. */
 | 
							/* We already tested this adequately. */
 | 
				
			||||||
		return 0;
 | 
							ksft_test_result_pass("vsyscall_map_x is true\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("[RUN]\tMake sure that vsyscalls really page fault\n");
 | 
						ksft_print_msg("Make sure that vsyscalls really page fault\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool can_exec;
 | 
						bool can_exec;
 | 
				
			||||||
	if (sigsetjmp(jmpbuf, 1) == 0) {
 | 
						if (sigsetjmp(jmpbuf, 1) == 0) {
 | 
				
			||||||
| 
						 | 
					@ -443,20 +375,14 @@ static int test_vsys_x(void)
 | 
				
			||||||
		can_exec = false;
 | 
							can_exec = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (can_exec) {
 | 
						if (can_exec)
 | 
				
			||||||
		printf("[FAIL]\tExecuting the vsyscall did not page fault\n");
 | 
							ksft_test_result_fail("Executing the vsyscall did not page fault\n");
 | 
				
			||||||
		return 1;
 | 
						else if (segv_err & (1 << 4)) /* INSTR */
 | 
				
			||||||
	} else if (segv_err & (1 << 4)) { /* INSTR */
 | 
							ksft_test_result_pass("Executing the vsyscall page failed: #PF(0x%lx)\n",
 | 
				
			||||||
		printf("[OK]\tExecuting the vsyscall page failed: #PF(0x%lx)\n",
 | 
					 | 
				
			||||||
				      segv_err);
 | 
									      segv_err);
 | 
				
			||||||
	} else {
 | 
						else
 | 
				
			||||||
		printf("[FAIL]\tExecution failed with the wrong error: #PF(0x%lx)\n",
 | 
							ksft_test_result_fail("Execution failed with the wrong error: #PF(0x%lx)\n",
 | 
				
			||||||
				      segv_err);
 | 
									      segv_err);
 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -470,14 +396,13 @@ static int test_vsys_x(void)
 | 
				
			||||||
 * fact that ptrace() ever worked was a nice courtesy of old kernels,
 | 
					 * fact that ptrace() ever worked was a nice courtesy of old kernels,
 | 
				
			||||||
 * but the code to support it is fairly gross.
 | 
					 * but the code to support it is fairly gross.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int test_process_vm_readv(void)
 | 
					static void test_process_vm_readv(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef __x86_64__
 | 
					 | 
				
			||||||
	char buf[4096];
 | 
						char buf[4096];
 | 
				
			||||||
	struct iovec local, remote;
 | 
						struct iovec local, remote;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("[RUN]\tprocess_vm_readv() from vsyscall page\n");
 | 
						ksft_print_msg("process_vm_readv() from vsyscall page\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local.iov_base = buf;
 | 
						local.iov_base = buf;
 | 
				
			||||||
	local.iov_len = 4096;
 | 
						local.iov_len = 4096;
 | 
				
			||||||
| 
						 | 
					@ -489,27 +414,71 @@ static int test_process_vm_readv(void)
 | 
				
			||||||
		 * We expect process_vm_readv() to work if and only if the
 | 
							 * We expect process_vm_readv() to work if and only if the
 | 
				
			||||||
		 * vsyscall page is readable.
 | 
							 * vsyscall page is readable.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		printf("[%s]\tprocess_vm_readv() failed (ret = %d, errno = %d)\n", vsyscall_map_r ? "FAIL" : "OK", ret, errno);
 | 
							ksft_test_result(!vsyscall_map_r,
 | 
				
			||||||
		return vsyscall_map_r ? 1 : 0;
 | 
									 "process_vm_readv() failed (ret = %d, errno = %d)\n", ret, errno);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vsyscall_map_r) {
 | 
						if (vsyscall_map_r)
 | 
				
			||||||
		if (!memcmp(buf, remote.iov_base, sizeof(buf))) {
 | 
							ksft_test_result(!memcmp(buf, remote.iov_base, sizeof(buf)), "Read data\n");
 | 
				
			||||||
			printf("[OK]\tIt worked and read correct data\n");
 | 
						else
 | 
				
			||||||
		} else {
 | 
							ksft_test_result_fail("process_rm_readv() succeeded, but it should have failed in this configuration\n");
 | 
				
			||||||
			printf("[FAIL]\tIt worked but returned incorrect data\n");
 | 
					}
 | 
				
			||||||
			return 1;
 | 
					
 | 
				
			||||||
		}
 | 
					static void init_vsys(void)
 | 
				
			||||||
	} else {
 | 
					{
 | 
				
			||||||
		printf("[FAIL]\tprocess_rm_readv() succeeded, but it should have failed in this configuration\n");
 | 
						int nerrs = 0;
 | 
				
			||||||
		return 1;
 | 
						FILE *maps;
 | 
				
			||||||
	}
 | 
						char line[MAPS_LINE_LEN];
 | 
				
			||||||
#endif
 | 
						bool found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						maps = fopen("/proc/self/maps", "r");
 | 
				
			||||||
 | 
						if (!maps) {
 | 
				
			||||||
 | 
							ksft_test_result_skip("Could not open /proc/self/maps -- assuming vsyscall is r-x\n");
 | 
				
			||||||
 | 
							vsyscall_map_r = true;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (fgets(line, MAPS_LINE_LEN, maps)) {
 | 
				
			||||||
 | 
							char r, x;
 | 
				
			||||||
 | 
							void *start, *end;
 | 
				
			||||||
 | 
							char name[MAPS_LINE_LEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* sscanf() is safe here as strlen(name) >= strlen(line) */
 | 
				
			||||||
 | 
							if (sscanf(line, "%p-%p %c-%cp %*x %*x:%*x %*u %s",
 | 
				
			||||||
 | 
								   &start, &end, &r, &x, name) != 5)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (strcmp(name, "[vsyscall]"))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ksft_print_msg("vsyscall map: %s", line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (start != (void *)0xffffffffff600000 ||
 | 
				
			||||||
 | 
							    end != (void *)0xffffffffff601000) {
 | 
				
			||||||
 | 
								ksft_print_msg("address range is nonsense\n");
 | 
				
			||||||
 | 
								nerrs++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ksft_print_msg("vsyscall permissions are %c-%c\n", r, x);
 | 
				
			||||||
 | 
							vsyscall_map_r = (r == 'r');
 | 
				
			||||||
 | 
							vsyscall_map_x = (x == 'x');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							found = true;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fclose(maps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!found) {
 | 
				
			||||||
 | 
							ksft_print_msg("no vsyscall map in /proc/self/maps\n");
 | 
				
			||||||
 | 
							vsyscall_map_r = false;
 | 
				
			||||||
 | 
							vsyscall_map_x = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_test_result(!nerrs, "vsyscall map\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __x86_64__
 | 
					 | 
				
			||||||
static volatile sig_atomic_t num_vsyscall_traps;
 | 
					static volatile sig_atomic_t num_vsyscall_traps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 | 
					static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 | 
				
			||||||
| 
						 | 
					@ -521,15 +490,17 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 | 
				
			||||||
		num_vsyscall_traps++;
 | 
							num_vsyscall_traps++;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int test_emulation(void)
 | 
					static void test_emulation(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	time_t tmp;
 | 
						time_t tmp;
 | 
				
			||||||
	bool is_native;
 | 
						bool is_native;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!vsyscall_map_x)
 | 
						if (!vsyscall_map_x) {
 | 
				
			||||||
		return 0;
 | 
							ksft_test_result_skip("vsyscall_map_x isn't set\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("[RUN]\tchecking that vsyscalls are emulated\n");
 | 
						ksft_print_msg("checking that vsyscalls are emulated\n");
 | 
				
			||||||
	sethandler(SIGTRAP, sigtrap, 0);
 | 
						sethandler(SIGTRAP, sigtrap, 0);
 | 
				
			||||||
	set_eflags(get_eflags() | X86_EFLAGS_TF);
 | 
						set_eflags(get_eflags() | X86_EFLAGS_TF);
 | 
				
			||||||
	vtime(&tmp);
 | 
						vtime(&tmp);
 | 
				
			||||||
| 
						 | 
					@ -545,36 +516,35 @@ static int test_emulation(void)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	is_native = (num_vsyscall_traps > 1);
 | 
						is_native = (num_vsyscall_traps > 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("[%s]\tvsyscalls are %s (%d instructions in vsyscall page)\n",
 | 
						ksft_test_result(!is_native, "vsyscalls are %s (%d instructions in vsyscall page)\n",
 | 
				
			||||||
	       (is_native ? "FAIL" : "OK"),
 | 
								 (is_native ? "native" : "emulated"), (int)num_vsyscall_traps);
 | 
				
			||||||
	       (is_native ? "native" : "emulated"),
 | 
					 | 
				
			||||||
	       (int)num_vsyscall_traps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return is_native;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int nerrs = 0;
 | 
						int total_tests = TOTAL_TESTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_print_header();
 | 
				
			||||||
 | 
						ksft_set_plan(total_tests);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_vdso();
 | 
						init_vdso();
 | 
				
			||||||
	nerrs += init_vsys();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nerrs += test_gtod();
 | 
					 | 
				
			||||||
	nerrs += test_time();
 | 
					 | 
				
			||||||
	nerrs += test_getcpu(0);
 | 
					 | 
				
			||||||
	nerrs += test_getcpu(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sethandler(SIGSEGV, sigsegv, 0);
 | 
					 | 
				
			||||||
	nerrs += test_vsys_r();
 | 
					 | 
				
			||||||
	nerrs += test_vsys_x();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nerrs += test_process_vm_readv();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __x86_64__
 | 
					#ifdef __x86_64__
 | 
				
			||||||
	nerrs += test_emulation();
 | 
						init_vsys();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nerrs ? 1 : 0;
 | 
						test_gtod();
 | 
				
			||||||
 | 
						test_time();
 | 
				
			||||||
 | 
						test_getcpu(0);
 | 
				
			||||||
 | 
						test_getcpu(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __x86_64__
 | 
				
			||||||
 | 
						sethandler(SIGSEGV, sigsegv, 0);
 | 
				
			||||||
 | 
						test_vsys_r();
 | 
				
			||||||
 | 
						test_vsys_x();
 | 
				
			||||||
 | 
						test_process_vm_readv();
 | 
				
			||||||
 | 
						test_emulation();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksft_finished();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue