diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index f1a1937bcfb42941a4e699f2a91bd4464455e30f..0bcf728436a1718c2ef951378d7a45ab01992fd9 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -68,7 +68,7 @@ ifneq ($(KERNELRELEASE),) LISA_KMOD_NAME ?= lisa obj-m := $(LISA_KMOD_NAME).o -$(LISA_KMOD_NAME)-y := main.o tp.o wq.o features.o pixel6.o introspection_data.o +$(LISA_KMOD_NAME)-y := main.o tp.o wq.o features.o pixel6.o introspection_data.o debugfs.o # -fno-stack-protector is needed to possibly undefined __stack_chk_guard symbol ccflags-y := "-I$(MODULE_SRC)" -std=gnu11 -fno-stack-protector -Wno-declaration-after-statement -Wno-error diff --git a/lisa/_assets/kmodules/lisa/debugfs.c b/lisa/_assets/kmodules/lisa/debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..bc9613a48dcea69918dd04979e9bb6116433bfa1 --- /dev/null +++ b/lisa/_assets/kmodules/lisa/debugfs.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +#include + +#include +#include + +#include "main.h" +#include "debugfs.h" +#include "features.h" + +static struct dentry *reload_file; +static struct dentry *lisa_debugfs; + + +static ssize_t reload_file_write(struct file *f, const char __user *user_buf, size_t n, loff_t *offset) { + char buf[16] = {0}; + ssize_t ret = simple_write_to_buffer(buf, sizeof(buf), offset, user_buf, n); + if (!strncmp(buf, "all\n", sizeof(buf))) { + if (reload()) { + return -ENOTRECOVERABLE; + } else { + return ret; + } + + } + return ret; +} + +const struct file_operations reload_file_fops = { + .owner = THIS_MODULE, + .write = reload_file_write, +}; + +#ifdef CONFIG_DEBUG_FS +int debugfs_init(void) +{ + lisa_debugfs = debugfs_create_dir("lisa", NULL); + if (!lisa_debugfs) { + pr_err("Could not create lisa debugfs folder\n"); + return -ENOENT; + } + + reload_file = debugfs_create_file("reload", 0644, lisa_debugfs, NULL, + &reload_file_fops); + + if (lisa_debugfs) { + return 0; + } else { + pr_err("Could not create lisa debugfs folder\n"); + debugfs_exit(); + return -ENOENT; + } +} + +void debugfs_exit(void) +{ + if (lisa_debugfs) + debugfs_remove_recursive(lisa_debugfs); +} + +#else /* CONFIG_DEBUG_FS */ + +int debugfs_init(void) +{ + return 0; +} + +void debugfs_exit(void) +{ +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/lisa/_assets/kmodules/lisa/debugfs.h b/lisa/_assets/kmodules/lisa/debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..f57a9c615a0ebebf50028151582a3cec38ad7f1d --- /dev/null +++ b/lisa/_assets/kmodules/lisa/debugfs.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _DEBUGFS_H +#define _DEBUGFS_H + + +int debugfs_init(void); +void debugfs_exit(void); + +#endif diff --git a/lisa/_assets/kmodules/lisa/features.c b/lisa/_assets/kmodules/lisa/features.c index 01e5c2c8c93564357588e89bf9beb756cfff2922..42d9b769a1f39958c32878341fc8cd6d22b3507d 100644 --- a/lisa/_assets/kmodules/lisa/features.c +++ b/lisa/_assets/kmodules/lisa/features.c @@ -90,13 +90,6 @@ static int __process_features(char **selected, size_t selected_len, feature_proc return ret; } - -static int __list_feature(struct feature* feature) { - if (!feature->__internal) - pr_info(" %s", feature->name); - return 0; -} - static int __enable_feature_explicitly(struct feature* feature) { mutex_lock(feature->lock); feature->__explicitly_enabled++; @@ -104,11 +97,32 @@ static int __enable_feature_explicitly(struct feature* feature) { return __enable_feature(feature); } +static int __reset_feature_state(struct feature* feature) { + mutex_lock(feature->lock); + + if (!feature->__internal) + pr_info(" %s", feature->name); + + /* All features should have been deinitialized at this point, so this + * should be 0 + */ + BUG_ON(feature->__explicitly_enabled); + + /* Reset some state in case we are reloading the module */ + feature->__enable_ret = 0; + feature->data = NULL; + + mutex_unlock(feature->lock); + return 0; +} + int init_features(char **selected, size_t selected_len) { BUG_ON(MAX_FEATURES < ((__lisa_features_stop - __lisa_features_start) / sizeof(struct feature))); - pr_info("Available features:"); - __process_features(NULL, 0, __list_feature); + pr_info("Available features: "); + __process_features(NULL, 0, __reset_feature_state); + pr_info("\n"); + return __process_features(selected, selected_len, __enable_feature_explicitly); } @@ -116,12 +130,13 @@ static int __disable_explicitly_enabled_feature(struct feature* feature) { int ret = 0; mutex_lock(feature->lock); - int selected = feature->__explicitly_enabled; - mutex_unlock(feature->lock); - while (selected) { + while (feature->__explicitly_enabled) { + mutex_unlock(feature->lock); ret |= __disable_feature(feature); - selected--; + mutex_lock(feature->lock); + feature->__explicitly_enabled--; } + mutex_unlock(feature->lock); return ret; } diff --git a/lisa/_assets/kmodules/lisa/main.c b/lisa/_assets/kmodules/lisa/main.c index 05ec9b2cfcb167a5af51d3aba0a428d9746caca1..fed6180bbc2cd66d05a1abdf88ab48b23e29b4c0 100644 --- a/lisa/_assets/kmodules/lisa/main.c +++ b/lisa/_assets/kmodules/lisa/main.c @@ -2,6 +2,7 @@ #include #include "main.h" +#include "debugfs.h" #include "features.h" #include "introspection.h" #include "generated/module_version.h" @@ -15,18 +16,24 @@ module_param(version, charp, 0); MODULE_PARM_DESC(version, "Module version defined as sha1sum of the module sources"); static char *features[MAX_FEATURES]; -unsigned int features_len = 0; -module_param_array(features, charp, &features_len, 0); +static unsigned int features_len = 0; +module_param_array(features, charp, &features_len, 0600); MODULE_PARM_DESC(features, "Comma-separated list of features to enable. Available features are printed when loading the module"); -static void modexit(void) { - if (deinit_features()) - pr_err("Some errors happened while unloading LISA kernel module\n"); + +static int exit(void) { + int ret = deinit_features(); + if (ret) + pr_err("Some errors happened while unloading LISA kernel module: %d\n", ret); + return ret; } -static int __init modinit(void) { - int ret; +static void modexit(void) { + debugfs_exit(); + exit(); +} +static int init(void) { pr_info("Loading Lisa module version %s\n", LISA_MODULE_VERSION); if (strcmp(version, LISA_MODULE_VERSION)) { pr_err("Lisa module version check failed. Got %s, expected %s\n", version, LISA_MODULE_VERSION); @@ -40,14 +47,27 @@ static int __init modinit(void) { pr_info(" %s: %s\n", kernel_feature_names[i], kernel_feature_values[i] ? "enabled" : "disabled"); } - ret = init_features(features_len ? features : NULL , features_len); + int ret = init_features(features_len ? features : NULL , features_len); + if (ret) + pr_err("Some errors happened while loading LISA kernel module: %d\n", ret); + return ret; +} - if (ret) { - pr_err("Some errors happened while loading LISA kernel module\n"); +int reload(void) { + int ret = 0; + ret |= exit(); + ret |= init(); - /* Use one of the standard error code */ - ret = -EINVAL; + if (ret) + pr_err("Some errors happened while reloading LISA module: %d\n", ret); + return ret; +} +static int __init modinit(void) { + /* First load the features, so there is no race with someone trying to + * reload from debugfs at the same time. + */ + if (init()) { /* If the user selected features manually, make module loading fail so * that they are aware that things went wrong. Otherwise, just * keep going as the user just wanted to enable as many features @@ -60,13 +80,25 @@ static int __init modinit(void) { * vanishes. */ modexit(); - return ret; + /* Use one of the standard error code */ + return -EINVAL; + + } else { + return 0; } } + + int ret = debugfs_init(); + if (ret) { + pr_err("Some errors happened while setting up debugfs for LISA kernel module: %d\n", ret); + return -EINVAL; + } return 0; } + + module_init(modinit); module_exit(modexit); diff --git a/lisa/_assets/kmodules/lisa/main.h b/lisa/_assets/kmodules/lisa/main.h index e3691166dfbfaeb0b0552aac271fe4625219ae25..08dfd75af06126808e334f543c48c41978070a81 100644 --- a/lisa/_assets/kmodules/lisa/main.h +++ b/lisa/_assets/kmodules/lisa/main.h @@ -7,4 +7,6 @@ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +int reload(void); + #endif diff --git a/tools/kmodules/lisa/debugfs.c b/tools/kmodules/lisa/debugfs.c new file mode 120000 index 0000000000000000000000000000000000000000..dd89b164d83a4dfbd7d69e7661699d54a84a97b9 --- /dev/null +++ b/tools/kmodules/lisa/debugfs.c @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/debugfs.c \ No newline at end of file diff --git a/tools/kmodules/lisa/debugfs.h b/tools/kmodules/lisa/debugfs.h new file mode 120000 index 0000000000000000000000000000000000000000..7ec2191898e51f9c7be45e63ff28454642ba10c4 --- /dev/null +++ b/tools/kmodules/lisa/debugfs.h @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/debugfs.h \ No newline at end of file