summaryrefslogtreecommitdiff
path: root/mali_kbase/tests/kutf
diff options
context:
space:
mode:
authorJörg Wagner <jorwag@google.com>2023-12-14 09:44:26 +0000
committerJörg Wagner <jorwag@google.com>2023-12-14 09:44:26 +0000
commit049a542207ed694271316782397b78b2e202086a (patch)
tree105e9378d4d5062dc72109fdd4a77c915bd9425d /mali_kbase/tests/kutf
parente61eb93296e9f940b32d4ad4b0c3a5557cbeaf17 (diff)
downloadgpu-049a542207ed694271316782397b78b2e202086a.tar.gz
Update KMD to r47p0
Provenance: ipdelivery@ad01e50d640910a99224382bb227e6d4de627657 Change-Id: I19ac9bce34a5c5a319c1b4a388e8b037b3dfe6e7
Diffstat (limited to 'mali_kbase/tests/kutf')
-rw-r--r--mali_kbase/tests/kutf/Kbuild5
-rw-r--r--mali_kbase/tests/kutf/build.bp3
-rw-r--r--mali_kbase/tests/kutf/kutf_helpers.c13
-rw-r--r--mali_kbase/tests/kutf/kutf_helpers_user.c160
-rw-r--r--mali_kbase/tests/kutf/kutf_kprobe.c344
-rw-r--r--mali_kbase/tests/kutf/kutf_mem.c4
-rw-r--r--mali_kbase/tests/kutf/kutf_resultset.c18
-rw-r--r--mali_kbase/tests/kutf/kutf_suite.c334
-rw-r--r--mali_kbase/tests/kutf/kutf_utils.c11
9 files changed, 600 insertions, 292 deletions
diff --git a/mali_kbase/tests/kutf/Kbuild b/mali_kbase/tests/kutf/Kbuild
index c4790bc..aef44e0 100644
--- a/mali_kbase/tests/kutf/Kbuild
+++ b/mali_kbase/tests/kutf/Kbuild
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
-# (C) COPYRIGHT 2017, 2020-2021 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2017, 2020-2023 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -27,5 +27,6 @@ kutf-y := \
kutf_suite.o \
kutf_utils.o \
kutf_helpers.o \
- kutf_helpers_user.o
+ kutf_helpers_user.o \
+ kutf_kprobe.o
endif
diff --git a/mali_kbase/tests/kutf/build.bp b/mali_kbase/tests/kutf/build.bp
index 89edae9..267c14b 100644
--- a/mali_kbase/tests/kutf/build.bp
+++ b/mali_kbase/tests/kutf/build.bp
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
- * (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -34,6 +34,7 @@ bob_kernel_module {
"kutf_resultset.c",
"kutf_suite.c",
"kutf_utils.c",
+ "kutf_kprobe.c",
],
enabled: false,
mali_kutf: {
diff --git a/mali_kbase/tests/kutf/kutf_helpers.c b/mali_kbase/tests/kutf/kutf_helpers.c
index 4273619..e0fe598 100644
--- a/mali_kbase/tests/kutf/kutf_helpers.c
+++ b/mali_kbase/tests/kutf/kutf_helpers.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2017, 2020-2022 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -59,7 +59,7 @@ char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
spin_unlock(&kutf_input_lock);
err = wait_event_interruptible(context->userdata.input_waitq,
- kutf_helper_pending_input(context));
+ kutf_helper_pending_input(context));
if (err)
return ERR_PTR(-EINTR);
@@ -67,8 +67,7 @@ char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
spin_lock(&kutf_input_lock);
}
- line = list_first_entry(&context->userdata.input_head,
- struct kutf_userdata_line, node);
+ line = list_first_entry(&context->userdata.input_head, struct kutf_userdata_line, node);
if (line->str) {
/*
* Unless it is the end-of-input marker,
@@ -84,13 +83,11 @@ char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
return line->str;
}
-int kutf_helper_input_enqueue(struct kutf_context *context,
- const char __user *str, size_t size)
+int kutf_helper_input_enqueue(struct kutf_context *context, const char __user *str, size_t size)
{
struct kutf_userdata_line *line;
- line = kutf_mempool_alloc(&context->fixture_pool,
- sizeof(*line) + size + 1);
+ line = kutf_mempool_alloc(&context->fixture_pool, sizeof(*line) + size + 1);
if (!line)
return -ENOMEM;
if (str) {
diff --git a/mali_kbase/tests/kutf/kutf_helpers_user.c b/mali_kbase/tests/kutf/kutf_helpers_user.c
index c4e2943..a69c791 100644
--- a/mali_kbase/tests/kutf/kutf_helpers_user.c
+++ b/mali_kbase/tests/kutf/kutf_helpers_user.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2017, 2020-2022 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -56,11 +56,12 @@ static const char *get_val_type_name(enum kutf_helper_valtype valtype)
* - Has between 1 and KUTF_HELPER_MAX_VAL_NAME_LEN characters before the \0 terminator
* - And, each char is in the character set [A-Z0-9_]
*/
-static int validate_val_name(const char *val_str, int str_len)
+static int validate_val_name(const char *val_str, size_t str_len)
{
int i = 0;
- for (i = 0; str_len && i <= KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0'; ++i, --str_len) {
+ for (i = 0; str_len && i <= KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0';
+ ++i, --str_len) {
char val_chr = val_str[i];
if (val_chr >= 'A' && val_chr <= 'Z')
@@ -78,7 +79,8 @@ static int validate_val_name(const char *val_str, int str_len)
if (i == 0)
return 1;
/* Length greater than KUTF_HELPER_MAX_VAL_NAME_LEN not allowed */
- if (i > KUTF_HELPER_MAX_VAL_NAME_LEN || (i == KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0'))
+ if (i > KUTF_HELPER_MAX_VAL_NAME_LEN ||
+ (i == KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0'))
return 1;
return 0;
@@ -90,32 +92,31 @@ static int validate_val_name(const char *val_str, int str_len)
* That is, before any '\\', '\n' or '"' characters. This is so we don't have
* to escape the string
*/
-static int find_quoted_string_valid_len(const char *str)
+static size_t find_quoted_string_valid_len(const char *str)
{
char *ptr;
const char *check_chars = "\\\n\"";
ptr = strpbrk(str, check_chars);
if (ptr)
- return (int)(ptr-str);
+ return (size_t)(ptr - str);
- return (int)strlen(str);
+ return strlen(str);
}
-static int kutf_helper_userdata_enqueue(struct kutf_context *context,
- const char *str)
+static int kutf_helper_userdata_enqueue(struct kutf_context *context, const char *str)
{
char *str_copy;
size_t len;
int err;
- len = strlen(str)+1;
+ len = strlen(str) + 1;
str_copy = kutf_mempool_alloc(&context->fixture_pool, len);
if (!str_copy)
return -ENOMEM;
- strcpy(str_copy, str);
+ strscpy(str_copy, str, len);
err = kutf_add_result(context, KUTF_RESULT_USERDATA, str_copy);
@@ -126,8 +127,7 @@ static int kutf_helper_userdata_enqueue(struct kutf_context *context,
/* (Name size) + ("=0x" size) + (64-bit hex value size) + (terminator) */
#define NAMED_U64_VAL_BUF_SZ (KUTF_HELPER_MAX_VAL_NAME_LEN + 3 + MAX_U64_HEX_LEN + 1)
-int kutf_helper_send_named_u64(struct kutf_context *context,
- const char *val_name, u64 val)
+int kutf_helper_send_named_u64(struct kutf_context *context, const char *val_name, u64 val)
{
int ret = 1;
char msgbuf[NAMED_U64_VAL_BUF_SZ];
@@ -135,23 +135,25 @@ int kutf_helper_send_named_u64(struct kutf_context *context,
if (validate_val_name(val_name, KUTF_HELPER_MAX_VAL_NAME_LEN + 1)) {
errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send u64 value named '%s': Invalid value name", val_name);
+ "Failed to send u64 value named '%s': Invalid value name",
+ val_name);
goto out_err;
}
ret = snprintf(msgbuf, NAMED_U64_VAL_BUF_SZ, "%s=0x%llx", val_name, val);
if (ret >= NAMED_U64_VAL_BUF_SZ || ret < 0) {
- errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send u64 value named '%s': snprintf() problem buffer size==%d ret=%d",
- val_name, NAMED_U64_VAL_BUF_SZ, ret);
+ errmsg = kutf_dsprintf(
+ &context->fixture_pool,
+ "Failed to send u64 value named '%s': snprintf() problem buffer size==%d ret=%d",
+ val_name, NAMED_U64_VAL_BUF_SZ, ret);
goto out_err;
}
ret = kutf_helper_userdata_enqueue(context, msgbuf);
if (ret) {
errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send u64 value named '%s': send returned %d",
- val_name, ret);
+ "Failed to send u64 value named '%s': send returned %d",
+ val_name, ret);
goto out_err;
}
@@ -166,8 +168,7 @@ EXPORT_SYMBOL(kutf_helper_send_named_u64);
#define NAMED_STR_START_DELIM NAMED_VALUE_SEP "\""
#define NAMED_STR_END_DELIM "\""
-int kutf_helper_max_str_len_for_kern(const char *val_name,
- int kern_buf_sz)
+int kutf_helper_max_str_len_for_kern(const char *val_name, int kern_buf_sz)
{
const int val_name_len = strlen(val_name);
const int start_delim_len = strlen(NAMED_STR_START_DELIM);
@@ -175,30 +176,29 @@ int kutf_helper_max_str_len_for_kern(const char *val_name,
int max_msg_len = kern_buf_sz;
int max_str_len;
- max_str_len = max_msg_len - val_name_len - start_delim_len -
- end_delim_len;
+ max_str_len = max_msg_len - val_name_len - start_delim_len - end_delim_len;
return max_str_len;
}
EXPORT_SYMBOL(kutf_helper_max_str_len_for_kern);
-int kutf_helper_send_named_str(struct kutf_context *context,
- const char *val_name,
- const char *val_str)
+int kutf_helper_send_named_str(struct kutf_context *context, const char *val_name,
+ const char *val_str)
{
- int val_str_len;
- int str_buf_sz;
+ size_t val_str_len;
+ size_t str_buf_sz;
char *str_buf = NULL;
int ret = 1;
char *copy_ptr;
- int val_name_len;
- int start_delim_len = strlen(NAMED_STR_START_DELIM);
- int end_delim_len = strlen(NAMED_STR_END_DELIM);
+ size_t val_name_len;
+ size_t start_delim_len = strlen(NAMED_STR_START_DELIM);
+ size_t end_delim_len = strlen(NAMED_STR_END_DELIM);
const char *errmsg = NULL;
if (validate_val_name(val_name, KUTF_HELPER_MAX_VAL_NAME_LEN + 1)) {
errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send u64 value named '%s': Invalid value name", val_name);
+ "Failed to send u64 value named '%s': Invalid value name",
+ val_name);
goto out_err;
}
val_name_len = strlen(val_name);
@@ -213,9 +213,10 @@ int kutf_helper_send_named_str(struct kutf_context *context,
*/
str_buf = kmalloc(str_buf_sz, GFP_KERNEL);
if (!str_buf) {
- errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send str value named '%s': kmalloc failed, str_buf_sz=%d",
- val_name, str_buf_sz);
+ errmsg = kutf_dsprintf(
+ &context->fixture_pool,
+ "Failed to send str value named '%s': kmalloc failed, str_buf_sz=%zu",
+ val_name, str_buf_sz);
goto out_err;
}
copy_ptr = str_buf;
@@ -247,8 +248,8 @@ int kutf_helper_send_named_str(struct kutf_context *context,
if (ret) {
errmsg = kutf_dsprintf(&context->fixture_pool,
- "Failed to send str value named '%s': send returned %d",
- val_name, ret);
+ "Failed to send str value named '%s': send returned %d",
+ val_name, ret);
goto out_err;
}
@@ -262,16 +263,15 @@ out_err:
}
EXPORT_SYMBOL(kutf_helper_send_named_str);
-int kutf_helper_receive_named_val(
- struct kutf_context *context,
- struct kutf_helper_named_val *named_val)
+int kutf_helper_receive_named_val(struct kutf_context *context,
+ struct kutf_helper_named_val *named_val)
{
size_t recv_sz;
char *recv_str;
char *search_ptr;
char *name_str = NULL;
- int name_len;
- int strval_len;
+ size_t name_len;
+ size_t strval_len;
enum kutf_helper_valtype type = KUTF_HELPER_VALTYPE_INVALID;
char *strval = NULL;
u64 u64val = 0;
@@ -286,7 +286,7 @@ int kutf_helper_receive_named_val(
/* Find the '=', grab the name and validate it */
search_ptr = strnchr(recv_str, recv_sz, NAMED_VALUE_SEP[0]);
if (search_ptr) {
- name_len = search_ptr - recv_str;
+ name_len = (size_t)(search_ptr - recv_str);
if (!validate_val_name(recv_str, name_len)) {
/* no need to reallocate - just modify string in place */
name_str = recv_str;
@@ -298,8 +298,7 @@ int kutf_helper_receive_named_val(
}
}
if (!name_str) {
- pr_err("Invalid name part for received string '%s'\n",
- recv_str);
+ pr_err("Invalid name part for received string '%s'\n", recv_str);
return KUTF_HELPER_ERR_INVALID_NAME;
}
@@ -312,7 +311,7 @@ int kutf_helper_receive_named_val(
/* Find end of string */
search_ptr = strnchr(recv_str, recv_sz, NAMED_STR_END_DELIM[0]);
if (search_ptr) {
- strval_len = search_ptr - recv_str;
+ strval_len = (size_t)(search_ptr - recv_str);
/* Validate the string to ensure it contains no quotes */
if (strval_len == find_quoted_string_valid_len(recv_str)) {
/* no need to reallocate - just modify string in place */
@@ -324,11 +323,13 @@ int kutf_helper_receive_named_val(
recv_sz -= (strval_len + 1);
type = KUTF_HELPER_VALTYPE_STR;
} else {
- pr_err("String value contains invalid characters in rest of received string '%s'\n", recv_str);
+ pr_err("String value contains invalid characters in rest of received string '%s'\n",
+ recv_str);
err = KUTF_HELPER_ERR_CHARS_AFTER_VAL;
}
} else {
- pr_err("End of string delimiter not found in rest of received string '%s'\n", recv_str);
+ pr_err("End of string delimiter not found in rest of received string '%s'\n",
+ recv_str);
err = KUTF_HELPER_ERR_NO_END_DELIMITER;
}
} else {
@@ -338,14 +339,15 @@ int kutf_helper_receive_named_val(
* reads characters after the number it'll report -EINVAL
*/
if (!err) {
- int len_remain = strnlen(recv_str, recv_sz);
+ size_t len_remain = strnlen(recv_str, recv_sz);
type = KUTF_HELPER_VALTYPE_U64;
recv_str += len_remain;
recv_sz -= len_remain;
} else {
/* special case: not a number, report as such */
- pr_err("Rest of received string was not a numeric value or quoted string value: '%s'\n", recv_str);
+ pr_err("Rest of received string was not a numeric value or quoted string value: '%s'\n",
+ recv_str);
}
}
@@ -354,8 +356,8 @@ int kutf_helper_receive_named_val(
/* Any remaining characters - error */
if (strnlen(recv_str, recv_sz) != 0) {
- pr_err("Characters remain after value of type %s: '%s'\n",
- get_val_type_name(type), recv_str);
+ pr_err("Characters remain after value of type %s: '%s'\n", get_val_type_name(type),
+ recv_str);
return KUTF_HELPER_ERR_CHARS_AFTER_VAL;
}
@@ -381,44 +383,41 @@ int kutf_helper_receive_named_val(
EXPORT_SYMBOL(kutf_helper_receive_named_val);
#define DUMMY_MSG "<placeholder due to test fail>"
-int kutf_helper_receive_check_val(
- struct kutf_helper_named_val *named_val,
- struct kutf_context *context,
- const char *expect_val_name,
- enum kutf_helper_valtype expect_val_type)
+int kutf_helper_receive_check_val(struct kutf_helper_named_val *named_val,
+ struct kutf_context *context, const char *expect_val_name,
+ enum kutf_helper_valtype expect_val_type)
{
int err;
err = kutf_helper_receive_named_val(context, named_val);
if (err < 0) {
const char *msg = kutf_dsprintf(&context->fixture_pool,
- "Failed to receive value named '%s'",
- expect_val_name);
+ "Failed to receive value named '%s'",
+ expect_val_name);
kutf_test_fail(context, msg);
return err;
} else if (err > 0) {
- const char *msg = kutf_dsprintf(&context->fixture_pool,
- "Named-value parse error when expecting value named '%s'",
- expect_val_name);
+ const char *msg = kutf_dsprintf(
+ &context->fixture_pool,
+ "Named-value parse error when expecting value named '%s'", expect_val_name);
kutf_test_fail(context, msg);
goto out_fail_and_fixup;
}
- if (named_val->val_name != NULL &&
- strcmp(named_val->val_name, expect_val_name) != 0) {
- const char *msg = kutf_dsprintf(&context->fixture_pool,
- "Expecting to receive value named '%s' but got '%s'",
- expect_val_name, named_val->val_name);
+ if (named_val->val_name != NULL && strcmp(named_val->val_name, expect_val_name) != 0) {
+ const char *msg =
+ kutf_dsprintf(&context->fixture_pool,
+ "Expecting to receive value named '%s' but got '%s'",
+ expect_val_name, named_val->val_name);
kutf_test_fail(context, msg);
goto out_fail_and_fixup;
}
-
if (named_val->type != expect_val_type) {
- const char *msg = kutf_dsprintf(&context->fixture_pool,
- "Expecting value named '%s' to be of type %s but got %s",
- expect_val_name, get_val_type_name(expect_val_type),
- get_val_type_name(named_val->type));
+ const char *msg = kutf_dsprintf(
+ &context->fixture_pool,
+ "Expecting value named '%s' to be of type %s but got %s", expect_val_name,
+ get_val_type_name(expect_val_type), get_val_type_name(named_val->type));
kutf_test_fail(context, msg);
goto out_fail_and_fixup;
}
@@ -431,17 +430,16 @@ out_fail_and_fixup:
case KUTF_HELPER_VALTYPE_U64:
named_val->u.val_u64 = 0ull;
break;
- case KUTF_HELPER_VALTYPE_STR:
- {
- char *str = kutf_mempool_alloc(&context->fixture_pool, sizeof(DUMMY_MSG));
+ case KUTF_HELPER_VALTYPE_STR: {
+ char *str = kutf_mempool_alloc(&context->fixture_pool, sizeof(DUMMY_MSG));
- if (!str)
- return -1;
+ if (!str)
+ return -1;
- strcpy(str, DUMMY_MSG);
- named_val->u.val_str = str;
- break;
- }
+ strcpy(str, DUMMY_MSG);
+ named_val->u.val_str = str;
+ break;
+ }
default:
break;
}
diff --git a/mali_kbase/tests/kutf/kutf_kprobe.c b/mali_kbase/tests/kutf/kutf_kprobe.c
new file mode 100644
index 0000000..f118692
--- /dev/null
+++ b/mali_kbase/tests/kutf/kutf_kprobe.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+/*
+ *
+ * (C) COPYRIGHT 2023 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ */
+
+/* Kernel probe functionality.
+ */
+
+#ifdef CONFIG_KPROBES
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/kprobes.h>
+#include <linux/version.h>
+#include <kutf/kutf_kprobe.h>
+
+#define KUTF_KP_REG_MIN_ARGS 3
+#define KUTF_KP_UNREG_MIN_ARGS 2
+#define KUTF_KP_FUNC_NAME_ARG 0
+#define KUTF_KP_FUNC_ENTRY_EXIT_ARG 1
+#define KUTF_KP_FUNC_HANDLER_ARG 2
+
+#define KUTF_KP_WRITE_BUFSIZE 4096
+
+/* Stores address to kernel function 'kallsyms_lookup_name'
+ * as 'kallsyms_lookup_name' is no longer exported from 5.7 kernel.
+ */
+typedef unsigned long (*kallsyms_lookup_name_t)(const char *name);
+kallsyms_lookup_name_t kutf_ksym_lookup_name;
+
+static ssize_t kutf_kp_reg_debugfs_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos);
+
+static ssize_t kutf_kp_unreg_debugfs_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos);
+
+static LIST_HEAD(kp_list);
+static DEFINE_MUTEX(kp_list_lock);
+
+/**
+ * struct kutf_kp_data - Structure which holds data per kprobe instance
+ * @kretp: reference to kernel ret probe
+ * @entry: true if this probe is for function entry.Otherwise it is exit.
+ * @argc: Number of arguments to be passed to probe handler
+ * @argv: arguments passed to probe handler
+ * @kp_handler: Actual handler which is called when probe is triggered
+ * @list: node for adding to kp_list
+ */
+struct kutf_kp_data {
+ struct kretprobe kretp;
+ bool entry;
+ int argc;
+ char **argv;
+ kutf_kp_handler kp_handler;
+ struct list_head list;
+};
+
+const struct file_operations kutf_kp_reg_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = kutf_kp_reg_debugfs_write,
+};
+
+const struct file_operations kutf_kp_unreg_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = kutf_kp_unreg_debugfs_write,
+};
+
+struct kprobe kutf_kallsym_kp = { .symbol_name = "kallsyms_lookup_name" };
+
+void kutf_kp_sample_kernel_function(void)
+{
+ pr_debug("%s called\n", __func__);
+}
+EXPORT_SYMBOL(kutf_kp_sample_kernel_function);
+
+void kutf_kp_sample_handler(int argc, char **argv)
+{
+ int i = 0;
+
+ for (; i < argc; i++)
+ pr_info("%s %s\n", __func__, argv[i]);
+}
+EXPORT_SYMBOL(kutf_kp_sample_handler);
+
+static int kutf_call_kp_handler(struct kretprobe *p)
+{
+ struct kutf_kp_data *kp_p;
+ kutf_kp_handler kp_handler;
+
+ kp_p = (struct kutf_kp_data *)p;
+ kp_handler = kp_p->kp_handler;
+
+ if (kp_handler) {
+ /* Arguments to registered handler starts after
+ * KUTF_KP_REG_MIN_ARGS.
+ */
+ (*kp_handler)((kp_p->argc) - KUTF_KP_REG_MIN_ARGS,
+ &(kp_p->argv[KUTF_KP_REG_MIN_ARGS]));
+ }
+ return 0;
+}
+
+static int kutf_kretp_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+#if (KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE)
+ return kutf_call_kp_handler(ri->rph->rp);
+#else
+ return kutf_call_kp_handler(ri->rp);
+#endif
+}
+
+static kutf_kp_handler kutf_get_kp_handler(char **argv)
+{
+ if ((NULL == argv) || (NULL == kutf_ksym_lookup_name))
+ return NULL;
+
+ return (kutf_kp_handler)((*kutf_ksym_lookup_name)(argv[KUTF_KP_FUNC_HANDLER_ARG]));
+}
+
+static ssize_t kutf_kp_reg_debugfs_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int argc = 0;
+ int ret = count;
+ char **argv;
+ char *kbuf;
+ char *func_name;
+ struct kutf_kp_data *kp_p;
+ struct kutf_kp_data *kp_iter;
+
+ if (count >= KUTF_KP_WRITE_BUFSIZE)
+ return -EINVAL;
+
+ kbuf = memdup_user(user_buf, count);
+ if (IS_ERR(kbuf)) {
+ return -ENOMEM;
+ }
+ kbuf[count - 1] = '\0';
+
+ argv = argv_split(GFP_KERNEL, kbuf, &argc);
+ if (!argv) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (argc < KUTF_KP_REG_MIN_ARGS) {
+ pr_debug("Insufficient args in reg kprobe:%d\n", argc);
+ ret = -EINVAL;
+ goto argv_out;
+ }
+
+ kp_p = kzalloc(sizeof(struct kutf_kp_data), GFP_KERNEL);
+ if (!kp_p)
+ goto argv_out;
+
+ if (!(strcmp(argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG], "entry"))) {
+ kp_p->kretp.entry_handler = kutf_kretp_handler;
+ kp_p->entry = 1;
+ } else if (!(strcmp(argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG], "exit"))) {
+ kp_p->kretp.handler = kutf_kretp_handler;
+ } else {
+ pr_err("Invalid arg:%s passed in reg kprobe\n", argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG]);
+ ret = -EINVAL;
+ kfree(kp_p);
+ goto argv_out;
+ }
+
+ func_name = argv[KUTF_KP_FUNC_NAME_ARG];
+
+ mutex_lock(&kp_list_lock);
+ list_for_each_entry(kp_iter, &kp_list, list) {
+ if ((kp_iter->entry == kp_p->entry) &&
+ (!(strcmp(kp_iter->kretp.kp.symbol_name, func_name)))) {
+ ret = -EEXIST;
+ kfree(kp_p);
+ mutex_unlock(&kp_list_lock);
+ goto argv_out;
+ }
+ }
+
+ kp_p->kretp.kp.symbol_name = func_name;
+ kp_p->kp_handler = kutf_get_kp_handler(argv);
+ if (!(kp_p->kp_handler)) {
+ pr_debug("cannot find addr for handler:%s\n", argv[KUTF_KP_FUNC_HANDLER_ARG]);
+ ret = -EINVAL;
+ kfree(kp_p);
+ mutex_unlock(&kp_list_lock);
+ goto argv_out;
+ }
+ kp_p->argc = argc;
+ kp_p->argv = argv;
+ ret = register_kretprobe(&kp_p->kretp);
+ if (ret) {
+ ret = -EINVAL;
+ kfree(kp_p);
+ mutex_unlock(&kp_list_lock);
+ goto argv_out;
+ }
+ INIT_LIST_HEAD(&kp_p->list);
+ list_add(&kp_p->list, &kp_list);
+
+ mutex_unlock(&kp_list_lock);
+
+ ret = count;
+ goto out;
+
+argv_out:
+ argv_free(argv);
+
+out:
+ kfree(kbuf);
+
+ return ret;
+}
+
+static ssize_t kutf_kp_unreg_debugfs_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int argc = 0;
+ int ret = -EINVAL;
+ char **argv = NULL;
+ char *kbuf;
+ char *func_name;
+ struct kutf_kp_data *kp_iter;
+ bool entry;
+
+ if (count >= KUTF_KP_WRITE_BUFSIZE)
+ return -EINVAL;
+
+ kbuf = memdup_user(user_buf, count);
+ if (IS_ERR(kbuf)) {
+ return -ENOMEM;
+ }
+ kbuf[count - 1] = '\0';
+
+ argv = argv_split(GFP_KERNEL, kbuf, &argc);
+ if (!argv) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (argc < KUTF_KP_UNREG_MIN_ARGS) {
+ pr_debug("Insufficient args in unreg kprobe:%d\n", argc);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!(strcmp(argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG], "entry")))
+ entry = 1;
+ else if (!(strcmp(argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG], "exit")))
+ entry = 0;
+ else {
+ pr_err("Invalid arg:%s passed in unreg kprobe\n",
+ argv[KUTF_KP_FUNC_ENTRY_EXIT_ARG]);
+ ret = -EINVAL;
+ goto out;
+ }
+ func_name = argv[KUTF_KP_FUNC_NAME_ARG];
+
+ mutex_lock(&kp_list_lock);
+ list_for_each_entry(kp_iter, &kp_list, list) {
+ if ((kp_iter->entry == entry) &&
+ (!(strcmp(func_name, kp_iter->kretp.kp.symbol_name)))) {
+ unregister_kretprobe(&kp_iter->kretp);
+ argv_free(kp_iter->argv);
+ list_del(&kp_iter->list);
+ kfree(kp_iter);
+ ret = count;
+ break;
+ }
+ }
+ mutex_unlock(&kp_list_lock);
+out:
+ argv_free(argv);
+ kfree(kbuf);
+
+ return ret;
+}
+
+int __init kutf_kprobe_init(struct dentry *base_dir)
+{
+ struct dentry *kutf_kp_reg_debugfs_file;
+ struct dentry *kutf_kp_unreg_debugfs_file;
+
+ if (!(register_kprobe(&kutf_kallsym_kp))) {
+ /* After kernel 5.7, 'kallsyms_lookup_name' is no longer
+ * exported. So we need this workaround to get the
+ * addr of 'kallsyms_lookup_name'. This will be used later
+ * in kprobe handler function to call the registered
+ * handler for a probe from the name passed from userspace.
+ */
+ kutf_ksym_lookup_name = (kallsyms_lookup_name_t)kutf_kallsym_kp.addr;
+ unregister_kprobe(&kutf_kallsym_kp);
+ kutf_kp_reg_debugfs_file = debugfs_create_file("register_kprobe", 0200, base_dir,
+ NULL, &kutf_kp_reg_debugfs_fops);
+ if (IS_ERR_OR_NULL(kutf_kp_reg_debugfs_file))
+ pr_err("Failed to create kprobe reg debugfs file");
+
+ kutf_kp_unreg_debugfs_file = debugfs_create_file(
+ "unregister_kprobe", 0200, base_dir, NULL, &kutf_kp_unreg_debugfs_fops);
+ if (IS_ERR_OR_NULL(kutf_kp_unreg_debugfs_file)) {
+ pr_err("Failed to create kprobe unreg debugfs file");
+ debugfs_remove(kutf_kp_reg_debugfs_file);
+ }
+ } else
+ pr_info("kallsyms_lookup_name addr not available\n");
+
+ return 0;
+}
+
+void kutf_kprobe_exit(void)
+{
+ struct kutf_kp_data *kp_iter;
+ struct kutf_kp_data *n;
+
+ mutex_lock(&kp_list_lock);
+
+ list_for_each_entry_safe(kp_iter, n, &kp_list, list) {
+ unregister_kretprobe(&kp_iter->kretp);
+ argv_free(kp_iter->argv);
+ list_del(&kp_iter->list);
+ kfree(kp_iter);
+ }
+
+ mutex_unlock(&kp_list_lock);
+}
+
+#endif
diff --git a/mali_kbase/tests/kutf/kutf_mem.c b/mali_kbase/tests/kutf/kutf_mem.c
index 716970a..527ddaa 100644
--- a/mali_kbase/tests/kutf/kutf_mem.c
+++ b/mali_kbase/tests/kutf/kutf_mem.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2014, 2017, 2020-2021 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -27,7 +27,6 @@
#include <kutf/kutf_mem.h>
-
/**
* struct kutf_alloc_entry - Structure representing an allocation.
* @node: List node for use with kutf_mempool.
@@ -71,7 +70,6 @@ void kutf_mempool_destroy(struct kutf_mempool *pool)
kfree(remove_alloc);
}
mutex_unlock(&pool->lock);
-
}
EXPORT_SYMBOL(kutf_mempool_destroy);
diff --git a/mali_kbase/tests/kutf/kutf_resultset.c b/mali_kbase/tests/kutf/kutf_resultset.c
index 3a7ade2..4f62d04 100644
--- a/mali_kbase/tests/kutf/kutf_resultset.c
+++ b/mali_kbase/tests/kutf/kutf_resultset.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2014, 2017, 2020-2021 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -54,9 +54,8 @@ fail_alloc:
return NULL;
}
-int kutf_add_result(struct kutf_context *context,
- enum kutf_result_status status,
- const char *message)
+int kutf_add_result(struct kutf_context *context, enum kutf_result_status status,
+ const char *message)
{
struct kutf_mempool *mempool = &context->fixture_pool;
struct kutf_result_set *set = context->result_set;
@@ -115,8 +114,7 @@ struct kutf_result *kutf_remove_result(struct kutf_result_set *set)
int ret;
do {
- ret = wait_event_interruptible(set->waitq,
- kutf_has_result(set));
+ ret = wait_event_interruptible(set->waitq, kutf_has_result(set));
if (ret)
return ERR_PTR(ret);
@@ -124,15 +122,11 @@ struct kutf_result *kutf_remove_result(struct kutf_result_set *set)
spin_lock(&kutf_result_lock);
if (!list_empty(&set->results)) {
- result = list_first_entry(&set->results,
- struct kutf_result,
- node);
+ result = list_first_entry(&set->results, struct kutf_result, node);
list_del(&result->node);
} else if (set->flags & KUTF_RESULT_SET_WAITING_FOR_INPUT) {
/* Return a fake result */
- static struct kutf_result waiting = {
- .status = KUTF_RESULT_USERDATA_WAIT
- };
+ static struct kutf_result waiting = { .status = KUTF_RESULT_USERDATA_WAIT };
result = &waiting;
}
/* If result == NULL then there was a race with the event
diff --git a/mali_kbase/tests/kutf/kutf_suite.c b/mali_kbase/tests/kutf/kutf_suite.c
index 4468066..dcd4cb3 100644
--- a/mali_kbase/tests/kutf/kutf_suite.c
+++ b/mali_kbase/tests/kutf/kutf_suite.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2014, 2017-2022 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -33,13 +33,15 @@
#include <linux/version.h>
#include <linux/atomic.h>
#include <linux/sched.h>
-
#include <generated/autoconf.h>
#include <kutf/kutf_suite.h>
#include <kutf/kutf_resultset.h>
#include <kutf/kutf_utils.h>
#include <kutf/kutf_helpers.h>
+#ifdef CONFIG_KPROBES
+#include <kutf/kutf_kprobe.h>
+#endif
/**
* struct kutf_application - Structure which represents kutf application
@@ -49,9 +51,9 @@
* application
*/
struct kutf_application {
- const char *name;
- struct dentry *dir;
- struct list_head suite_list;
+ const char *name;
+ struct dentry *dir;
+ struct list_head suite_list;
};
/**
@@ -68,14 +70,14 @@ struct kutf_application {
* @dir: debugfs directory for this test function
*/
struct kutf_test_function {
- struct kutf_suite *suite;
- unsigned int filters;
- unsigned int test_id;
+ struct kutf_suite *suite;
+ unsigned int filters;
+ unsigned int test_id;
void (*execute)(struct kutf_context *context);
union kutf_callback_data test_data;
- struct list_head node;
- struct list_head variant_list;
- struct dentry *dir;
+ struct list_head node;
+ struct list_head variant_list;
+ struct dentry *dir;
};
/**
@@ -88,9 +90,9 @@ struct kutf_test_function {
*/
struct kutf_test_fixture {
struct kutf_test_function *test_func;
- unsigned int fixture_index;
- struct list_head node;
- struct dentry *dir;
+ unsigned int fixture_index;
+ struct list_head node;
+ struct dentry *dir;
};
static struct dentry *base_dir;
@@ -102,14 +104,14 @@ static struct workqueue_struct *kutf_workq;
* @result: Status value for a single test
*/
struct kutf_convert_table {
- char result_name[50];
+ char result_name[50];
enum kutf_result_status result;
};
static const struct kutf_convert_table kutf_convert[] = {
-#define ADD_UTF_RESULT(_name) \
- { \
-#_name, _name, \
+#define ADD_UTF_RESULT(_name) \
+ { \
+#_name, _name, \
}
ADD_UTF_RESULT(KUTF_RESULT_BENCHMARK), ADD_UTF_RESULT(KUTF_RESULT_SKIP),
ADD_UTF_RESULT(KUTF_RESULT_UNKNOWN), ADD_UTF_RESULT(KUTF_RESULT_PASS),
@@ -130,8 +132,7 @@ static const struct kutf_convert_table kutf_convert[] = {
*
* Return: Returns the created test context on success or NULL on failure
*/
-static struct kutf_context *kutf_create_context(
- struct kutf_test_fixture *test_fix);
+static struct kutf_context *kutf_create_context(struct kutf_test_fixture *test_fix);
/**
* kutf_destroy_context() - Destroy a previously created test context, only
@@ -166,8 +167,7 @@ static void kutf_context_put(struct kutf_context *context);
* @context: Test context
* @status: Result status
*/
-static void kutf_set_result(struct kutf_context *context,
- enum kutf_result_status status);
+static void kutf_set_result(struct kutf_context *context, enum kutf_result_status status);
/**
* kutf_set_expected_result() - Set the expected test result for the specified
@@ -176,7 +176,7 @@ static void kutf_set_result(struct kutf_context *context,
* @expected_status: Expected result status
*/
static void kutf_set_expected_result(struct kutf_context *context,
- enum kutf_result_status expected_status);
+ enum kutf_result_status expected_status);
/**
* kutf_result_to_string() - Converts a KUTF result into a string
@@ -187,7 +187,7 @@ static void kutf_set_expected_result(struct kutf_context *context,
*/
static int kutf_result_to_string(const char **result_str, enum kutf_result_status result)
{
- int i;
+ size_t i;
int ret = 0;
for (i = 0; i < UTF_CONVERT_SIZE; i++) {
@@ -210,8 +210,8 @@ static int kutf_result_to_string(const char **result_str, enum kutf_result_statu
* Return: On success, the number of bytes read and offset @ppos advanced by
* this number; on error, negative value
*/
-static ssize_t kutf_debugfs_const_string_read(struct file *file,
- char __user *buf, size_t len, loff_t *ppos)
+static ssize_t kutf_debugfs_const_string_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
{
char *str = file->private_data;
@@ -222,7 +222,7 @@ static const struct file_operations kutf_debugfs_const_string_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = kutf_debugfs_const_string_read,
- .llseek = default_llseek,
+ .llseek = default_llseek,
};
/**
@@ -237,41 +237,33 @@ static void kutf_add_explicit_result(struct kutf_context *context)
case KUTF_RESULT_WARN:
if (context->status == KUTF_RESULT_WARN)
- kutf_test_pass(context,
- "Pass (expected warn occurred)");
+ kutf_test_pass(context, "Pass (expected warn occurred)");
else if (context->status != KUTF_RESULT_SKIP)
- kutf_test_fail(context,
- "Fail (expected warn missing)");
+ kutf_test_fail(context, "Fail (expected warn missing)");
break;
case KUTF_RESULT_FAIL:
if (context->status == KUTF_RESULT_FAIL)
- kutf_test_pass(context,
- "Pass (expected fail occurred)");
+ kutf_test_pass(context, "Pass (expected fail occurred)");
else if (context->status != KUTF_RESULT_SKIP) {
/* Force the expected status so the fail gets logged */
context->expected_status = KUTF_RESULT_PASS;
- kutf_test_fail(context,
- "Fail (expected fail missing)");
+ kutf_test_fail(context, "Fail (expected fail missing)");
}
break;
case KUTF_RESULT_FATAL:
if (context->status == KUTF_RESULT_FATAL)
- kutf_test_pass(context,
- "Pass (expected fatal occurred)");
+ kutf_test_pass(context, "Pass (expected fatal occurred)");
else if (context->status != KUTF_RESULT_SKIP)
- kutf_test_fail(context,
- "Fail (expected fatal missing)");
+ kutf_test_fail(context, "Fail (expected fatal missing)");
break;
case KUTF_RESULT_ABORT:
if (context->status == KUTF_RESULT_ABORT)
- kutf_test_pass(context,
- "Pass (expected abort occurred)");
+ kutf_test_pass(context, "Pass (expected abort occurred)");
else if (context->status != KUTF_RESULT_SKIP)
- kutf_test_fail(context,
- "Fail (expected abort missing)");
+ kutf_test_fail(context, "Fail (expected abort missing)");
break;
default:
break;
@@ -280,8 +272,7 @@ static void kutf_add_explicit_result(struct kutf_context *context)
static void kutf_run_test(struct work_struct *data)
{
- struct kutf_context *test_context = container_of(data,
- struct kutf_context, work);
+ struct kutf_context *test_context = container_of(data, struct kutf_context, work);
struct kutf_suite *suite = test_context->suite;
struct kutf_test_function *test_func;
@@ -295,10 +286,13 @@ static void kutf_run_test(struct work_struct *data)
test_context->fixture = suite->create_fixture(test_context);
/* Only run the test if the fixture was created (if required) */
- if ((suite->create_fixture && test_context->fixture) ||
- (!suite->create_fixture)) {
- /* Run this fixture */
- test_func->execute(test_context);
+ if ((suite->create_fixture && test_context->fixture) || (!suite->create_fixture)) {
+ if (test_func->filters & KUTF_F_TEST_EXPECTED_FAILURE) {
+ kutf_test_fail(test_context,
+ "KUTF: Test marked as 'Expected Failure' not run.");
+ } else {
+ test_func->execute(test_context);
+ }
if (suite->remove_fixture)
suite->remove_fixture(test_context);
@@ -368,8 +362,7 @@ finish:
*
* Return: Number of bytes read.
*/
-static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf,
- size_t len, loff_t *ppos)
+static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
{
struct kutf_context *test_context = file->private_data;
struct kutf_result *res;
@@ -394,8 +387,7 @@ static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf,
case KUTF_RESULT_TEST_FINISHED:
return 0;
case KUTF_RESULT_USERDATA_WAIT:
- if (test_context->userdata.flags &
- KUTF_USERDATA_WARNING_OUTPUT) {
+ if (test_context->userdata.flags & KUTF_USERDATA_WARNING_OUTPUT) {
/*
* Warning message already output,
* signal end-of-file
@@ -403,37 +395,33 @@ static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf,
return 0;
}
- message_len = sizeof(USERDATA_WARNING_MESSAGE)-1;
+ message_len = sizeof(USERDATA_WARNING_MESSAGE) - 1;
if (message_len > len)
message_len = len;
- bytes_not_copied = copy_to_user(buf,
- USERDATA_WARNING_MESSAGE,
- message_len);
+ bytes_not_copied = copy_to_user(buf, USERDATA_WARNING_MESSAGE, message_len);
if (bytes_not_copied != 0)
return -EFAULT;
test_context->userdata.flags |= KUTF_USERDATA_WARNING_OUTPUT;
- return message_len;
+ return (ssize_t)message_len;
case KUTF_RESULT_USERDATA:
message_len = strlen(res->message);
- if (message_len > len-1) {
- message_len = len-1;
+ if (message_len > len - 1) {
+ message_len = len - 1;
pr_warn("User data truncated, read not long enough\n");
}
- bytes_not_copied = copy_to_user(buf, res->message,
- message_len);
+ bytes_not_copied = copy_to_user(buf, res->message, message_len);
if (bytes_not_copied != 0) {
pr_warn("Failed to copy data to user space buffer\n");
return -EFAULT;
}
/* Finally the terminator */
- bytes_not_copied = copy_to_user(&buf[message_len],
- &terminator, 1);
+ bytes_not_copied = copy_to_user(&buf[message_len], &terminator, 1);
if (bytes_not_copied != 0) {
pr_warn("Failed to copy data to user space buffer\n");
return -EFAULT;
}
- return message_len+1;
+ return (ssize_t)message_len + 1;
default:
/* Fall through - this is a test result */
break;
@@ -454,33 +442,29 @@ static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf,
/* First copy the result string */
if (kutf_str_ptr) {
- bytes_not_copied = copy_to_user(&buf[0], kutf_str_ptr,
- kutf_str_len);
- bytes_copied += kutf_str_len - bytes_not_copied;
+ bytes_not_copied = copy_to_user(&buf[0], kutf_str_ptr, kutf_str_len);
+ bytes_copied += (ssize_t)(kutf_str_len - bytes_not_copied);
if (bytes_not_copied)
goto exit;
}
/* Then the separator */
- bytes_not_copied = copy_to_user(&buf[bytes_copied],
- &separator, 1);
- bytes_copied += 1 - bytes_not_copied;
+ bytes_not_copied = copy_to_user(&buf[bytes_copied], &separator, 1);
+ bytes_copied += (ssize_t)(1 - bytes_not_copied);
if (bytes_not_copied)
goto exit;
/* Finally Next copy the result string */
if (res->message) {
- bytes_not_copied = copy_to_user(&buf[bytes_copied],
- res->message, message_len);
- bytes_copied += message_len - bytes_not_copied;
+ bytes_not_copied = copy_to_user(&buf[bytes_copied], res->message, message_len);
+ bytes_copied += (ssize_t)(message_len - bytes_not_copied);
if (bytes_not_copied)
goto exit;
}
/* Finally the terminator */
- bytes_not_copied = copy_to_user(&buf[bytes_copied],
- &terminator, 1);
- bytes_copied += 1 - bytes_not_copied;
+ bytes_not_copied = copy_to_user(&buf[bytes_copied], &terminator, 1);
+ bytes_copied += (ssize_t)(1 - bytes_not_copied);
exit:
return bytes_copied;
@@ -500,8 +484,8 @@ exit:
*
* Return: Number of bytes written
*/
-static ssize_t kutf_debugfs_run_write(struct file *file,
- const char __user *buf, size_t len, loff_t *ppos)
+static ssize_t kutf_debugfs_run_write(struct file *file, const char __user *buf, size_t len,
+ loff_t *ppos)
{
int ret = 0;
struct kutf_context *test_context = file->private_data;
@@ -513,7 +497,7 @@ static ssize_t kutf_debugfs_run_write(struct file *file,
if (ret < 0)
return ret;
- return len;
+ return (ssize_t)len;
}
/**
@@ -544,7 +528,7 @@ static const struct file_operations kutf_debugfs_run_ops = {
.read = kutf_debugfs_run_read,
.write = kutf_debugfs_run_write,
.release = kutf_debugfs_run_release,
- .llseek = default_llseek,
+ .llseek = default_llseek,
};
/**
@@ -556,11 +540,10 @@ static const struct file_operations kutf_debugfs_run_ops = {
*
* Return: 0 on success, negative value corresponding to error code in failure
*/
-static int create_fixture_variant(struct kutf_test_function *test_func,
- unsigned int fixture_index)
+static int create_fixture_variant(struct kutf_test_function *test_func, unsigned int fixture_index)
{
struct kutf_test_fixture *test_fix;
- char name[11]; /* Enough to print the MAX_UINT32 + the null terminator */
+ char name[11]; /* Enough to print the MAX_UINT32 + the null terminator */
struct dentry *tmp;
int err;
@@ -592,10 +575,8 @@ static int create_fixture_variant(struct kutf_test_function *test_func,
goto fail_file;
}
- tmp = debugfs_create_file_unsafe(
- "run", 0600, test_fix->dir,
- test_fix,
- &kutf_debugfs_run_ops);
+ tmp = debugfs_create_file_unsafe("run", 0600, test_fix->dir, test_fix,
+ &kutf_debugfs_run_ops);
if (IS_ERR_OR_NULL(tmp)) {
pr_err("Failed to create debugfs file \"run\" when adding fixture\n");
/* Might not be the right error, we don't get it passed back to us */
@@ -635,13 +616,10 @@ static int ktufp_u32_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(kutfp_fops_x32_ro, ktufp_u32_get, NULL, "0x%08llx\n");
#endif
-void kutf_add_test_with_filters_and_data(
- struct kutf_suite *suite,
- unsigned int id,
- const char *name,
- void (*execute)(struct kutf_context *context),
- unsigned int filters,
- union kutf_callback_data test_data)
+void kutf_add_test_with_filters_and_data(struct kutf_suite *suite, unsigned int id,
+ const char *name,
+ void (*execute)(struct kutf_context *context),
+ unsigned int filters, union kutf_callback_data test_data)
{
struct kutf_test_function *test_func;
struct dentry *tmp;
@@ -670,11 +648,10 @@ void kutf_add_test_with_filters_and_data(
test_func->filters = filters;
#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
- tmp = debugfs_create_file_unsafe("filters", 0004, test_func->dir,
- &test_func->filters, &kutfp_fops_x32_ro);
+ tmp = debugfs_create_file_unsafe("filters", 0004, test_func->dir, &test_func->filters,
+ &kutfp_fops_x32_ro);
#else
- tmp = debugfs_create_x32("filters", 0004, test_func->dir,
- &test_func->filters);
+ tmp = debugfs_create_x32("filters", 0004, test_func->dir, &test_func->filters);
#endif
if (IS_ERR_OR_NULL(tmp)) {
pr_err("Failed to create debugfs file \"filters\" when adding test %s\n", name);
@@ -683,11 +660,9 @@ void kutf_add_test_with_filters_and_data(
test_func->test_id = id;
#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
- debugfs_create_u32("test_id", 0004, test_func->dir,
- &test_func->test_id);
+ debugfs_create_u32("test_id", 0004, test_func->dir, &test_func->test_id);
#else
- tmp = debugfs_create_u32("test_id", 0004, test_func->dir,
- &test_func->test_id);
+ tmp = debugfs_create_u32("test_id", 0004, test_func->dir, &test_func->test_id);
if (IS_ERR_OR_NULL(tmp)) {
pr_err("Failed to create debugfs file \"test_id\" when adding test %s\n", name);
goto fail_file;
@@ -717,40 +692,26 @@ fail_alloc:
}
EXPORT_SYMBOL(kutf_add_test_with_filters_and_data);
-void kutf_add_test_with_filters(
- struct kutf_suite *suite,
- unsigned int id,
- const char *name,
- void (*execute)(struct kutf_context *context),
- unsigned int filters)
+void kutf_add_test_with_filters(struct kutf_suite *suite, unsigned int id, const char *name,
+ void (*execute)(struct kutf_context *context), unsigned int filters)
{
union kutf_callback_data data;
data.ptr_value = NULL;
- kutf_add_test_with_filters_and_data(suite,
- id,
- name,
- execute,
- suite->suite_default_flags,
- data);
+ kutf_add_test_with_filters_and_data(suite, id, name, execute,
+ suite->suite_default_flags & filters, data);
}
EXPORT_SYMBOL(kutf_add_test_with_filters);
-void kutf_add_test(struct kutf_suite *suite,
- unsigned int id,
- const char *name,
- void (*execute)(struct kutf_context *context))
+void kutf_add_test(struct kutf_suite *suite, unsigned int id, const char *name,
+ void (*execute)(struct kutf_context *context))
{
union kutf_callback_data data;
data.ptr_value = NULL;
- kutf_add_test_with_filters_and_data(suite,
- id,
- name,
- execute,
- suite->suite_default_flags,
+ kutf_add_test_with_filters_and_data(suite, id, name, execute, suite->suite_default_flags,
data);
}
EXPORT_SYMBOL(kutf_add_test);
@@ -776,14 +737,12 @@ static void kutf_remove_test(struct kutf_test_function *test_func)
kfree(test_func);
}
-struct kutf_suite *kutf_create_suite_with_filters_and_data(
- struct kutf_application *app,
- const char *name,
- unsigned int fixture_count,
- void *(*create_fixture)(struct kutf_context *context),
- void (*remove_fixture)(struct kutf_context *context),
- unsigned int filters,
- union kutf_callback_data suite_data)
+struct kutf_suite *
+kutf_create_suite_with_filters_and_data(struct kutf_application *app, const char *name,
+ unsigned int fixture_count,
+ void *(*create_fixture)(struct kutf_context *context),
+ void (*remove_fixture)(struct kutf_context *context),
+ unsigned int filters, union kutf_callback_data suite_data)
{
struct kutf_suite *suite;
struct dentry *tmp;
@@ -830,43 +789,28 @@ fail_kmalloc:
EXPORT_SYMBOL(kutf_create_suite_with_filters_and_data);
struct kutf_suite *kutf_create_suite_with_filters(
- struct kutf_application *app,
- const char *name,
- unsigned int fixture_count,
- void *(*create_fixture)(struct kutf_context *context),
- void (*remove_fixture)(struct kutf_context *context),
- unsigned int filters)
+ struct kutf_application *app, const char *name, unsigned int fixture_count,
+ void *(*create_fixture)(struct kutf_context *context),
+ void (*remove_fixture)(struct kutf_context *context), unsigned int filters)
{
union kutf_callback_data data;
data.ptr_value = NULL;
- return kutf_create_suite_with_filters_and_data(app,
- name,
- fixture_count,
- create_fixture,
- remove_fixture,
- filters,
- data);
+ return kutf_create_suite_with_filters_and_data(app, name, fixture_count, create_fixture,
+ remove_fixture, filters, data);
}
EXPORT_SYMBOL(kutf_create_suite_with_filters);
-struct kutf_suite *kutf_create_suite(
- struct kutf_application *app,
- const char *name,
- unsigned int fixture_count,
- void *(*create_fixture)(struct kutf_context *context),
- void (*remove_fixture)(struct kutf_context *context))
+struct kutf_suite *kutf_create_suite(struct kutf_application *app, const char *name,
+ unsigned int fixture_count,
+ void *(*create_fixture)(struct kutf_context *context),
+ void (*remove_fixture)(struct kutf_context *context))
{
union kutf_callback_data data;
data.ptr_value = NULL;
- return kutf_create_suite_with_filters_and_data(app,
- name,
- fixture_count,
- create_fixture,
- remove_fixture,
- KUTF_F_TEST_GENERIC,
- data);
+ return kutf_create_suite_with_filters_and_data(app, name, fixture_count, create_fixture,
+ remove_fixture, KUTF_F_TEST_GENERIC, data);
}
EXPORT_SYMBOL(kutf_create_suite);
@@ -911,7 +855,8 @@ struct kutf_application *kutf_create_application(const char *name)
tmp = debugfs_create_file("type", 0004, app->dir, "application\n",
&kutf_debugfs_const_string_ops);
if (IS_ERR_OR_NULL(tmp)) {
- pr_err("Failed to create debugfs file \"type\" when creating application %s\n", name);
+ pr_err("Failed to create debugfs file \"type\" when creating application %s\n",
+ name);
goto fail_file;
}
@@ -946,15 +891,14 @@ void kutf_destroy_application(struct kutf_application *app)
}
EXPORT_SYMBOL(kutf_destroy_application);
-static struct kutf_context *kutf_create_context(
- struct kutf_test_fixture *test_fix)
+static struct kutf_context *kutf_create_context(struct kutf_test_fixture *test_fix)
{
struct kutf_context *new_context;
new_context = kmalloc(sizeof(*new_context), GFP_KERNEL);
if (!new_context) {
pr_err("Failed to allocate test context");
- goto fail_alloc;
+ goto fail_context_alloc;
}
new_context->result_set = kutf_create_result_set();
@@ -975,6 +919,8 @@ static struct kutf_context *kutf_create_context(
new_context->fixture_name = NULL;
new_context->test_data = test_fix->test_func->test_data;
+ mutex_init(&new_context->output_sync);
+
new_context->userdata.flags = 0;
INIT_LIST_HEAD(&new_context->userdata.input_head);
init_waitqueue_head(&new_context->userdata.input_waitq);
@@ -987,7 +933,7 @@ static struct kutf_context *kutf_create_context(
fail_result_set:
kfree(new_context);
-fail_alloc:
+fail_context_alloc:
return NULL;
}
@@ -1011,15 +957,13 @@ static void kutf_context_put(struct kutf_context *context)
kref_put(&context->kref, kutf_destroy_context);
}
-
-static void kutf_set_result(struct kutf_context *context,
- enum kutf_result_status status)
+static void kutf_set_result(struct kutf_context *context, enum kutf_result_status status)
{
context->status = status;
}
static void kutf_set_expected_result(struct kutf_context *context,
- enum kutf_result_status expected_status)
+ enum kutf_result_status expected_status)
{
context->expected_status = expected_status;
}
@@ -1030,10 +974,8 @@ static void kutf_set_expected_result(struct kutf_context *context,
* @message: Result string
* @new_status: Result status
*/
-static void kutf_test_log_result(
- struct kutf_context *context,
- const char *message,
- enum kutf_result_status new_status)
+static void kutf_test_log_result(struct kutf_context *context, const char *message,
+ enum kutf_result_status new_status)
{
if (context->status < new_status)
context->status = new_status;
@@ -1042,10 +984,8 @@ static void kutf_test_log_result(
kutf_add_result(context, new_status, message);
}
-void kutf_test_log_result_external(
- struct kutf_context *context,
- const char *message,
- enum kutf_result_status new_status)
+void kutf_test_log_result_external(struct kutf_context *context, const char *message,
+ enum kutf_result_status new_status)
{
kutf_test_log_result(context, message, new_status);
}
@@ -1095,8 +1035,9 @@ void kutf_test_skip_msg(struct kutf_context *context, const char *message)
kutf_set_result(context, KUTF_RESULT_SKIP);
kutf_set_expected_result(context, KUTF_RESULT_UNKNOWN);
- kutf_test_log_result(context, kutf_dsprintf(&context->fixture_pool,
- "Test skipped: %s", message), KUTF_RESULT_SKIP);
+ kutf_test_log_result(context,
+ kutf_dsprintf(&context->fixture_pool, "Test skipped: %s", message),
+ KUTF_RESULT_SKIP);
kutf_test_log_result(context, "!!!Test skipped!!!", KUTF_RESULT_SKIP);
}
EXPORT_SYMBOL(kutf_test_skip_msg);
@@ -1124,6 +1065,20 @@ void kutf_test_info(struct kutf_context *context, char const *message)
}
EXPORT_SYMBOL(kutf_test_info);
+__printf(2, 3) void kutf_test_info_msg(struct kutf_context *context, char const *msg, ...)
+{
+ va_list args;
+
+ mutex_lock(&context->output_sync);
+
+ va_start(args, msg);
+ kutf_test_info(context, kutf_dsprintf(&context->fixture_pool, msg, args));
+ va_end(args);
+
+ mutex_unlock(&context->output_sync);
+}
+EXPORT_SYMBOL(kutf_test_info_msg);
+
void kutf_test_warn(struct kutf_context *context, char const *message)
{
kutf_test_log_result(context, message, KUTF_RESULT_WARN);
@@ -1136,6 +1091,20 @@ void kutf_test_fail(struct kutf_context *context, char const *message)
}
EXPORT_SYMBOL(kutf_test_fail);
+__printf(2, 3) void kutf_test_fail_msg(struct kutf_context *context, char const *msg, ...)
+{
+ va_list args;
+
+ mutex_lock(&context->output_sync);
+
+ va_start(args, msg);
+ kutf_test_fail(context, kutf_dsprintf(&context->fixture_pool, msg, args));
+ va_end(args);
+
+ mutex_unlock(&context->output_sync);
+}
+EXPORT_SYMBOL(kutf_test_fail_msg);
+
void kutf_test_fatal(struct kutf_context *context, char const *message)
{
kutf_test_log_result(context, message, KUTF_RESULT_FATAL);
@@ -1169,6 +1138,10 @@ static int __init init_kutf_core(void)
return -ENOMEM;
}
+#ifdef CONFIG_KPROBES
+ kutf_kprobe_init(base_dir);
+#endif
+
return 0;
}
@@ -1179,13 +1152,16 @@ static int __init init_kutf_core(void)
*/
static void __exit exit_kutf_core(void)
{
+#ifdef CONFIG_KPROBES
+ kutf_kprobe_exit();
+#endif
debugfs_remove_recursive(base_dir);
if (kutf_workq)
destroy_workqueue(kutf_workq);
}
-#else /* CONFIG_DEBUG_FS */
+#else /* CONFIG_DEBUG_FS */
/**
* init_kutf_core - Module entry point
@@ -1208,7 +1184,7 @@ static int __init init_kutf_core(void)
static void __exit exit_kutf_core(void)
{
}
-#endif /* CONFIG_DEBUG_FS */
+#endif /* CONFIG_DEBUG_FS */
MODULE_LICENSE("GPL");
diff --git a/mali_kbase/tests/kutf/kutf_utils.c b/mali_kbase/tests/kutf/kutf_utils.c
index 21f5fad..183ab36 100644
--- a/mali_kbase/tests/kutf/kutf_utils.c
+++ b/mali_kbase/tests/kutf/kutf_utils.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2014, 2017, 2020-2022 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -33,12 +33,11 @@ static char tmp_buffer[KUTF_MAX_DSPRINTF_LEN];
static DEFINE_MUTEX(buffer_lock);
-const char *kutf_dsprintf(struct kutf_mempool *pool,
- const char *fmt, ...)
+const char *kutf_dsprintf(struct kutf_mempool *pool, const char *fmt, ...)
{
va_list args;
int len;
- int size;
+ size_t size;
void *buffer;
mutex_lock(&buffer_lock);
@@ -51,11 +50,11 @@ const char *kutf_dsprintf(struct kutf_mempool *pool,
goto fail_format;
}
- if (len >= sizeof(tmp_buffer)) {
+ if (len >= (int)sizeof(tmp_buffer)) {
pr_warn("%s: Truncated dsprintf message %s\n", __func__, fmt);
size = sizeof(tmp_buffer);
} else {
- size = len + 1;
+ size = (size_t)(len + 1);
}
buffer = kutf_mempool_alloc(pool, size);