Merge 4b95dc8736 ("Merge tag 'linux_kselftest-next-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest") into android-mainline

Steps on the way to 6.10-rc1

Change-Id: I7f9db0c04dfccb854d1a0f3f2c2158709d89aa87
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-07-16 17:15:12 +00:00
86 changed files with 1060 additions and 834 deletions
+1 -1
View File
@@ -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
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
one would use:
one would use::
$ ./run_kselftest.sh --override-timeout 165
+21 -3
View File
@@ -301,6 +301,8 @@ struct kunit {
struct list_head resources; /* Protected by lock. */
char status_comment[KUNIT_STATUS_COMMENT_SIZE];
/* Saves the last seen test. Useful to help with faults. */
struct kunit_loc last_seen;
};
static inline void kunit_set_failure(struct kunit *test)
@@ -567,6 +569,15 @@ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt,
#define kunit_err(test, fmt, ...) \
kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
/*
* Must be called at the beginning of each KUNIT_*_ASSERTION().
* Cf. KUNIT_CURRENT_LOC.
*/
#define _KUNIT_SAVE_LOC(test) do { \
WRITE_ONCE(test->last_seen.file, __FILE__); \
WRITE_ONCE(test->last_seen.line, __LINE__); \
} while (0)
/**
* KUNIT_SUCCEED() - A no-op expectation. Only exists for code clarity.
* @test: The test context object.
@@ -575,7 +586,7 @@ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt,
* words, it does nothing and only exists for code clarity. See
* KUNIT_EXPECT_TRUE() for more information.
*/
#define KUNIT_SUCCEED(test) do {} while (0)
#define KUNIT_SUCCEED(test) _KUNIT_SAVE_LOC(test)
void __noreturn __kunit_abort(struct kunit *test);
@@ -601,14 +612,16 @@ void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test,
} while (0)
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) \
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) do { \
_KUNIT_SAVE_LOC(test); \
_KUNIT_FAILED(test, \
assert_type, \
kunit_fail_assert, \
kunit_fail_assert_format, \
{}, \
fmt, \
##__VA_ARGS__)
##__VA_ARGS__); \
} while (0)
/**
* KUNIT_FAIL() - Always causes a test to fail when evaluated.
@@ -637,6 +650,7 @@ void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test,
fmt, \
...) \
do { \
_KUNIT_SAVE_LOC(test); \
if (likely(!!(condition_) == !!expected_true_)) \
break; \
\
@@ -698,6 +712,7 @@ do { \
.right_text = #right, \
}; \
\
_KUNIT_SAVE_LOC(test); \
if (likely(__left op __right)) \
break; \
\
@@ -758,6 +773,7 @@ do { \
.right_text = #right, \
}; \
\
_KUNIT_SAVE_LOC(test); \
if (likely((__left) && (__right) && (strcmp(__left, __right) op 0))) \
break; \
\
@@ -791,6 +807,7 @@ do { \
.right_text = #right, \
}; \
\
_KUNIT_SAVE_LOC(test); \
if (likely(__left && __right)) \
if (likely(memcmp(__left, __right, __size) op 0)) \
break; \
@@ -815,6 +832,7 @@ do { \
do { \
const typeof(ptr) __ptr = (ptr); \
\
_KUNIT_SAVE_LOC(test); \
if (!IS_ERR_OR_NULL(__ptr)) \
break; \
\
-3
View File
@@ -14,13 +14,11 @@
typedef void (*kunit_try_catch_func_t)(void *);
struct completion;
struct kunit;
/**
* struct kunit_try_catch - provides a generic way to run code which might fail.
* @test: The test case that is currently being executed.
* @try_completion: Completion that the control thread waits on while test runs.
* @try_result: Contains any errno obtained while running test case.
* @try: The function, the test case, to attempt to run.
* @catch: The function called if @try bails out.
@@ -46,7 +44,6 @@ struct kunit;
struct kunit_try_catch {
/* private: internal use only. */
struct kunit *test;
struct completion *try_completion;
int try_result;
kunit_try_catch_func_t try;
kunit_try_catch_func_t catch;
+1
View File
@@ -315,6 +315,7 @@ void __noreturn kthread_exit(long result)
kthread->result = result;
do_exit(0);
}
EXPORT_SYMBOL(kthread_exit);
/**
* kthread_complete_and_exit - Exit the current kthread.
+11
View File
@@ -24,6 +24,17 @@ config KUNIT_DEBUGFS
test suite, which allow users to see results of the last test suite
run that occurred.
config KUNIT_FAULT_TEST
bool "Enable KUnit tests which print BUG stacktraces"
depends on KUNIT_TEST
depends on !UML
default y
help
Enables fault handling tests for the KUnit framework. These tests may
trigger a kernel BUG(), and the associated stack trace, even when they
pass. If this conflicts with your test infrastrcture (or is confusing
or annoying), they can be disabled by setting this to N.
config KUNIT_TEST
tristate "KUnit test for KUnit" if !KUNIT_ALL_TESTS
default KUNIT_ALL_TESTS
+1 -1
View File
@@ -51,7 +51,7 @@ int kunit_bus_init(void)
error = bus_register(&kunit_bus_type);
if (error)
bus_unregister(&kunit_bus_type);
root_device_unregister(kunit_bus_device);
return error;
}
+44 -1
View File
@@ -109,6 +109,48 @@ static struct kunit_suite kunit_try_catch_test_suite = {
.test_cases = kunit_try_catch_test_cases,
};
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
static void kunit_test_null_dereference(void *data)
{
struct kunit *test = data;
int *null = NULL;
*null = 0;
KUNIT_FAIL(test, "This line should never be reached\n");
}
static void kunit_test_fault_null_dereference(struct kunit *test)
{
struct kunit_try_catch_test_context *ctx = test->priv;
struct kunit_try_catch *try_catch = ctx->try_catch;
kunit_try_catch_init(try_catch,
test,
kunit_test_null_dereference,
kunit_test_catch);
kunit_try_catch_run(try_catch, test);
KUNIT_EXPECT_EQ(test, try_catch->try_result, -EINTR);
KUNIT_EXPECT_TRUE(test, ctx->function_called);
}
#endif /* CONFIG_KUNIT_FAULT_TEST */
static struct kunit_case kunit_fault_test_cases[] = {
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
KUNIT_CASE(kunit_test_fault_null_dereference),
#endif /* CONFIG_KUNIT_FAULT_TEST */
{}
};
static struct kunit_suite kunit_fault_test_suite = {
.name = "kunit_fault",
.init = kunit_try_catch_test_init,
.test_cases = kunit_fault_test_cases,
};
/*
* Context for testing test managed resources
* is_resource_initialized is used to test arbitrary resources
@@ -826,6 +868,7 @@ static struct kunit_suite kunit_current_test_suite = {
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
&kunit_log_test_suite, &kunit_status_test_suite,
&kunit_current_test_suite, &kunit_device_test_suite);
&kunit_current_test_suite, &kunit_device_test_suite,
&kunit_fault_test_suite);
MODULE_LICENSE("GPL v2");
+2 -10
View File
@@ -22,18 +22,10 @@ struct string_stream_test_priv {
};
/* Avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
static void kfree_wrapper(void *p)
{
kfree(p);
}
KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
/* Avoids a cast warning if string_stream_destroy() is passed direct to kunit_add_action(). */
static void cleanup_raw_stream(void *p)
{
struct string_stream *stream = p;
string_stream_destroy(stream);
}
KUNIT_DEFINE_ACTION_WRAPPER(cleanup_raw_stream, string_stream_destroy, struct string_stream *);
static char *get_concatenated_string(struct kunit *test, struct string_stream *stream)
{
+3
View File
@@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
{
unsigned int i;
if (num_suites == 0)
return 0;
if (!kunit_enabled() && num_suites > 0) {
pr_info("kunit: disabled\n");
return 0;
+29 -11
View File
@@ -11,13 +11,14 @@
#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/sched/task.h>
#include "try-catch-impl.h"
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
{
try_catch->try_result = -EFAULT;
kthread_complete_and_exit(try_catch->try_completion, -EFAULT);
kthread_exit(0);
}
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
@@ -25,9 +26,12 @@ static int kunit_generic_run_threadfn_adapter(void *data)
{
struct kunit_try_catch *try_catch = data;
try_catch->try_result = -EINTR;
try_catch->try(try_catch->context);
if (try_catch->try_result == -EINTR)
try_catch->try_result = 0;
kthread_complete_and_exit(try_catch->try_completion, 0);
return 0;
}
static unsigned long kunit_test_timeout(void)
@@ -57,30 +61,38 @@ static unsigned long kunit_test_timeout(void)
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
{
DECLARE_COMPLETION_ONSTACK(try_completion);
struct kunit *test = try_catch->test;
struct task_struct *task_struct;
struct completion *task_done;
int exit_code, time_remaining;
try_catch->context = context;
try_catch->try_completion = &try_completion;
try_catch->try_result = 0;
task_struct = kthread_run(kunit_generic_run_threadfn_adapter,
try_catch,
"kunit_try_catch_thread");
task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
try_catch, "kunit_try_catch_thread");
if (IS_ERR(task_struct)) {
try_catch->try_result = PTR_ERR(task_struct);
try_catch->catch(try_catch->context);
return;
}
get_task_struct(task_struct);
/*
* As for a vfork(2), task_struct->vfork_done (pointing to the
* underlying kthread->exited) can be used to wait for the end of a
* kernel thread. It is set to NULL when the thread exits, so we
* keep a copy here.
*/
task_done = task_struct->vfork_done;
wake_up_process(task_struct);
time_remaining = wait_for_completion_timeout(&try_completion,
time_remaining = wait_for_completion_timeout(task_done,
kunit_test_timeout());
if (time_remaining == 0) {
kunit_err(test, "try timed out\n");
try_catch->try_result = -ETIMEDOUT;
kthread_stop(task_struct);
}
put_task_struct(task_struct);
exit_code = try_catch->try_result;
if (!exit_code)
@@ -88,8 +100,14 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
if (exit_code == -EFAULT)
try_catch->try_result = 0;
else if (exit_code == -EINTR)
kunit_err(test, "wake_up_process() was never called\n");
else if (exit_code == -EINTR) {
if (test->last_seen.file)
kunit_err(test, "try faulted: last line seen %s:%d\n",
test->last_seen.file, test->last_seen.line);
else
kunit_err(test, "try faulted\n");
} else if (exit_code == -ETIMEDOUT)
kunit_err(test, "try timed out\n");
else if (exit_code)
kunit_err(test, "Unknown error: %d\n", exit_code);
+9 -9
View File
@@ -139,7 +139,7 @@ static void __init iov_kunit_copy_to_kvec(struct kunit *test)
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -194,7 +194,7 @@ stop:
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
struct bvec_test_range {
@@ -302,7 +302,7 @@ static void __init iov_kunit_copy_to_bvec(struct kunit *test)
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -359,7 +359,7 @@ stop:
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
static void iov_kunit_destroy_xarray(void *data)
@@ -453,7 +453,7 @@ static void __init iov_kunit_copy_to_xarray(struct kunit *test)
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -516,7 +516,7 @@ stop:
return;
}
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -596,7 +596,7 @@ static void __init iov_kunit_extract_pages_kvec(struct kunit *test)
stop:
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_EQ(test, iter.count, 0);
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -674,7 +674,7 @@ static void __init iov_kunit_extract_pages_bvec(struct kunit *test)
stop:
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_EQ(test, iter.count, 0);
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
/*
@@ -753,7 +753,7 @@ static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
}
stop:
KUNIT_SUCCEED();
KUNIT_SUCCEED(test);
}
static struct kunit_case __refdata iov_kunit_cases[] = {
+1 -1
View File
@@ -185,7 +185,7 @@ void *realloc(void *old_ptr, size_t new_size)
if (__builtin_expect(!ret, 0))
return NULL;
memcpy(ret, heap->user_p, heap->len);
memcpy(ret, heap->user_p, user_p_len);
munmap(heap, heap->len);
return ret;
}
+25 -19
View File
@@ -123,7 +123,7 @@ char *strcpy(char *dst, const char *src)
* thus itself, hence the asm() statement below that's meant to disable this
* confusing practice.
*/
static __attribute__((unused))
__attribute__((weak,unused,section(".text.nolibc_strlen")))
size_t strlen(const char *str)
{
size_t len;
@@ -187,22 +187,26 @@ char *strndup(const char *str, size_t maxlen)
static __attribute__((unused))
size_t strlcat(char *dst, const char *src, size_t size)
{
size_t len;
char c;
size_t len = strnlen(dst, size);
for (len = 0; dst[len]; len++)
;
for (;;) {
c = *src;
if (len < size)
dst[len] = c;
if (!c)
/*
* We want len < size-1. But as size is unsigned and can wrap
* around, we use len + 1 instead.
*/
while (len + 1 < size) {
dst[len] = *src;
if (*src == '\0')
break;
len++;
src++;
}
if (len < size)
dst[len] = '\0';
while (*src++)
len++;
return len;
}
@@ -210,16 +214,18 @@ static __attribute__((unused))
size_t strlcpy(char *dst, const char *src, size_t size)
{
size_t len;
char c;
for (len = 0;;) {
c = src[len];
if (len < size)
dst[len] = c;
if (!c)
break;
len++;
for (len = 0; len < size; len++) {
dst[len] = src[len];
if (!dst[len])
return len;
}
if (size)
dst[size-1] = '\0';
while (src[len])
len++;
return len;
}
+27
View File
@@ -22,6 +22,7 @@
#include <linux/stat.h> /* for statx() */
#include <linux/prctl.h>
#include <linux/resource.h>
#include <linux/utsname.h>
#include "arch.h"
#include "errno.h"
@@ -1139,6 +1140,32 @@ int umount2(const char *path, int flags)
}
/*
* int uname(struct utsname *buf);
*/
struct utsname {
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
};
static __attribute__((unused))
int sys_uname(struct utsname *buf)
{
return my_syscall1(__NR_uname, buf);
}
static __attribute__((unused))
int uname(struct utsname *buf)
{
return __sysret(sys_uname(buf));
}
/*
* int unlink(const char *path);
*/
+2 -2
View File
@@ -161,11 +161,11 @@ ifneq ($(KBUILD_OUTPUT),)
# $(realpath ...) resolves symlinks
abs_objtree := $(realpath $(abs_objtree))
BUILD := $(abs_objtree)/kselftest
KHDR_INCLUDES := -isystem ${abs_objtree}/usr/include
KHDR_INCLUDES := -D_GNU_SOURCE -isystem ${abs_objtree}/usr/include
else
BUILD := $(CURDIR)
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
endif
@@ -82,7 +82,7 @@ static bool create_and_enter_ns(uid_t inner_uid)
{
uid_t outer_uid;
gid_t outer_gid;
int i;
int i, ret;
bool have_outer_privilege;
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));
// 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++)
if (capng_have_capability(CAPNG_PERMITTED, 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)
{
int ret;
bool have_outer_privilege = create_and_enter_ns(uid);
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));
}
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 */
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)
{
const char *atsec = "";
int ret;
/*
* 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)";
#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)) {
ksft_print_msg("Wrong effective state%s\n", atsec);
+6 -1
View File
@@ -95,9 +95,14 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
getpid(), pid);
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;
}
if (!WIFEXITED(status)) {
ksft_print_msg("Child did not exit normally, status 0x%x\n",
status);
return EXIT_FAILURE;
}
if (WEXITSTATUS(status))
return WEXITSTATUS(status);
@@ -120,5 +120,5 @@ int main(int argc, char **argv)
test_clone3_clear_sighand();
return ksft_exit_pass();
ksft_exit_pass();
}
+72 -49
View File
@@ -114,7 +114,8 @@ static int call_clone3_set_tid(pid_t *set_tid,
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,
int flags,
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,
wait_for_it);
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);
if (ret != expected)
ksft_test_result_fail(
"[%d] Result (%d) is different than expected (%d)\n",
getpid(), ret, expected);
else
ksft_test_result_pass(
"[%d] Result (%d) matches expectation (%d)\n",
getpid(), ret, expected);
ksft_test_result(ret == expected, "%s with %zu TIDs and flags 0x%x\n",
desc, set_tid_size, flags);
}
int main(int argc, char *argv[])
{
FILE *f;
@@ -172,73 +169,91 @@ int main(int argc, char *argv[])
/* Try invalid settings */
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,
-EINVAL, 0, 0);
test_clone3_set_tid("invalid size, 0 TID",
set_tid, MAX_PID_NS_LEVEL * 2 + 1, 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
* 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));
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,
-EINVAL, 0, 0);
test_clone3_set_tid("invalid size, TID all 1s",
set_tid, MAX_PID_NS_LEVEL * 2 + 1, 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
* 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));
/* Try with an invalid PID */
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;
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. */
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 */
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
ksft_test_result_skip("Clone3() with set_tid requires root\n");
/* Try with a valid PID (1) this should return -EEXIST. */
set_tid[0] = 1;
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
ksft_test_result_skip("Clone3() with set_tid requires root\n");
/* Try it in a new PID namespace */
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
ksft_test_result_skip("Clone3() with set_tid requires root\n");
/* pid_max should fail everywhere */
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)
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
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. */
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 */
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
@@ -274,7 +291,8 @@ int main(int argc, char *argv[])
*/
set_tid[0] = 1;
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");
if (unshare(CLONE_NEWPID) == -1)
@@ -284,7 +302,8 @@ int main(int argc, char *argv[])
set_tid[0] = pid;
/* 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 */
ns_pid = fork();
@@ -295,21 +314,25 @@ int main(int argc, char *argv[])
*/
set_tid[0] = 43;
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[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());
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[1] = -1;
set_tid[2] = pid;
/* 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[1] = 42;
@@ -319,13 +342,15 @@ int main(int argc, char *argv[])
* namespaces. Again assuming this is running in the host's
* 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
* 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);
}
@@ -380,16 +405,14 @@ int main(int argc, char *argv[])
ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status));
ksft_cnt.ksft_fail = WEXITSTATUS(status);
if (ns3 == pid && ns2 == 42 && ns1 == 1)
ksft_test_result_pass(
"PIDs in all namespaces as expected (%d,%d,%d)\n",
ns3, ns2, ns1);
else
ksft_test_result_fail(
"PIDs in all namespaces not as expected (%d,%d,%d)\n",
ns3, ns2, ns1);
ksft_print_msg("Expecting PIDs %d, 42, 1\n", pid);
ksft_print_msg("Have PIDs in namespaces: %d, %d, %d\n", ns3, ns2, ns1);
ksft_test_result(ns3 == pid && ns2 == 42 && ns1 == 1,
"PIDs in all namespaces as expected\n");
out:
ret = 0;
return !ret ? ksft_exit_pass() : ksft_exit_fail();
if (ret)
ksft_exit_fail();
ksft_exit_pass();
}
+1 -2
View File
@@ -178,8 +178,7 @@ cpufreq_basic_tests()
count=$(count_cpufreq_managed_cpus)
if [ $count = 0 ]; then
printf "No cpu is managed by cpufreq core, exiting\n"
exit;
ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting\n"
else
printf "CPUFreq manages: $count CPUs\n\n"
fi
+28 -19
View File
@@ -7,15 +7,15 @@ source governor.sh
source module.sh
source special-tests.sh
DIR="$(dirname $(readlink -f "$0"))"
source "${DIR}"/../kselftest/ktap_helpers.sh
FUNC=basic # do basic tests by default
OUTFILE=cpufreq_selftest
SYSFS=
CPUROOT=
CPUFREQROOT=
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
helpme()
{
printf "Usage: $0 [-h] [-todg args]
@@ -32,7 +32,7 @@ helpme()
[-d <driver's module name: only with \"-t modtest>\"]
[-g <governor's module name: only with \"-t modtest>\"]
\n"
exit 2
exit "${KSFT_FAIL}"
}
prerequisite()
@@ -40,8 +40,8 @@ prerequisite()
msg="skip all tests:"
if [ $UID != 0 ]; then
echo $msg must be run as root >&2
exit $ksft_skip
ktap_skip_all "$msg must be run as root"
exit "${KSFT_SKIP}"
fi
taskset -p 01 $$
@@ -49,21 +49,21 @@ prerequisite()
SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
if [ ! -d "$SYSFS" ]; then
echo $msg sysfs is not mounted >&2
exit 2
ktap_skip_all "$msg sysfs is not mounted"
exit "${KSFT_SKIP}"
fi
CPUROOT=$SYSFS/devices/system/cpu
CPUFREQROOT="$CPUROOT/cpufreq"
if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
echo $msg cpus not available in sysfs >&2
exit 2
ktap_skip_all "$msg cpus not available in sysfs"
exit "${KSFT_SKIP}"
fi
if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
echo $msg cpufreq directory not available in sysfs >&2
exit 2
ktap_skip_all "$msg cpufreq directory not available in sysfs"
exit "${KSFT_SKIP}"
fi
}
@@ -105,8 +105,7 @@ do_test()
count=$(count_cpufreq_managed_cpus)
if [ $count = 0 -a $FUNC != "modtest" ]; then
echo "No cpu is managed by cpufreq core, exiting"
exit 2;
ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting"
fi
case "$FUNC" in
@@ -125,8 +124,7 @@ do_test()
"modtest")
# Do we have modules in place?
if [ -z $DRIVER_MOD ] && [ -z $GOVERNOR_MOD ]; then
echo "No driver or governor module passed with -d or -g"
exit 2;
ktap_exit_fail_msg "No driver or governor module passed with -d or -g"
fi
if [ $DRIVER_MOD ]; then
@@ -137,8 +135,7 @@ do_test()
fi
else
if [ $count = 0 ]; then
echo "No cpu is managed by cpufreq core, exiting"
exit 2;
ktap_exit_fail_msg "No cpu is managed by cpufreq core, exiting"
fi
module_governor_test $GOVERNOR_MOD
@@ -162,7 +159,7 @@ do_test()
;;
*)
echo "Invalid [-f] function type"
ktap_print_msg "Invalid [-f] function type"
helpme
;;
esac
@@ -186,13 +183,25 @@ dmesg_dumps()
dmesg >> $1.dmesg_full.txt
}
ktap_print_header
# Parse arguments
parse_arguments $@
ktap_set_plan 1
# Make sure all requirements are met
prerequisite
# Run requested functions
clear_dumps $OUTFILE
do_test | tee -a $OUTFILE.txt
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
exit ${PIPESTATUS[0]};
fi
dmesg_dumps $OUTFILE
ktap_test_pass "Completed successfully"
ktap_print_totals
exit "${KSFT_PASS}"
+2 -4
View File
@@ -24,16 +24,14 @@ test_basic_insmod_rmmod()
# insert module
insmod $1
if [ $? != 0 ]; then
printf "Insmod $1 failed\n"
exit;
ktap_exit_fail_msg "Insmod $1 failed\n"
fi
printf "Removing $1 module\n"
# remove module
rmmod $1
if [ $? != 0 ]; then
printf "rmmod $1 failed\n"
exit;
ktap_exit_fail_msg "rmmod $1 failed\n"
fi
printf "\n"
+104 -149
View File
@@ -15,6 +15,7 @@
#include <linux/dma-buf.h>
#include <linux/dma-heap.h>
#include <drm/drm.h>
#include "../kselftest.h"
#define DEVPATH "/dev/dma_heap"
@@ -90,14 +91,13 @@ static int dmabuf_heap_open(char *name)
char buf[256];
ret = snprintf(buf, 256, "%s/%s", DEVPATH, name);
if (ret < 0) {
printf("snprintf failed!\n");
return ret;
}
if (ret < 0)
ksft_exit_fail_msg("snprintf failed! %d\n", ret);
fd = open(buf, O_RDWR);
if (fd < 0)
printf("open %s failed!\n", buf);
ksft_exit_fail_msg("open %s failed: %s\n", buf, strerror(errno));
return fd;
}
@@ -140,7 +140,7 @@ static int dmabuf_sync(int fd, int start_stop)
#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;
uint32_t handle = 0;
@@ -148,27 +148,19 @@ static int test_alloc_and_import(char *heap_name)
int ret;
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);
if (ret) {
printf("FAIL (Allocation Failed!)\n");
ret = -1;
goto out;
ksft_test_result_fail("FAIL (Allocation Failed!) %d\n", ret);
return;
}
/* mmap and write a simple pattern */
p = mmap(NULL,
ONE_MEG,
PROT_READ | PROT_WRITE,
MAP_SHARED,
dmabuf_fd,
0);
p = mmap(NULL, ONE_MEG, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd, 0);
if (p == MAP_FAILED) {
printf("FAIL (mmap() failed)\n");
ret = -1;
goto out;
ksft_test_result_fail("FAIL (mmap() failed): %s\n", strerror(errno));
goto close_and_return;
}
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();
if (importer_fd < 0) {
ret = importer_fd;
printf("(Could not open vgem - skipping): ");
ksft_test_result_skip("Could not open vgem %d\n", importer_fd);
} else {
ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
if (ret < 0) {
printf("FAIL (Failed to import buffer)\n");
goto out;
}
ksft_test_result(ret >= 0, "Import buffer %d\n", ret);
}
ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
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;
}
memset(p, 0xff, ONE_MEG);
ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
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;
}
close_handle(importer_fd, handle);
ret = 0;
printf(" OK\n");
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);
ksft_test_result_pass("%s dmabuf sync succeeded\n", __func__);
return;
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 i, j, ret;
int i, j, k, ret;
void *p = NULL;
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);
if (heap_fd < 0)
return -1;
/* Allocate and fill a bunch of buffers */
for (i = 0; i < 32; i++) {
ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
if (ret < 0) {
printf("FAIL (Allocation (%i) failed)\n", i);
goto out;
if (ret) {
ksft_test_result_fail("FAIL (Allocation (%i) failed) %d\n", i, ret);
goto close_and_return;
}
/* mmap and fill with simple pattern */
p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
if (p == MAP_FAILED) {
printf("FAIL (mmap() failed!)\n");
ret = -1;
goto out;
ksft_test_result_fail("FAIL (mmap() failed!): %s\n", strerror(errno));
goto close_and_return;
}
dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
memset(p, 0xff, size);
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 */
for (i = 0; i < 32; i++)
close(dmabuf_fd[i]);
ksft_test_result_pass("Allocate and fill a bunch of buffers\n");
/* Allocate and validate all buffers are zeroed */
for (i = 0; i < 32; i++) {
ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
if (ret < 0) {
printf("FAIL (Allocation (%i) failed)\n", i);
goto out;
ksft_test_result_fail("FAIL (Allocation (%i) failed) %d\n", i, ret);
goto close_and_return;
}
/* mmap and validate everything is zero */
p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
if (p == MAP_FAILED) {
printf("FAIL (mmap() failed!)\n");
ret = -1;
goto out;
ksft_test_result_fail("FAIL (mmap() failed!): %s\n", strerror(errno));
goto close_and_return;
}
dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
c = (char *)p;
for (j = 0; j < size; j++) {
if (c[j] != 0) {
printf("FAIL (Allocated buffer not zeroed @ %i)\n", j);
break;
ksft_print_msg("FAIL (Allocated buffer not zeroed @ %i)\n", j);
dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
munmap(p, size);
goto out;
}
}
dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
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:
while (i > 0) {
close(dmabuf_fd[i]);
i--;
}
ksft_test_result(i == 32, "Allocate and validate all buffers are zeroed\n");
close_and_return:
/* close them all */
for (k = 0; k < i; k++)
close(dmabuf_fd[k]);
close(heap_fd);
return ret;
return;
}
/* 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;
}
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;
int ret, heap_fd = -1, dmabuf_fd = -1;
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);
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)
close(dmabuf_fd);
if (heap_fd >= 0)
close(heap_fd);
ksft_test_result(!ret, "dmabuf_heap_alloc_older\n");
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 ret;
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);
if (!ret) {
printf("FAIL (Did not see expected error (invalid fd)!)\n");
ret = -1;
goto out;
}
ksft_test_result(ret, "Error expected on invalid fd %d\n", ret);
ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0x111111, &dmabuf_fd);
if (!ret) {
printf("FAIL (Did not see expected error (invalid heap flags)!)\n");
ret = -1;
goto out;
}
ksft_test_result(ret, "Error expected on invalid heap flags %d\n", ret);
ret = dmabuf_heap_alloc_fdflags(heap_fd, ONE_MEG,
~(O_RDWR | O_CLOEXEC), 0, &dmabuf_fd);
if (!ret) {
printf("FAIL (Did not see expected error (invalid fd flags)!)\n");
ret = -1;
goto out;
}
ksft_test_result(ret, "Error expected on invalid heap flags %d\n", ret);
printf("OK\n");
ret = 0;
out:
if (dmabuf_fd >= 0)
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)
{
DIR *d;
struct dirent *dir;
int ret = -1;
DIR *d;
ksft_print_header();
d = opendir(DEVPATH);
if (!d) {
printf("No %s directory?\n", DEVPATH);
return -1;
ksft_print_msg("No %s directory?\n", DEVPATH);
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))
continue;
if (!strncmp(dir->d_name, "..", 3))
continue;
printf("Testing heap: %s\n", dir->d_name);
printf("=======================================\n");
ret = test_alloc_and_import(dir->d_name);
if (ret)
break;
ret = test_alloc_zeroed(dir->d_name, 4 * 1024);
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;
ksft_print_msg("Testing heap: %s\n", dir->d_name);
ksft_print_msg("=======================================\n");
test_alloc_and_import(dir->d_name);
test_alloc_zeroed(dir->d_name, 4 * 1024);
test_alloc_zeroed(dir->d_name, ONE_MEG);
test_alloc_compat(dir->d_name);
test_alloc_errors(dir->d_name);
}
closedir(d);
return ret;
ksft_finished();
}
@@ -37,25 +37,25 @@ int main(void)
ksft_test_result_skip("error: unshare, errno %d\n", errno);
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)
ksft_exit_fail_msg("error: mount '/', errno %d\n", errno);
ksft_exit_fail_perror("error: mount '/'");
/* Require "exec" filesystem. */
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"
fd = creat(FILENAME, 0700);
if (fd == -1)
ksft_exit_fail_msg("error: creat, errno %d\n", errno);
ksft_exit_fail_perror("error: creat");
#define S "#!" FILENAME "\n"
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);
@@ -3,6 +3,4 @@
CFLAGS += $(KHDR_INCLUDES) -pthread
TEST_GEN_PROGS := binderfs_test
binderfs_test: binderfs_test.c ../../kselftest.h ../../kselftest_harness.h
include ../../lib.mk
@@ -3,6 +3,7 @@
#define _GNU_SOURCE
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <sched.h>
#include <fcntl.h>
+7 -1
View File
@@ -255,7 +255,13 @@ prlog() { # messages
[ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE
}
catlog() { #file
cat $1
if [ "${KTAP}" = "1" ]; then
cat $1 | while read line ; do
echo "# $line"
done
else
cat $1
fi
[ "$LOG_FILE" ] && cat $1 | strip_esc >> $LOG_FILE
}
prlog "=== Ftrace unit tests ==="
@@ -5,4 +5,4 @@
#
# Copyright (C) Arm Ltd., 2023
./ftracetest -K
./ftracetest -K -v
@@ -53,7 +53,7 @@ fi
echo > dynamic_events
if [ "$FIELDS" ] ; then
if [ "$FIELDS" -a "$FPROBES" ] ; then
echo "t:tpevent ${TP2} obj_size=s->object_size" >> 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
@@ -11,7 +11,7 @@ echo 1 > events/tests/enable
echo > trace
cat trace > /dev/null
function streq() {
streq() {
test $1 = $2
}
@@ -11,7 +11,7 @@ echo 1 > events/kprobes/enable
echo > trace
cat trace > /dev/null
function streq() {
streq() {
test $1 = $2
}
+5 -6
View File
@@ -198,13 +198,12 @@ int main(int argc, char **argv)
struct msgque_data msgque;
if (getuid() != 0)
return ksft_exit_skip(
"Please run the test as root - Exiting.\n");
ksft_exit_skip("Please run the test as root - Exiting.\n");
msgque.key = ftok(argv[0], 822155650);
if (msgque.key == -1) {
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);
@@ -243,13 +242,13 @@ int main(int argc, char **argv)
printf("Failed to test queue: %d\n", err);
goto err_out;
}
return ksft_exit_pass();
ksft_exit_pass();
err_destroy:
if (msgctl(msgque.msq_id, IPC_RMID, NULL)) {
printf("Failed to destroy queue: %d\n", -errno);
return ksft_exit_fail();
ksft_exit_fail();
}
err_out:
return ksft_exit_fail();
ksft_exit_fail();
}
+43 -6
View File
@@ -16,10 +16,12 @@
* For each test, report any progress, debugging, etc with:
*
* ksft_print_msg(fmt, ...);
* ksft_perror(msg);
*
* and finally report the pass/fail/skip/xfail state of the test with one of:
*
* ksft_test_result(condition, fmt, ...);
* ksft_test_result_report(result, fmt, ...);
* ksft_test_result_pass(fmt, ...);
* ksft_test_result_fail(fmt, ...);
* ksft_test_result_skip(fmt, ...);
@@ -39,6 +41,7 @@
* the program is aborting before finishing all tests):
*
* ksft_exit_fail_msg(fmt, ...);
* ksft_exit_fail_perror(msg);
*
*/
#ifndef __KSELFTEST_H
@@ -305,13 +308,34 @@ void ksft_test_result_code(int exit_code, const char *test_name,
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();
exit(KSFT_PASS);
}
static inline __noreturn int ksft_exit_fail(void)
static inline __noreturn void ksft_exit_fail(void)
{
ksft_print_cnts();
exit(KSFT_FAIL);
@@ -338,7 +362,7 @@ static inline __noreturn int ksft_exit_fail(void)
ksft_cnt.ksft_xfail + \
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;
va_list args;
@@ -353,19 +377,32 @@ static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg,
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();
exit(KSFT_XFAIL);
}
static inline __noreturn int ksft_exit_xpass(void)
static inline __noreturn void ksft_exit_xpass(void)
{
ksft_print_cnts();
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;
va_list args;
@@ -43,7 +43,7 @@ __ktap_test() {
directive="$3" # optional
local directive_str=
[[ ! -z "$directive" ]] && directive_str="# $directive"
[ ! -z "$directive" ] && directive_str="# $directive"
echo $result $KTAP_TESTNO $description $directive_str
@@ -99,7 +99,7 @@ ktap_exit_fail_msg() {
ktap_finished() {
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"
else
exit "$KSFT_FAIL"
@@ -244,6 +244,7 @@ l4_test()
l5_test()
{
tests=$(find $(dirname "$test") -type f -name "*.mk")
[[ -z "${tests// }" ]] && return
test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \
cut -d "=" -f 2)
+1 -1
View File
@@ -51,7 +51,7 @@
#define __KSELFTEST_HARNESS_H
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
static_assert(0, "kselftest harness requires _GNU_SOURCE to be defined");
#endif
#include <asm/types.h>
#include <ctype.h>
+11 -3
View File
@@ -7,6 +7,8 @@ else ifneq ($(filter -%,$(LLVM)),)
LLVM_SUFFIX := $(LLVM)
endif
CLANG := $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi
CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu
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_x86 := x86_64-linux-gnu
CLANG_TARGET_FLAGS_x86_64 := x86_64-linux-gnu
CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
# 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))
endif
ifeq ($(CROSS_COMPILE),)
ifeq ($(CLANG_TARGET_FLAGS),)
@@ -30,7 +38,7 @@ else
CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
endif # CROSS_COMPILE
CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as
CC := $(CLANG) $(CLANG_FLAGS) -fintegrated-as
else
CC := $(CROSS_COMPILE)gcc
endif # LLVM
@@ -45,7 +53,7 @@ selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
top_srcdir = $(selfdir)/../../..
ifeq ($(KHDR_INCLUDES),)
KHDR_INCLUDES := -isystem $(top_srcdir)/usr/include
KHDR_INCLUDES := -D_GNU_SOURCE -isystem $(top_srcdir)/usr/include
endif
# The following are built by lib.mk common compile rules.
@@ -69,5 +69,5 @@ int main(int argc, char **argv)
/* Multi-threaded */
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);
return ksft_exit_pass();
ksft_exit_pass();
}
+3 -3
View File
@@ -177,7 +177,7 @@ int main(int argc, char **argv)
ksft_print_header();
if (prereq() || geteuid())
return ksft_exit_skip("Prerequisites unsatisfied\n");
ksft_exit_skip("Prerequisites unsatisfied\n");
ksft_set_plan(1);
@@ -225,7 +225,7 @@ int main(int argc, char **argv)
}
if (check_compaction(mem_free, hugepage_size) == 0)
return ksft_exit_pass();
ksft_exit_pass();
return ksft_exit_fail();
ksft_exit_fail();
}
+1 -1
View File
@@ -1779,5 +1779,5 @@ int main(int argc, char **argv)
if (err)
ksft_exit_fail_msg("%d out of %d tests failed\n",
err, ksft_test_num());
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -456,5 +456,5 @@ int main(int argc, char **argv)
if (err)
ksft_exit_fail_msg("%d out of %d tests failed\n",
err, ksft_test_num());
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -228,7 +228,7 @@ int main(int argc, char **argv)
break;
}
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);
@@ -267,5 +267,5 @@ int main(int argc, char **argv)
free(tid);
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -646,5 +646,5 @@ int main(int argc, char **argv)
if (err)
ksft_exit_fail_msg("%d out of %d tests failed\n",
err, ksft_test_num());
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -307,5 +307,5 @@ int main(int argc, char **argv)
if (err)
ksft_exit_fail_msg("%d out of %d tests failed\n",
err, ksft_test_num());
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -375,5 +375,5 @@ int main(void)
if (err)
ksft_exit_fail_msg("%d out of %d tests failed\n",
err, ksft_test_num());
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -1484,7 +1484,7 @@ int main(int argc, char *argv[])
ksft_print_header();
if (init_uffd())
return ksft_exit_pass();
ksft_exit_pass();
ksft_set_plan(115);
@@ -1660,5 +1660,5 @@ int main(int argc, char *argv[])
userfaultfd_tests();
close(pagemap_fd);
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -209,5 +209,5 @@ int main(int argc, char **argv)
close(pagemap_fd);
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -27,6 +27,7 @@
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
@@ -600,6 +601,25 @@ int expect_strne(const char *expr, int llen, const char *cmp)
return ret;
}
#define EXPECT_STRBUFEQ(cond, expr, buf, val, cmp) \
do { if (!(cond)) result(llen, SKIPPED); else ret += expect_str_buf_eq(expr, buf, val, llen, cmp); } while (0)
static __attribute__((unused))
int expect_str_buf_eq(size_t expr, const char *buf, size_t val, int llen, const char *cmp)
{
llen += printf(" = %lu <%s> ", expr, buf);
if (strcmp(buf, cmp) != 0) {
result(llen, FAIL);
return 1;
}
if (expr != val) {
result(llen, FAIL);
return 1;
}
result(llen, OK);
return 0;
}
/* declare tests based on line numbers. There must be exactly one test per line. */
#define CASE_TEST(name) \
@@ -761,6 +781,45 @@ int test_stat_timestamps(void)
return 0;
}
int test_uname(void)
{
struct utsname buf;
char osrelease[sizeof(buf.release)];
ssize_t r;
int fd;
memset(&buf.domainname, 'P', sizeof(buf.domainname));
if (uname(&buf))
return 1;
if (strncmp("Linux", buf.sysname, sizeof(buf.sysname)))
return 1;
fd = open("/proc/sys/kernel/osrelease", O_RDONLY);
if (fd == -1)
return 1;
r = read(fd, osrelease, sizeof(osrelease));
if (r == -1)
return 1;
close(fd);
if (osrelease[r - 1] == '\n')
r--;
/* Validate one of the later fields to ensure field sizes are correct */
if (strncmp(osrelease, buf.release, r))
return 1;
/* Ensure the field domainname is set, it is missing from struct old_utsname */
if (strnlen(buf.domainname, sizeof(buf.domainname)) == sizeof(buf.domainname))
return 1;
return 0;
}
int test_mmap_munmap(void)
{
int ret, fd, i, page_size;
@@ -966,6 +1025,8 @@ int run_syscall(int min, int max)
CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break;
CASE_TEST(stat_timestamps); EXPECT_SYSZR(1, test_stat_timestamps()); break;
CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break;
CASE_TEST(uname); EXPECT_SYSZR(proc, test_uname()); break;
CASE_TEST(uname_fault); EXPECT_SYSER(1, uname(NULL), -1, EFAULT); break;
CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break;
CASE_TEST(unlink_blah); EXPECT_SYSER(1, unlink("/proc/self/blah"), -1, ENOENT); break;
CASE_TEST(wait_child); EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break;
@@ -991,6 +1052,14 @@ int run_stdlib(int min, int max)
for (test = min; test >= 0 && test <= max; test++) {
int llen = 0; /* line length */
/* For functions that take a long buffer, like strlcat()
* Add some more chars after the \0, to test functions that overwrite the buffer set
* the \0 at the exact right position.
*/
char buf[10] = "test123456";
buf[4] = '\0';
/* avoid leaving empty lines below, this will insert holes into
* test numbers.
*/
@@ -1007,6 +1076,19 @@ int run_stdlib(int min, int max)
CASE_TEST(strchr_foobar_z); EXPECT_STRZR(1, strchr("foobar", 'z')); break;
CASE_TEST(strrchr_foobar_o); EXPECT_STREQ(1, strrchr("foobar", 'o'), "obar"); break;
CASE_TEST(strrchr_foobar_z); EXPECT_STRZR(1, strrchr("foobar", 'z')); break;
#ifdef NOLIBC
CASE_TEST(strlcat_0); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 0), buf, 3, "test"); break;
CASE_TEST(strlcat_1); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 1), buf, 4, "test"); break;
CASE_TEST(strlcat_5); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 5), buf, 7, "test"); break;
CASE_TEST(strlcat_6); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 6), buf, 7, "testb"); break;
CASE_TEST(strlcat_7); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 7), buf, 7, "testba"); break;
CASE_TEST(strlcat_8); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 8), buf, 7, "testbar"); break;
CASE_TEST(strlcpy_0); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 0), buf, 3, "test"); break;
CASE_TEST(strlcpy_1); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 1), buf, 3, ""); break;
CASE_TEST(strlcpy_2); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 2), buf, 3, "b"); break;
CASE_TEST(strlcpy_3); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 3), buf, 3, "ba"); break;
CASE_TEST(strlcpy_4); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 4), buf, 3, "bar"); break;
#endif
CASE_TEST(memcmp_20_20); EXPECT_EQ(1, memcmp("aaa\x20", "aaa\x20", 4), 0); break;
CASE_TEST(memcmp_20_60); EXPECT_LT(1, memcmp("aaa\x20", "aaa\x60", 4), 0); break;
CASE_TEST(memcmp_60_20); EXPECT_GT(1, memcmp("aaa\x60", "aaa\x20", 4), 0); break;
@@ -307,5 +307,5 @@ int main(int argc, char **argv)
test_pidfd_fdinfo_nspid();
test_pidfd_dead_fdinfo();
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -159,5 +159,7 @@ on_error:
if (pidfd >= 0)
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");
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -572,5 +572,5 @@ int main(int argc, char **argv)
test_pidfd_send_signal_exited_fail();
test_pidfd_send_signal_recycled_pid_fail();
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -23,7 +23,7 @@ count_tests() {
total_tests=0
for i in $SUPPLIES; do
total_tests=$(("$total_tests" + "$NUM_TESTS"))
total_tests=$((total_tests + NUM_TESTS))
done
echo "$total_tests"
+3 -1
View File
@@ -5,6 +5,8 @@ CFLAGS += $(KHDR_INCLUDES)
TEST_GEN_PROGS := resctrl_tests
LOCAL_HDRS += $(wildcard *.h)
include ../lib.mk
$(OUTPUT)/resctrl_tests: $(wildcard *.[ch])
$(OUTPUT)/resctrl_tests: $(wildcard *.c)
+3 -5
View File
@@ -128,7 +128,7 @@ static int check_results(struct resctrl_val_param *param, const char *cache_type
return fail;
}
void cat_test_cleanup(void)
static void cat_test_cleanup(void)
{
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, &param, span, start_mask);
if (ret)
goto out;
return ret;
ret = check_results(&param, test->resource,
cache_total_size, full_cache_mask, start_mask);
out:
cat_test_cleanup();
return ret;
}
@@ -373,6 +370,7 @@ struct resctrl_test l3_cat_test = {
.resource = "L3",
.feature_check = test_resource_feature_check,
.run_test = cat_run_test,
.cleanup = cat_test_cleanup,
};
struct resctrl_test l3_noncont_cat_test = {
+4 -4
View File
@@ -40,11 +40,11 @@ static int show_results_info(unsigned long sum_llc_val, int no_of_bits,
int ret;
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;
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",
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);
}
void cmt_test_cleanup(void)
static void cmt_test_cleanup(void)
{
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");
out:
cmt_test_cleanup();
free(span_str);
return ret;
@@ -178,4 +177,5 @@ struct resctrl_test cmt_test = {
.resource = "L3",
.feature_check = cmt_feature_check,
.run_test = cmt_run_test,
.cleanup = cmt_test_cleanup,
};
+4 -6
View File
@@ -60,8 +60,8 @@ static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
/* Memory bandwidth from 100% down to 10% */
for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
allocation++) {
unsigned long avg_bw_imc, avg_bw_resc;
unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
long avg_bw_imc, avg_bw_resc;
int avg_diff_per;
float avg_diff;
@@ -137,7 +137,7 @@ static int check_results(void)
return show_mba_info(bw_imc, bw_resc);
}
void mba_test_cleanup(void)
static void mba_test_cleanup(void)
{
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, &param);
if (ret)
goto out;
return ret;
ret = check_results();
out:
mba_test_cleanup();
return ret;
}
@@ -180,4 +177,5 @@ struct resctrl_test mba_test = {
.vendor_specific = ARCH_INTEL,
.feature_check = mba_feature_check,
.run_test = mba_run_test,
.cleanup = mba_test_cleanup,
};
+4 -6
View File
@@ -17,8 +17,8 @@
static int
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;
long avg_bw_imc = 0, avg_bw_resc = 0;
int runs, ret, avg_diff_per;
float avg_diff = 0;
@@ -105,7 +105,7 @@ static int mbm_setup(const struct resctrl_test *test,
return ret;
}
void mbm_test_cleanup(void)
static void mbm_test_cleanup(void)
{
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, &param);
if (ret)
goto out;
return ret;
ret = check_results(DEFAULT_SPAN);
if (ret && (get_vendor() == ARCH_INTEL))
ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
out:
mbm_test_cleanup();
return ret;
}
@@ -150,4 +147,5 @@ struct resctrl_test mbm_test = {
.vendor_specific = ARCH_INTEL,
.feature_check = mbm_feature_check,
.run_test = mbm_run_test,
.cleanup = mbm_test_cleanup,
};
+3 -6
View File
@@ -72,6 +72,7 @@ struct user_params {
* @disabled: Test is disabled
* @feature_check: Callback to check required resctrl features
* @run_test: Callback to run the test
* @cleanup: Callback to cleanup after the test
*/
struct resctrl_test {
const char *name;
@@ -82,6 +83,7 @@ struct resctrl_test {
bool (*feature_check)(const struct resctrl_test *test);
int (*run_test)(const struct resctrl_test *test,
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 char * const *benchmark_cmd,
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 int count_contiguous_bits(unsigned long val, unsigned int *start);
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 resource_info_unsigned_get(const char *resource, const char *filename, unsigned int *val);
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 cat_test_cleanup(void);
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_initialize_read_format(struct perf_event_read *pe_read);
+10 -16
View File
@@ -81,19 +81,11 @@ static void cmd_help(void)
printf("\t-h: help\n");
}
void tests_cleanup(void)
{
mbm_test_cleanup();
mba_test_cleanup();
cmt_test_cleanup();
cat_test_cleanup();
}
static int test_prepare(void)
static int test_prepare(const struct resctrl_test *test)
{
int res;
res = signal_handler_register();
res = signal_handler_register(test);
if (res) {
ksft_print_msg("Failed to register signal handler\n");
return res;
@@ -108,8 +100,10 @@ static int test_prepare(void)
return 0;
}
static void test_cleanup(void)
static void test_cleanup(const struct resctrl_test *test)
{
if (test->cleanup)
test->cleanup();
umount_resctrlfs();
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);
if (test_prepare()) {
if (test_prepare(test)) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
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);
cleanup:
test_cleanup();
test_cleanup(test);
}
static void init_user_params(struct user_params *uparams)
@@ -253,13 +247,13 @@ last_arg:
* 2. We execute perf commands
*/
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())
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())
return ksft_exit_skip("resctrl FS unmount failed.\n");
ksft_exit_skip("resctrl FS unmount failed.\n");
filter_dmesg();
@@ -62,6 +62,7 @@ struct imc_counter_config {
static char mbm_total_path[1024];
static int imcs;
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)
{
@@ -472,7 +473,8 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
if (bm_pid)
kill(bm_pid, SIGKILL);
umount_resctrlfs();
tests_cleanup();
if (current_test && current_test->cleanup)
current_test->cleanup();
ksft_print_msg("Ending\n\n");
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
* child process before exiting.
*/
int signal_handler_register(void)
int signal_handler_register(const struct resctrl_test *test)
{
struct sigaction sigact = {};
int ret = 0;
bm_pid = 0;
current_test = test;
sigact.sa_sigaction = ctrlc_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
@@ -510,6 +513,7 @@ void signal_handler_unregister(void)
{
struct sigaction sigact = {};
current_test = NULL;
sigact.sa_handler = SIG_DFL;
sigemptyset(&sigact.sa_mask);
if (sigaction(SIGINT, &sigact, NULL) ||
+1 -1
View File
@@ -12,7 +12,7 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
endif
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
ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \
-fno-stack-protector -mrdrnd $(INCLUDES)
-1
View File
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2016-20 Intel Corporation. */
#define _GNU_SOURCE
#include <assert.h>
#include <getopt.h>
#include <stdbool.h>
+1 -2
View File
@@ -109,6 +109,5 @@ int main(void)
ksft_exit_fail_msg("%d out of %d sync tests failed\n",
err, ksft_test_num());
/* need this return to keep gcc happy */
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -205,7 +205,7 @@ int main(int argc, char **argv)
adjtimex(&tx1);
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);
}
if (final_ret)
return ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_fail();
ksft_exit_pass();
}
+2 -2
View File
@@ -89,8 +89,8 @@ int main(int argc, char **argv)
if (ret) {
printf("[FAIL]");
return ksft_exit_fail();
ksft_exit_fail();
}
printf("[OK]");
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -257,7 +257,7 @@ int main(int argc, char **argv)
set_frequency(0.0);
if (fails)
return ksft_exit_fail();
ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_pass();
}
+5 -5
View File
@@ -268,7 +268,7 @@ int main(int argc, char **argv)
if (ret < 0) {
printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
time_state_str(ret));
return ksft_exit_fail();
ksft_exit_fail();
}
/* Validate STA_INS was set */
@@ -277,7 +277,7 @@ int main(int argc, char **argv)
if (tx.status != STA_INS && tx.status != STA_DEL) {
printf("Error: STA_INS/STA_DEL not set!: %s\n",
time_state_str(ret));
return ksft_exit_fail();
ksft_exit_fail();
}
if (tai_time) {
@@ -295,7 +295,7 @@ int main(int argc, char **argv)
se.sigev_value.sival_int = 0;
if (timer_create(CLOCK_REALTIME, &se, &tm1) == -1) {
printf("Error: timer_create failed\n");
return ksft_exit_fail();
ksft_exit_fail();
}
its1.it_value.tv_sec = next_leap;
its1.it_value.tv_nsec = 0;
@@ -366,7 +366,7 @@ int main(int argc, char **argv)
if (error_found) {
printf("Errors observed\n");
clear_time_state();
return ksft_exit_fail();
ksft_exit_fail();
}
printf("\n");
if ((iterations != -1) && !(--iterations))
@@ -374,5 +374,5 @@ int main(int argc, char **argv)
}
clear_time_state();
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -87,7 +87,7 @@ int main(void)
tv.tv_usec = 0;
if (settimeofday(&tv, NULL)) {
printf("Error: You're likely not running with proper (ie: root) permissions\n");
return ksft_exit_fail();
ksft_exit_fail();
}
tx.modes = 0;
adjtimex(&tx);
@@ -104,5 +104,5 @@ int main(void)
fflush(stdout);
}
printf("[OK]\n");
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -107,8 +107,8 @@ int main(int argc, char **argv)
ret = mqueue_lat_test();
if (ret < 0) {
printf("[FAILED]\n");
return ksft_exit_fail();
ksft_exit_fail();
}
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");
if (check_itimer(ITIMER_VIRTUAL) < 0)
return ksft_exit_fail();
ksft_exit_fail();
if (check_itimer(ITIMER_PROF) < 0)
return ksft_exit_fail();
ksft_exit_fail();
if (check_itimer(ITIMER_REAL) < 0)
return ksft_exit_fail();
ksft_exit_fail();
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
@@ -281,10 +281,10 @@ int main(int argc, char **argv)
* find a better solution.
*/
if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
return ksft_exit_fail();
ksft_exit_fail();
if (check_timer_distribution() < 0)
return ksft_exit_fail();
ksft_exit_fail();
ksft_finished();
}
+3 -3
View File
@@ -137,11 +137,11 @@ int main(int argc, char **argv)
if (tx1.offset || tx2.offset ||
tx1.freq != tx2.freq || tx1.tick != tx2.tick) {
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");
return ksft_exit_fail();
ksft_exit_fail();
}
printf(" [OK]\n");
return ksft_exit_pass();
ksft_exit_pass();
}
+2 -2
View File
@@ -128,6 +128,6 @@ out:
/* restore clock */
settime(start);
if (ret)
return ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_fail();
ksft_exit_pass();
}
+2 -2
View File
@@ -61,9 +61,9 @@ int main(int argc, char **argv)
ret = get_tai();
if (ret != i) {
printf("[FAILED] expected: %i got %i\n", i, ret);
return ksft_exit_fail();
ksft_exit_fail();
}
}
printf("[OK]\n");
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -278,6 +278,6 @@ int main(void)
ret |= do_timer_oneshot(clock_id, 0);
}
if (ret)
return ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_fail();
ksft_exit_pass();
}
+2 -2
View File
@@ -102,9 +102,9 @@ int main(int argc, char **argv)
printf("[OK]\n");
set_tz(min, dst);
return ksft_exit_pass();
ksft_exit_pass();
err:
set_tz(min, dst);
return ksft_exit_fail();
ksft_exit_fail();
}
@@ -70,8 +70,8 @@ int main(int argc, char **argv)
if (ret) {
printf("[FAILED]\n");
return ksft_exit_fail();
ksft_exit_fail();
}
printf("[OK]\n");
return ksft_exit_pass();
ksft_exit_pass();
}
+1 -1
View File
@@ -189,5 +189,5 @@ out:
/* die */
if (ret)
ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_pass();
}
@@ -324,10 +324,10 @@ int validate_set_offset(void)
int main(int argc, char **argv)
{
if (validate_freq())
return ksft_exit_fail();
ksft_exit_fail();
if (validate_set_offset())
return ksft_exit_fail();
ksft_exit_fail();
return ksft_exit_pass();
ksft_exit_pass();
}
+33 -15
View File
@@ -47,42 +47,60 @@ int main(int argc, char **argv)
int r;
char tty[PATH_MAX] = {};
struct stat st1, st2;
int result = KSFT_FAIL;
ksft_print_header();
ksft_set_plan(1);
r = readlink("/proc/self/fd/0", tty, PATH_MAX);
if (r < 0)
ksft_exit_fail_msg("readlink on /proc/self/fd/0 failed: %m\n");
if (r < 0) {
ksft_print_msg("readlink on /proc/self/fd/0 failed: %m\n");
goto out;
}
if (!tty_valid(tty))
ksft_exit_skip("invalid tty path '%s'\n", tty);
if (!tty_valid(tty)) {
ksft_print_msg("invalid tty path '%s'\n", tty);
result = KSFT_SKIP;
goto out;
}
r = stat(tty, &st1);
if (r < 0)
ksft_exit_fail_msg("stat failed on tty path '%s': %m\n", tty);
if (r < 0) {
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 */
/* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fbf47635315ab308c9b58a1ea0906e711a9228de */
sleep(10);
r = write_dev_tty();
if (r < 0)
ksft_exit_fail_msg("failed to write to /dev/tty: %s\n",
strerror(-r));
if (r < 0) {
ksft_print_msg("failed to write to /dev/tty: %s\n",
strerror(-r));
goto out;
}
r = stat(tty, &st2);
if (r < 0)
ksft_exit_fail_msg("stat failed on tty path '%s': %m\n", tty);
if (r < 0) {
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 */
if (st1.st_atim.tv_sec == st2.st_atim.tv_sec &&
st1.st_mtim.tv_sec == st2.st_mtim.tv_sec) {
ksft_test_result_fail("tty timestamps not updated\n");
ksft_exit_fail();
ksft_print_msg("tty timestamps not updated\n");
goto out;
}
ksft_test_result_pass(
ksft_print_msg(
"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();
}
+1 -1
View File
@@ -1237,5 +1237,5 @@ int main(int argc, char **argv)
ksft_set_plan(tests_cnt);
return ksft_exit_pass();
ksft_exit_pass();
}
+21 -22
View File
@@ -19,6 +19,7 @@
#include <sys/auxv.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include "../kselftest.h"
#define PAGE_SIZE 4096
@@ -29,13 +30,13 @@ static int try_to_remap(void *vdso_addr, unsigned long size)
/* Searching for memory location where to remap */
dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
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;
}
printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
vdso_addr, (unsigned long)vdso_addr + size,
dest_addr, (unsigned long)dest_addr + size);
ksft_print_msg("Moving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
vdso_addr, (unsigned long)vdso_addr + size,
dest_addr, (unsigned long)dest_addr + size);
fflush(stdout);
new_addr = mremap(vdso_addr, size, size,
@@ -43,10 +44,10 @@ static int try_to_remap(void *vdso_addr, unsigned long size)
if ((unsigned long)new_addr == (unsigned long)-1) {
munmap(dest_addr, size);
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 */
}
printf("[FAIL]\tmremap failed (%d): %m\n", errno);
ksft_print_msg("[FAIL]\tmremap failed (%d): %m\n", errno);
return 1;
}
@@ -58,11 +59,12 @@ int main(int argc, char **argv, char **envp)
{
pid_t child;
ksft_print_header();
ksft_set_plan(1);
child = fork();
if (child == -1) {
printf("[WARN]\tfailed to fork (%d): %m\n", errno);
return 1;
}
if (child == -1)
ksft_exit_fail_msg("failed to fork (%d): %m\n", errno);
if (child == 0) {
unsigned long vdso_size = PAGE_SIZE;
@@ -70,9 +72,9 @@ int main(int argc, char **argv, char **envp)
int ret = -1;
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) {
printf("[WARN]\tgetauxval failed\n");
ksft_print_msg("WARN: getauxval failed\n");
return 0;
}
@@ -92,16 +94,13 @@ int main(int argc, char **argv, char **envp)
int status;
if (waitpid(child, &status, 0) != child ||
!WIFEXITED(status)) {
printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n");
return 1;
} else if (WEXITSTATUS(status) != 0) {
printf("[FAIL]\tChild failed with %d\n",
WEXITSTATUS(status));
return 1;
}
printf("[OK]\n");
!WIFEXITED(status))
ksft_test_result_fail("mremap() of the vDSO does not work on this kernel!\n");
else if (WEXITSTATUS(status) != 0)
ksft_test_result_fail("Child failed with %d\n", WEXITSTATUS(status));
else
ksft_test_result_pass("%s\n", __func__);
}
return 0;
ksft_finished();
}
+336 -366
View File
@@ -21,6 +21,13 @@
#include <sys/uio.h>
#include "helpers.h"
#include "../kselftest.h"
#ifdef __x86_64__
#define TOTAL_TESTS 13
#else
#define TOTAL_TESTS 8
#endif
#ifdef __x86_64__
# define VSYS(x) (x)
@@ -39,18 +46,6 @@
/* max length of lines in /proc/self/maps - anything longer is skipped here */
#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 */
bool vsyscall_map_r = false, vsyscall_map_x = false;
@@ -75,83 +70,25 @@ static void init_vdso(void)
if (!vdso)
vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if (!vdso) {
printf("[WARN]\tfailed to find vDSO\n");
ksft_print_msg("[WARN] failed to find vDSO\n");
return;
}
vdso_gtod = (gtod_t)dlsym(vdso, "__vdso_gettimeofday");
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");
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");
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");
if (!vdso_getcpu)
printf("[WARN]\tfailed 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
ksft_print_msg("[WARN] failed to find getcpu in vDSO\n");
}
/* syscalls */
@@ -176,9 +113,221 @@ static inline long sys_getcpu(unsigned * cpu, unsigned * node,
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 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)
{
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);
}
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) +
(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");
ksft_print_msg("Checking read access to the vsyscall page\n");
bool can_read;
if (sigsetjmp(jmpbuf, 1) == 0) {
*(volatile int *)0xffffffffff600000;
@@ -408,32 +347,25 @@ static int test_vsys_r(void)
can_read = false;
}
if (can_read && !vsyscall_map_r) {
printf("[FAIL]\tWe have read access, but we shouldn't\n");
return 1;
} else if (!can_read && vsyscall_map_r) {
printf("[FAIL]\tWe don't have read access, but we should\n");
return 1;
} else if (can_read) {
printf("[OK]\tWe have read access\n");
} else {
printf("[OK]\tWe do not have read access: #PF(0x%lx)\n",
segv_err);
}
#endif
return 0;
if (can_read && !vsyscall_map_r)
ksft_test_result_fail("We have read access, but we shouldn't\n");
else if (!can_read && vsyscall_map_r)
ksft_test_result_fail("We don't have read access, but we should\n");
else if (can_read)
ksft_test_result_pass("We have read access\n");
else
ksft_test_result_pass("We do not have read access: #PF(0x%lx)\n", segv_err);
}
static int test_vsys_x(void)
static void test_vsys_x(void)
{
#ifdef __x86_64__
if (vsyscall_map_x) {
/* 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;
if (sigsetjmp(jmpbuf, 1) == 0) {
@@ -443,20 +375,14 @@ static int test_vsys_x(void)
can_exec = false;
}
if (can_exec) {
printf("[FAIL]\tExecuting the vsyscall did not page fault\n");
return 1;
} else if (segv_err & (1 << 4)) { /* INSTR */
printf("[OK]\tExecuting the vsyscall page failed: #PF(0x%lx)\n",
segv_err);
} else {
printf("[FAIL]\tExecution failed with the wrong error: #PF(0x%lx)\n",
segv_err);
return 1;
}
#endif
return 0;
if (can_exec)
ksft_test_result_fail("Executing the vsyscall did not page fault\n");
else if (segv_err & (1 << 4)) /* INSTR */
ksft_test_result_pass("Executing the vsyscall page failed: #PF(0x%lx)\n",
segv_err);
else
ksft_test_result_fail("Execution failed with the wrong error: #PF(0x%lx)\n",
segv_err);
}
/*
@@ -470,14 +396,13 @@ static int test_vsys_x(void)
* fact that ptrace() ever worked was a nice courtesy of old kernels,
* 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];
struct iovec local, remote;
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_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
* vsyscall page is readable.
*/
printf("[%s]\tprocess_vm_readv() failed (ret = %d, errno = %d)\n", vsyscall_map_r ? "FAIL" : "OK", ret, errno);
return vsyscall_map_r ? 1 : 0;
ksft_test_result(!vsyscall_map_r,
"process_vm_readv() failed (ret = %d, errno = %d)\n", ret, errno);
return;
}
if (vsyscall_map_r) {
if (!memcmp(buf, remote.iov_base, sizeof(buf))) {
printf("[OK]\tIt worked and read correct data\n");
} else {
printf("[FAIL]\tIt worked but returned incorrect data\n");
return 1;
}
} else {
printf("[FAIL]\tprocess_rm_readv() succeeded, but it should have failed in this configuration\n");
return 1;
}
#endif
return 0;
if (vsyscall_map_r)
ksft_test_result(!memcmp(buf, remote.iov_base, sizeof(buf)), "Read data\n");
else
ksft_test_result_fail("process_rm_readv() succeeded, but it should have failed in this configuration\n");
}
static void init_vsys(void)
{
int nerrs = 0;
FILE *maps;
char line[MAPS_LINE_LEN];
bool found = false;
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 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++;
}
static int test_emulation(void)
static void test_emulation(void)
{
time_t tmp;
bool is_native;
if (!vsyscall_map_x)
return 0;
if (!vsyscall_map_x) {
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);
set_eflags(get_eflags() | X86_EFLAGS_TF);
vtime(&tmp);
@@ -545,36 +516,35 @@ static int test_emulation(void)
*/
is_native = (num_vsyscall_traps > 1);
printf("[%s]\tvsyscalls are %s (%d instructions in vsyscall page)\n",
(is_native ? "FAIL" : "OK"),
(is_native ? "native" : "emulated"),
(int)num_vsyscall_traps);
return is_native;
ksft_test_result(!is_native, "vsyscalls are %s (%d instructions in vsyscall page)\n",
(is_native ? "native" : "emulated"), (int)num_vsyscall_traps);
}
#endif
int main(int argc, char **argv)
{
int nerrs = 0;
int total_tests = TOTAL_TESTS;
ksft_print_header();
ksft_set_plan(total_tests);
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__
nerrs += test_emulation();
init_vsys();
#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();
}