From: "Luis R. Rodriguez" <mcgrof@kernel.org> To: hpa@zytor.com, acme@redhat.com, tglx@linutronix.de, mingo@redhat.com, jpoimboe@redhat.com, bp@alien8.de, npiggin@gmail.com, mhiramat@kernel.org, masami.hiramatsu.pt@hitachi.com, jbaron@akamai.com, heiko.carstens@de.ibm.com, ananth@linux.vnet.ibm.com, anil.s.keshavamurthy@intel.com, davem@davemloft.net, realmz6@gmail.com, dalias@libc.org, linux@arm.linux.org.uk Cc: x86@kernel.org, luto@amacapital.net, keescook@chromium.org, linux@roeck-us.net, torvalds@linux-foundation.org, gregkh@linuxfoundation.org, rusty@rustcorp.com.au, gnomes@lxorguk.ukuu.org.uk, alan@linux.intel.com, dwmw2@infradead.org, arnd@arndb.de, ming.lei@canonical.com, linux-arch@vger.kernel.org, benh@kernel.crashing.org, pebolle@tiscali.nl, fontana@sharpeleven.org, david.vrabel@citrix.com, konrad.wilk@oracle.com, mcb30@ipxe.org, jgross@suse.com, andrew.cooper3@citrix.com, andriy.shevchenko@linux.intel.com, paul.gortmaker@windriver.com, xen-devel@lists.xensource.com, ak@linux.intel.com, pali.rohar@gmail.com, dvhart@infradead.org, platform-driver-x86@vger.kernel.org, mmarek@suse.com, linux@rasmusvillemoes.dk, jkosina@suse.cz, korea.drzix@gmail.com, linux-kbuild@vger.kernel Subject: [PATCH v5 14/14] lib: add linker tables test driver Date: Wed, 21 Dec 2016 18:38:10 -0800 [thread overview] Message-ID: <20161222023811.21246-15-mcgrof@kernel.org> (raw) In-Reply-To: <20161222023811.21246-1-mcgrof@kernel.org> Add a test drivers for linker tables. v5: added this commit for the first time in this series. Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> --- lib/Kconfig.debug | 6 + lib/Makefile | 1 + lib/test_linktables/Makefile | 13 + lib/test_linktables/test-linktables-00.c | 27 ++ lib/test_linktables/test-linktables-01.c | 27 ++ lib/test_linktables/test-linktables-02.c | 27 ++ lib/test_linktables/test-linktables-03.c | 27 ++ lib/test_linktables/test-linktables-04.c | 27 ++ lib/test_linktables/test-linktables.c | 801 +++++++++++++++++++++++++++++++ lib/test_linktables/test-linktables.h | 48 ++ 10 files changed, 1004 insertions(+) create mode 100644 lib/test_linktables/Makefile create mode 100644 lib/test_linktables/test-linktables-00.c create mode 100644 lib/test_linktables/test-linktables-01.c create mode 100644 lib/test_linktables/test-linktables-02.c create mode 100644 lib/test_linktables/test-linktables-03.c create mode 100644 lib/test_linktables/test-linktables-04.c create mode 100644 lib/test_linktables/test-linktables.c create mode 100644 lib/test_linktables/test-linktables.h diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index cb66a4648840..eca09bba2e8d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1850,6 +1850,12 @@ config TEST_HASH This is intended to help people writing architecture-specific optimized versions. If unsure, say N. +config TEST_LINKTABLES + bool "Test linker table functionality" + default n + help + Enable this option to test the kernel's linker table functionality. + endmenu # runtime tests config PROVIDE_OHCI1394_DMA_INIT diff --git a/lib/Makefile b/lib/Makefile index d15e235f72ea..4fce4aceb2a0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o obj-$(CONFIG_TEST_PRINTF) += test_printf.o obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o obj-$(CONFIG_TEST_UUID) += test_uuid.o +obj-$(CONFIG_TEST_LINKTABLES) += test_linktables/ ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/test_linktables/Makefile b/lib/test_linktables/Makefile new file mode 100644 index 000000000000..a1a67d7fd57a --- /dev/null +++ b/lib/test_linktables/Makefile @@ -0,0 +1,13 @@ +__LINKTABLE_TESTS := $(shell find ./ -name test-linktables-\*.c | wc -l) +ccflags-y += -D__LINKTABLE_TESTS=$(__LINKTABLE_TESTS) + +# Keep these disorganized, if linker tables did not work then +# things would not be ordered for us automatically at link time. +# Linker tables grants us the ability to be explicit about +# order. +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-04.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-02.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-01.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-03.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-00.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables.o diff --git a/lib/test_linktables/test-linktables-00.c b/lib/test_linktables/test-linktables-00.c new file mode 100644 index 000000000000..ea162bd69179 --- /dev/null +++ b/lib/test_linktables/test-linktables-00.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_00_init(int input) +{ + return 0 * input; +} + +static int __initdata test_linktable_00_init_data(int input) +{ + return 0 * input; +} + +static int test_linktable_00(int input) +{ + return 0 * input; +} + +test_linktable_init_data(00, test_linktable_00_init_data); /* .init.data */ +test_linktable_init_text(00, test_linktable_00_init); /* .init.text */ +test_linktable(00, test_linktable_00); /* .data */ +test_linktable_text(00, test_linktable_00); /* .text */ +test_linktable_rodata(00, test_linktable_00); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-01.c b/lib/test_linktables/test-linktables-01.c new file mode 100644 index 000000000000..39578990fd59 --- /dev/null +++ b/lib/test_linktables/test-linktables-01.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_01_init(int input) +{ + return 1 * input; +} + +static int __initdata test_linktable_01_init_data(int input) +{ + return 1 * input; +} + +static int test_linktable_01(int input) +{ + return 1 * input; +} + +test_linktable_init_data(01, test_linktable_01_init_data); /* .init.data */ +test_linktable_init_text(01, test_linktable_01_init); /* .init.text */ +test_linktable(01, test_linktable_01); /* .data */ +test_linktable_text(01, test_linktable_01); /* .text */ +test_linktable_rodata(01, test_linktable_01); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-02.c b/lib/test_linktables/test-linktables-02.c new file mode 100644 index 000000000000..7f4b34240ecb --- /dev/null +++ b/lib/test_linktables/test-linktables-02.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_02_init(int input) +{ + return 2 * input; +} + +static int __initdata test_linktable_02_init_data(int input) +{ + return 2 * input; +} + +static int test_linktable_02(int input) +{ + return 2 * input; +} + +test_linktable_init_data(02, test_linktable_02_init_data); /* .init.data */ +test_linktable_init_text(02, test_linktable_02_init); /* .init.text */ +test_linktable(02, test_linktable_02); /* .data */ +test_linktable_text(02, test_linktable_02); /* .text */ +test_linktable_rodata(02, test_linktable_02); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-03.c b/lib/test_linktables/test-linktables-03.c new file mode 100644 index 000000000000..47ca77e30c24 --- /dev/null +++ b/lib/test_linktables/test-linktables-03.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_03_init(int input) +{ + return 3 * input; +} + +static int __initdata test_linktable_03_init_data(int input) +{ + return 3 * input; +} + +static int test_linktable_03(int input) +{ + return 3 * input; +} + +test_linktable_init_data(03, test_linktable_03_init_data); /* .init.data */ +test_linktable_init_text(03, test_linktable_03_init); /* .init.text */ +test_linktable(03, test_linktable_03); /* .data */ +test_linktable_text(03, test_linktable_03); /* .text */ +test_linktable_rodata(03, test_linktable_03); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-04.c b/lib/test_linktables/test-linktables-04.c new file mode 100644 index 000000000000..4123e0e16715 --- /dev/null +++ b/lib/test_linktables/test-linktables-04.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_04_init(int input) +{ + return 4 * input; +} + +static int __initdata test_linktable_04_init_data(int input) +{ + return 4 * input; +} + +static int test_linktable_04(int input) +{ + return 4 * input; +} + +test_linktable_init_data(04, test_linktable_04_init_data); /* .init.data */ +test_linktable_init_text(04, test_linktable_04_init); /* .init.text */ +test_linktable(04, test_linktable_04); /* .data */ +test_linktable_text(04, test_linktable_04); /* .text */ +test_linktable_rodata(04, test_linktable_04); /* .rodata */ diff --git a/lib/test_linktables/test-linktables.c b/lib/test_linktables/test-linktables.c new file mode 100644 index 000000000000..e41cb09ee573 --- /dev/null +++ b/lib/test_linktables/test-linktables.c @@ -0,0 +1,801 @@ +/* + * Linker table test driver + * + * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@kernel.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of copyleft-next (version 0.3.1 or later) as published + * at http://copyleft-next.org/. + */ + +/* + * This driver provides an interface to trigger and test the linker table API + * through a series of configurations and a few triggers. This driver + * must be built-in as linker tables currently lack generalized modular + * support -- additional work is required on each module right now if you + * want to use linker tables, in the future we may make this much easier. + * For now just build this into your kernel. + * + * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n 3 > /sys/devices/virtual/misc/test_linktable/config_input + * echo 1 > /sys/devices/virtual/misc/test_linktable/trigger_config + * cat /sys/devices/virtual/misc/test_linktable/test_result + * 30 + * + * echo -n .data > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n .rodata > /sys/devices/virtual/misc/test_linktable/config_section_name + * + * To check the configuration: + * + * cat /sys/devices/virtual/misc/test_linktable/config + * + * NUM_TESTS + * ∑ test(n, input) + * n=0 + * + * Each linker table entry on each section has a series of entries. Each entry + * has a function which just multiplies the test case number by input value. + * + * ... + * test-linktables-03.c multiplies (3 * input) + * test-linktables-04.c multiplies (4 * input) + * ... + * + * A full run on a section produces the sum of these values. So with input set + * to 3 we have: + * + * (0 * 3) + (1 * 3) + (2 * 3) + (3 * 3) + (4 * 3) + * 0 + 3 + 6 + 9 + 12 + * 30 + * + * This is nothing important, its just a basic test. We had to pick something. + * Other than the above tests, this also demos and shows proper const use on + * all sections which we need as read-only: .text, .init.text, .rodata. + * Furthermore it does a silly write test to ensure write works on .data and + * init.data. Since the read-only sections use const we obviously are forced + * by the compiler to not be able to write to these sections. + * + * One of the more important items, the order, is tested. We could develop + * a fancy simple math algorithm that depends on order for correctness but + * instead we just annotate the expected order as we run. If the order listed + * on test->expected does not match with the actual order a routine was run + * in then we fail and complain. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> +#include <linux/module.h> +#include <linux/miscdevice.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> + +#include "test-linktables.h" + +#define NUM_TESTS __LINKTABLE_TESTS + +struct linktable_test_device *__test_dev = NULL; +static bool init_completed = false; + +static const char *test_dev_name = "test_linktable"; + +/* + * Used for the default test to start configuration with if we reset the + * test from scratch. Don't use .init.* sections given we can only test + * these on init, when init_completed is true we can't .init.* section + * code anymore. + */ +#define TEST_SECTION_START ".data" + +DEFINE_LINKTABLE(struct test_linktable, test_fns_data); +DEFINE_LINKTABLE_TEXT(struct test_linktable, test_fns_text); +DEFINE_LINKTABLE_RO(struct test_linktable, test_fns_rodata); +DEFINE_LINKTABLE_INIT(struct test_linktable, test_fns_init_text); +DEFINE_LINKTABLE_INIT_DATA(struct test_linktable, test_fns_init_data); + +struct test_config { + char *section_name; + int input; + int test_result; +}; + +/** + * linktable_test_device - test device to help test linker tables + * + * @dev_idx: unique ID for test device + * @misc_dev: we use a misc device under the hood + * @dev: pointer to misc_dev's own struct device + * @config_mutex: protects configuration of test + * @trigger_mutex: the test trigger can only be fired once at a time + */ +struct linktable_test_device { + struct test_config config; + struct miscdevice misc_dev; + struct device *dev; + struct mutex config_mutex; + struct mutex trigger_mutex; + unsigned int num_called; +}; + +/** + * enum linktable_test_case - linker table test case + * + * @TEST_LINKTABLE_INIT: tests .init.text (this is all const) + * @TEST_LINKTABLE_INIT_DATA: tests .init.data + * @TEST_LINKTABLE: tests .data + * @TEST_LINKTABLE_TEXT: tests .text (this is all const) + * @TEST_LINKTABLE_RO: tests .rodata (this is all const) + */ +enum linktable_test_case { + __TEST_LINKTABLE_INVALID = 0, + + TEST_LINKTABLE_INIT, + TEST_LINKTABLE_INIT_DATA, + TEST_LINKTABLE, + TEST_LINKTABLE_TEXT, + TEST_LINKTABLE_RO, +}; + +static struct miscdevice *dev_to_misc_dev(struct device *dev) +{ + return dev_get_drvdata(dev); +} + +static +struct linktable_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev) +{ + return container_of(misc_dev, struct linktable_test_device, misc_dev); +} + +static struct linktable_test_device *dev_to_test_dev(struct device *dev) +{ + struct miscdevice *misc_dev; + + misc_dev = dev_to_misc_dev(dev); + + return misc_dev_to_test_dev(misc_dev); +} + +static ssize_t config_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int len = 0; + + mutex_lock(&test_dev->config_mutex); + + len += snprintf(buf, PAGE_SIZE, + "Custom trigger configuration for: %s\n", + dev_name(dev)); + + if (config->section_name) + len += snprintf(buf+len, PAGE_SIZE, + "section name:\t%s\n", + config->section_name); + else + len += snprintf(buf+len, PAGE_SIZE, + "default name:\tEMTPY\n"); + + mutex_unlock(&test_dev->config_mutex); + + return len; +} +static DEVICE_ATTR_RO(config); + +static int write_test(struct test_linktable *test, int write_val) +{ + test->write_test = write_val; + if (test->write_test != write_val) { + pr_warn("Write test failed\n"); + return -EPERM; + } + return 0; +} + +static int __test_linktable(struct linktable_test_device *test_dev, + struct test_linktable *test) +{ + struct test_config *config = &test_dev->config; + int rc; + + if (test->expected != test_dev->num_called) { + pr_warn("test routine ID %d called on order %d\n", + test->expected, test_dev->num_called); + return -EINVAL; + } + + rc = write_test(test, test->expected+1); + if (rc) + return rc; + + rc = test->op(config->input); + test_dev->num_called++; + + return rc; +} + +static int __test_linktable_ro(struct linktable_test_device *test_dev, + const struct test_linktable *test) +{ + struct test_config *config = &test_dev->config; + int rc; + + if (test->expected != test_dev->num_called) { + pr_info("test routine ID %d called on order %d\n", + test->expected, test_dev->num_called); + return -EINVAL; + } + + /* + * Note, compiler would complain if we tried write_test() so + * no need to test that. + */ + + rc = test->op(config->input); + test_dev->num_called++; + + return rc; +} + +static enum linktable_test_case get_test_case(const char *section_name) +{ + if (strcmp(".init.text", section_name) == 0) + return TEST_LINKTABLE_INIT; + if (strcmp(".init.data", section_name) == 0) + return TEST_LINKTABLE_INIT_DATA; + if (strcmp(".data", section_name) == 0) + return TEST_LINKTABLE; + if (strcmp(".text", section_name) == 0) + return TEST_LINKTABLE_TEXT; + if (strcmp(".rodata", section_name) == 0) + return TEST_LINKTABLE_TEXT; + + return __TEST_LINKTABLE_INVALID; +} + +static int __run_sanity_test(struct linktable_test_device *test_dev, + int num_entries) +{ + if (!num_entries) { + pr_warn("no tests -- this is invalid\n"); + return -EINVAL; + } + + pr_debug("number of tests: %d\n", num_entries); + + if (num_entries != NUM_TESTS) { + pr_warn("expected: %d test\n", NUM_TESTS); + return -EINVAL; + } + + return 0; +} + +static int __init run_init_text_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_text); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_init_text) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int __init run_init_data_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_data); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_init_data) + total += __test_linktable(test_dev, test); + + return total; +} + +static int run_data_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_data); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_data) + total += __test_linktable(test_dev, test); + + return total; +} + +static int run_text_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_text); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_text) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int run_rodata_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_rodata); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_rodata) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int __ref __trigger_config_run(struct linktable_test_device *test_dev) +{ + enum linktable_test_case test_case; + struct test_config *config = &test_dev->config; + + test_dev->num_called = 0; + test_case = get_test_case(config->section_name); + + switch (test_case) { + case TEST_LINKTABLE_INIT: + if (!init_completed) + return run_init_text_test(test_dev); + else + return -EACCES; + case TEST_LINKTABLE_INIT_DATA: + if (!init_completed) + return run_init_data_test(test_dev); + else + return -EACCES; + case TEST_LINKTABLE: + return run_data_test(test_dev); + case TEST_LINKTABLE_TEXT: + return run_text_test(test_dev); + case TEST_LINKTABLE_RO: + return run_rodata_test(test_dev); + default: + pr_warn("Invalid test case requested: %s\n", + config->section_name); + return -EINVAL; + } +} + +static int trigger_config_run(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + int rc; + + mutex_lock(&test_dev->trigger_mutex); + mutex_lock(&test_dev->config_mutex); + + pr_debug("running test on '%s'\n", config->section_name); + + rc = __trigger_config_run(test_dev); + + config->test_result = rc; + pr_debug("result: %d\n", rc); + + if (rc < 0) { + rc = -EINVAL; + goto out; + } + + rc = 0; + +out: + mutex_unlock(&test_dev->config_mutex); + mutex_unlock(&test_dev->trigger_mutex); + + return rc; +} + +static ssize_t +trigger_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + int rc; + + rc = trigger_config_run(test_dev); + if (rc) + goto out; + + rc = count; +out: + return rc; +} +static DEVICE_ATTR_WO(trigger_config); + +/* + * XXX: move to kstrncpy() once merged. + * + * Users should use kfree_const() when freeing these. + */ +static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) +{ + *dst = kstrndup(name, count, gfp); + if (!*dst) + return -ENOSPC; + return count; +} + +static int config_copy_section_name(struct test_config *config, + const char *name, + size_t count) +{ + return __kstrncpy(&config->section_name, name, count, GFP_KERNEL); +} + +static void __linktable_config_free(struct test_config *config) +{ + kfree_const(config->section_name); + config->section_name = NULL; +} + +static void linktable_config_free(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + + mutex_lock(&test_dev->config_mutex); + __linktable_config_free(config); + mutex_unlock(&test_dev->config_mutex); +} + +static ssize_t config_section_name_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int rc; + + mutex_lock(&test_dev->config_mutex); + rc = config_copy_section_name(config, buf, count); + mutex_unlock(&test_dev->config_mutex); + + return rc; +} + +/* + * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE. + */ +static ssize_t config_test_show_str(struct mutex *config_mutex, + char *dst, + char *src) +{ + int len; + + mutex_lock(config_mutex); + len = snprintf(dst, PAGE_SIZE, "%s\n", src); + mutex_unlock(config_mutex); + + return len; +} + +static ssize_t config_section_name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return config_test_show_str(&test_dev->config_mutex, buf, + config->section_name); +} +static DEVICE_ATTR(config_section_name, 0644, config_section_name_show, + config_section_name_store); + +static int trigger_config_run_named(struct linktable_test_device *test_dev, + const char *section_name) +{ + int copied; + struct test_config *config = &test_dev->config; + + mutex_lock(&test_dev->config_mutex); + copied = config_copy_section_name(config, section_name, + strlen(section_name)); + mutex_unlock(&test_dev->config_mutex); + + if (copied <=0 || copied != strlen(section_name)) + return -EINVAL; + + return trigger_config_run(test_dev); +} + +static int __linktable_config_init(struct test_config *config) +{ + int ret; + + ret = config_copy_section_name(config, TEST_SECTION_START, + strlen(TEST_SECTION_START)); + if (ret < 0) + goto out; + + config->input = 3; + config->test_result = 0; + +out: + return ret; +} + +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int ret; + + mutex_lock(&test_dev->trigger_mutex); + mutex_lock(&test_dev->config_mutex); + + __linktable_config_free(config); + + ret = __linktable_config_init(config); + if (ret < 0) { + ret = -ENOMEM; + dev_err(dev, "could not alloc settings for config trigger: %d\n", + ret); + goto out; + } + + dev_info(dev, "reset\n"); + ret = count; + +out: + mutex_unlock(&test_dev->config_mutex); + mutex_unlock(&test_dev->trigger_mutex); + + return ret; +} +static DEVICE_ATTR_WO(reset); + +static int test_dev_config_update_int(struct linktable_test_device *test_dev, + const char *buf, size_t size, + int *config) +{ + char *end; + long new = simple_strtol(buf, &end, 0); + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + mutex_lock(&test_dev->config_mutex); + *config = new; + mutex_unlock(&test_dev->config_mutex); + /* Always return full write size even if we didn't consume all */ + return size; +} + +static ssize_t test_dev_config_show_int(struct linktable_test_device *test_dev, + char *buf, + int config) +{ + int val; + + mutex_lock(&test_dev->config_mutex); + val = config; + mutex_unlock(&test_dev->config_mutex); + + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t test_result_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_update_int(test_dev, buf, count, + &config->test_result); +} + +static ssize_t config_input_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_update_int(test_dev, buf, count, + &config->input); +} + +static ssize_t config_input_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_show_int(test_dev, buf, config->input); +} +static DEVICE_ATTR(config_input, 0644, config_input_show, config_input_store); + +static ssize_t test_result_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_show_int(test_dev, buf, config->test_result); +} +static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store); + +#define LINKTABLE_DEV_ATTR(name) &dev_attr_##name.attr + +static struct attribute *test_dev_attrs[] = { + LINKTABLE_DEV_ATTR(trigger_config), + LINKTABLE_DEV_ATTR(config), + LINKTABLE_DEV_ATTR(reset), + + LINKTABLE_DEV_ATTR(config_section_name), + LINKTABLE_DEV_ATTR(config_input), + LINKTABLE_DEV_ATTR(test_result), + + NULL, +}; + +ATTRIBUTE_GROUPS(test_dev); + +static int linktable_config_init(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + int ret; + + mutex_lock(&test_dev->config_mutex); + ret = __linktable_config_init(config); + mutex_unlock(&test_dev->config_mutex); + + return ret; +} + +static struct linktable_test_device *alloc_test_dev_linktable(void) +{ + int rc; + struct linktable_test_device *test_dev; + struct miscdevice *misc_dev; + + test_dev = vmalloc(sizeof(struct linktable_test_device)); + if (!test_dev) { + pr_err("Cannot alloc test_dev\n"); + goto err_out; + } + + memset(test_dev, 0, sizeof(struct linktable_test_device)); + + mutex_init(&test_dev->config_mutex); + mutex_init(&test_dev->trigger_mutex); + + rc = linktable_config_init(test_dev); + if (rc < 0) { + pr_err("Cannot alloc linktable_config_init()\n"); + goto err_out_free; + } + + misc_dev = &test_dev->misc_dev; + + misc_dev->minor = MISC_DYNAMIC_MINOR; + misc_dev->name = test_dev_name; + misc_dev->groups = test_dev_groups; + + return test_dev; + +err_out_free: + kfree(test_dev); +err_out: + return NULL; +} + +static void free_test_dev_linktable(struct linktable_test_device *test_dev) +{ + test_dev->misc_dev.name = NULL; + vfree(test_dev); + test_dev = NULL; + linktable_config_free(test_dev); +} + +static struct linktable_test_device *register_test_dev_linktable(void) +{ + struct linktable_test_device *test_dev = NULL; + int rc; + + test_dev = alloc_test_dev_linktable(); + if (!test_dev) { + return NULL; + } + + rc = misc_register(&test_dev->misc_dev); + if (rc) { + pr_err("could not register misc device: %d\n", rc); + free_test_dev_linktable(test_dev); + return NULL; + } + + test_dev->dev = test_dev->misc_dev.this_device; + dev_dbg(test_dev->dev, "interface ready\n"); + + return test_dev; +} + +static int __init test_linktable_init(void) +{ + struct linktable_test_device *test_dev; + int rc; + + test_dev = register_test_dev_linktable(); + if (!test_dev) { + pr_err("Cannot add test linktable device\n"); + return -ENODEV; + } + + rc = trigger_config_run_named(test_dev, ".init.text"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".init.data"); + if (WARN_ON(rc)) + return rc; + + init_completed = true; + + rc = trigger_config_run_named(test_dev, ".data"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".text"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".rodata"); + if (WARN_ON(rc)) + return rc; + + pr_info("linker table tests: OK!\n"); + + return 0; +} +late_initcall(test_linktable_init); + +static +void unregister_test_dev_linktable(struct linktable_test_device *test_dev) +{ + dev_info(test_dev->dev, "removing interface\n"); + misc_deregister(&test_dev->misc_dev); + free_test_dev_linktable(test_dev); +} + +static void __exit test_linktable_exit(void) +{ + struct linktable_test_device *test_dev = __test_dev; + + unregister_test_dev_linktable(test_dev); +} +module_exit(test_linktable_exit); + +MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>"); +MODULE_LICENSE("GPL"); diff --git a/lib/test_linktables/test-linktables.h b/lib/test_linktables/test-linktables.h new file mode 100644 index 000000000000..c9c9d5c87263 --- /dev/null +++ b/lib/test_linktables/test-linktables.h @@ -0,0 +1,48 @@ +#include <linux/tables.h> + +struct test_linktable { + int expected; + int write_test; + int (*op)(int input_digit); +}; + +#define test_linktable_init_text(__level, __op) \ + static LINKTABLE_INIT(test_fns_init_text, __level) \ + __test_fn_init_text_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_init_data(__level, __op) \ + static LINKTABLE_INIT_DATA(test_fns_init_data, __level) \ + __test_fn_init_data_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable(__level, __op) \ + static LINKTABLE(test_fns_data, __level) \ + __test_fn_data_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_text(__level, __op) \ + static LINKTABLE_TEXT(test_fns_text, __level) \ + __test_fn_text_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_rodata(__level, __op) \ + static LINKTABLE_RO(test_fns_rodata, __level) \ + __test_fn_rodata_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_init_text); +DECLARE_LINKTABLE(struct test_linktable, test_fns_init_data); +DECLARE_LINKTABLE(struct test_linktable, test_fns_data); +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_text); +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_rodata); -- 2.10.1
WARNING: multiple messages have this Message-ID (diff)
From: "Luis R. Rodriguez" <mcgrof@kernel.org> To: hpa@zytor.com, acme@redhat.com, tglx@linutronix.de, mingo@redhat.com, jpoimboe@redhat.com, bp@alien8.de, npiggin@gmail.com, mhiramat@kernel.org, masami.hiramatsu.pt@hitachi.com, jbaron@akamai.com, heiko.carstens@de.ibm.com, ananth@linux.vnet.ibm.com, anil.s.keshavamurthy@intel.com, davem@davemloft.net, realmz6@gmail.com, dalias@libc.org, linux@arm.linux.org.uk Cc: x86@kernel.org, luto@amacapital.net, keescook@chromium.org, linux@roeck-us.net, torvalds@linux-foundation.org, gregkh@linuxfoundation.org, rusty@rustcorp.com.au, gnomes@lxorguk.ukuu.org.uk, alan@linux.intel.com, dwmw2@infradead.org, arnd@arndb.de, ming.lei@canonical.com, linux-arch@vger.kernel.org, benh@kernel.crashing.org, pebolle@tiscali.nl, fontana@sharpeleven.org, david.vrabel@citrix.com, konrad.wilk@oracle.com, mcb30@ipxe.org, jgross@suse.com, andrew.cooper3@citrix.com, andriy.shevchenko@linux.intel.com, paul.gortmaker@windriver.com, xen-devel@lists.xensource.com, ak@linux.intel.com, pali.rohar@gmail.com, dvhart@infradead.org, platform-driver-x86@vger.kernel.org, mmarek@suse.com, linux@rasmusvillemoes.dk, jkosina@suse.cz, korea.drzix@gmail.com, linux-kbuild@vger.kernel.org, tony.luck@intel.com, akpm@linux-foundation.org, linux-ia64@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sh@vger.kernel.org, sparclinux@vger.kernel.org, catalin.marinas@arm.com, will.deacon@arm.com, rostedt@goodmis.org, jani.nikula@intel.com, mchehab@osg.samsung.com, markus.heiser@darmarit.de, jolsa@kernel.org, msalter@redhat.com, chris@zankel.net, jcmvbkbc@gmail.com, linux-xtensa@linux-xtensa.org, adrian.hunter@intel.com, dsahern@gmail.com, namhyung@kernel.org, wangnan0@huawei.com, dmitry.torokhov@gmail.com, joro@8bytes.org, paulus@samba.org, mpe@ellerman.id.au, James.Bottomley@HansenPartnership.com, "Luis R. Rodriguez" <mcgrof@kernel.org> Subject: [PATCH v5 14/14] lib: add linker tables test driver Date: Wed, 21 Dec 2016 18:38:10 -0800 [thread overview] Message-ID: <20161222023811.21246-15-mcgrof@kernel.org> (raw) Message-ID: <20161222023810.JLQXYHLl_syeBitngCCkwRZqiYHyS1zvtr1mwQDOxV4@z> (raw) In-Reply-To: <20161222023811.21246-1-mcgrof@kernel.org> Add a test drivers for linker tables. v5: added this commit for the first time in this series. Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> --- lib/Kconfig.debug | 6 + lib/Makefile | 1 + lib/test_linktables/Makefile | 13 + lib/test_linktables/test-linktables-00.c | 27 ++ lib/test_linktables/test-linktables-01.c | 27 ++ lib/test_linktables/test-linktables-02.c | 27 ++ lib/test_linktables/test-linktables-03.c | 27 ++ lib/test_linktables/test-linktables-04.c | 27 ++ lib/test_linktables/test-linktables.c | 801 +++++++++++++++++++++++++++++++ lib/test_linktables/test-linktables.h | 48 ++ 10 files changed, 1004 insertions(+) create mode 100644 lib/test_linktables/Makefile create mode 100644 lib/test_linktables/test-linktables-00.c create mode 100644 lib/test_linktables/test-linktables-01.c create mode 100644 lib/test_linktables/test-linktables-02.c create mode 100644 lib/test_linktables/test-linktables-03.c create mode 100644 lib/test_linktables/test-linktables-04.c create mode 100644 lib/test_linktables/test-linktables.c create mode 100644 lib/test_linktables/test-linktables.h diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index cb66a4648840..eca09bba2e8d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1850,6 +1850,12 @@ config TEST_HASH This is intended to help people writing architecture-specific optimized versions. If unsure, say N. +config TEST_LINKTABLES + bool "Test linker table functionality" + default n + help + Enable this option to test the kernel's linker table functionality. + endmenu # runtime tests config PROVIDE_OHCI1394_DMA_INIT diff --git a/lib/Makefile b/lib/Makefile index d15e235f72ea..4fce4aceb2a0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o obj-$(CONFIG_TEST_PRINTF) += test_printf.o obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o obj-$(CONFIG_TEST_UUID) += test_uuid.o +obj-$(CONFIG_TEST_LINKTABLES) += test_linktables/ ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/test_linktables/Makefile b/lib/test_linktables/Makefile new file mode 100644 index 000000000000..a1a67d7fd57a --- /dev/null +++ b/lib/test_linktables/Makefile @@ -0,0 +1,13 @@ +__LINKTABLE_TESTS := $(shell find ./ -name test-linktables-\*.c | wc -l) +ccflags-y += -D__LINKTABLE_TESTS=$(__LINKTABLE_TESTS) + +# Keep these disorganized, if linker tables did not work then +# things would not be ordered for us automatically at link time. +# Linker tables grants us the ability to be explicit about +# order. +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-04.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-02.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-01.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-03.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-00.o +obj-$(CONFIG_TEST_LINKTABLES) += test-linktables.o diff --git a/lib/test_linktables/test-linktables-00.c b/lib/test_linktables/test-linktables-00.c new file mode 100644 index 000000000000..ea162bd69179 --- /dev/null +++ b/lib/test_linktables/test-linktables-00.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_00_init(int input) +{ + return 0 * input; +} + +static int __initdata test_linktable_00_init_data(int input) +{ + return 0 * input; +} + +static int test_linktable_00(int input) +{ + return 0 * input; +} + +test_linktable_init_data(00, test_linktable_00_init_data); /* .init.data */ +test_linktable_init_text(00, test_linktable_00_init); /* .init.text */ +test_linktable(00, test_linktable_00); /* .data */ +test_linktable_text(00, test_linktable_00); /* .text */ +test_linktable_rodata(00, test_linktable_00); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-01.c b/lib/test_linktables/test-linktables-01.c new file mode 100644 index 000000000000..39578990fd59 --- /dev/null +++ b/lib/test_linktables/test-linktables-01.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_01_init(int input) +{ + return 1 * input; +} + +static int __initdata test_linktable_01_init_data(int input) +{ + return 1 * input; +} + +static int test_linktable_01(int input) +{ + return 1 * input; +} + +test_linktable_init_data(01, test_linktable_01_init_data); /* .init.data */ +test_linktable_init_text(01, test_linktable_01_init); /* .init.text */ +test_linktable(01, test_linktable_01); /* .data */ +test_linktable_text(01, test_linktable_01); /* .text */ +test_linktable_rodata(01, test_linktable_01); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-02.c b/lib/test_linktables/test-linktables-02.c new file mode 100644 index 000000000000..7f4b34240ecb --- /dev/null +++ b/lib/test_linktables/test-linktables-02.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_02_init(int input) +{ + return 2 * input; +} + +static int __initdata test_linktable_02_init_data(int input) +{ + return 2 * input; +} + +static int test_linktable_02(int input) +{ + return 2 * input; +} + +test_linktable_init_data(02, test_linktable_02_init_data); /* .init.data */ +test_linktable_init_text(02, test_linktable_02_init); /* .init.text */ +test_linktable(02, test_linktable_02); /* .data */ +test_linktable_text(02, test_linktable_02); /* .text */ +test_linktable_rodata(02, test_linktable_02); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-03.c b/lib/test_linktables/test-linktables-03.c new file mode 100644 index 000000000000..47ca77e30c24 --- /dev/null +++ b/lib/test_linktables/test-linktables-03.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_03_init(int input) +{ + return 3 * input; +} + +static int __initdata test_linktable_03_init_data(int input) +{ + return 3 * input; +} + +static int test_linktable_03(int input) +{ + return 3 * input; +} + +test_linktable_init_data(03, test_linktable_03_init_data); /* .init.data */ +test_linktable_init_text(03, test_linktable_03_init); /* .init.text */ +test_linktable(03, test_linktable_03); /* .data */ +test_linktable_text(03, test_linktable_03); /* .text */ +test_linktable_rodata(03, test_linktable_03); /* .rodata */ diff --git a/lib/test_linktables/test-linktables-04.c b/lib/test_linktables/test-linktables-04.c new file mode 100644 index 000000000000..4123e0e16715 --- /dev/null +++ b/lib/test_linktables/test-linktables-04.c @@ -0,0 +1,27 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> + +#include "test-linktables.h" + +static int __init test_linktable_04_init(int input) +{ + return 4 * input; +} + +static int __initdata test_linktable_04_init_data(int input) +{ + return 4 * input; +} + +static int test_linktable_04(int input) +{ + return 4 * input; +} + +test_linktable_init_data(04, test_linktable_04_init_data); /* .init.data */ +test_linktable_init_text(04, test_linktable_04_init); /* .init.text */ +test_linktable(04, test_linktable_04); /* .data */ +test_linktable_text(04, test_linktable_04); /* .text */ +test_linktable_rodata(04, test_linktable_04); /* .rodata */ diff --git a/lib/test_linktables/test-linktables.c b/lib/test_linktables/test-linktables.c new file mode 100644 index 000000000000..e41cb09ee573 --- /dev/null +++ b/lib/test_linktables/test-linktables.c @@ -0,0 +1,801 @@ +/* + * Linker table test driver + * + * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@kernel.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of copyleft-next (version 0.3.1 or later) as published + * at http://copyleft-next.org/. + */ + +/* + * This driver provides an interface to trigger and test the linker table API + * through a series of configurations and a few triggers. This driver + * must be built-in as linker tables currently lack generalized modular + * support -- additional work is required on each module right now if you + * want to use linker tables, in the future we may make this much easier. + * For now just build this into your kernel. + * + * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n 3 > /sys/devices/virtual/misc/test_linktable/config_input + * echo 1 > /sys/devices/virtual/misc/test_linktable/trigger_config + * cat /sys/devices/virtual/misc/test_linktable/test_result + * 30 + * + * echo -n .data > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name + * echo -n .rodata > /sys/devices/virtual/misc/test_linktable/config_section_name + * + * To check the configuration: + * + * cat /sys/devices/virtual/misc/test_linktable/config + * + * NUM_TESTS + * ∑ test(n, input) + * n=0 + * + * Each linker table entry on each section has a series of entries. Each entry + * has a function which just multiplies the test case number by input value. + * + * ... + * test-linktables-03.c multiplies (3 * input) + * test-linktables-04.c multiplies (4 * input) + * ... + * + * A full run on a section produces the sum of these values. So with input set + * to 3 we have: + * + * (0 * 3) + (1 * 3) + (2 * 3) + (3 * 3) + (4 * 3) + * 0 + 3 + 6 + 9 + 12 + * 30 + * + * This is nothing important, its just a basic test. We had to pick something. + * Other than the above tests, this also demos and shows proper const use on + * all sections which we need as read-only: .text, .init.text, .rodata. + * Furthermore it does a silly write test to ensure write works on .data and + * init.data. Since the read-only sections use const we obviously are forced + * by the compiler to not be able to write to these sections. + * + * One of the more important items, the order, is tested. We could develop + * a fancy simple math algorithm that depends on order for correctness but + * instead we just annotate the expected order as we run. If the order listed + * on test->expected does not match with the actual order a routine was run + * in then we fail and complain. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/tables.h> +#include <linux/printk.h> +#include <linux/module.h> +#include <linux/miscdevice.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> + +#include "test-linktables.h" + +#define NUM_TESTS __LINKTABLE_TESTS + +struct linktable_test_device *__test_dev = NULL; +static bool init_completed = false; + +static const char *test_dev_name = "test_linktable"; + +/* + * Used for the default test to start configuration with if we reset the + * test from scratch. Don't use .init.* sections given we can only test + * these on init, when init_completed is true we can't .init.* section + * code anymore. + */ +#define TEST_SECTION_START ".data" + +DEFINE_LINKTABLE(struct test_linktable, test_fns_data); +DEFINE_LINKTABLE_TEXT(struct test_linktable, test_fns_text); +DEFINE_LINKTABLE_RO(struct test_linktable, test_fns_rodata); +DEFINE_LINKTABLE_INIT(struct test_linktable, test_fns_init_text); +DEFINE_LINKTABLE_INIT_DATA(struct test_linktable, test_fns_init_data); + +struct test_config { + char *section_name; + int input; + int test_result; +}; + +/** + * linktable_test_device - test device to help test linker tables + * + * @dev_idx: unique ID for test device + * @misc_dev: we use a misc device under the hood + * @dev: pointer to misc_dev's own struct device + * @config_mutex: protects configuration of test + * @trigger_mutex: the test trigger can only be fired once at a time + */ +struct linktable_test_device { + struct test_config config; + struct miscdevice misc_dev; + struct device *dev; + struct mutex config_mutex; + struct mutex trigger_mutex; + unsigned int num_called; +}; + +/** + * enum linktable_test_case - linker table test case + * + * @TEST_LINKTABLE_INIT: tests .init.text (this is all const) + * @TEST_LINKTABLE_INIT_DATA: tests .init.data + * @TEST_LINKTABLE: tests .data + * @TEST_LINKTABLE_TEXT: tests .text (this is all const) + * @TEST_LINKTABLE_RO: tests .rodata (this is all const) + */ +enum linktable_test_case { + __TEST_LINKTABLE_INVALID = 0, + + TEST_LINKTABLE_INIT, + TEST_LINKTABLE_INIT_DATA, + TEST_LINKTABLE, + TEST_LINKTABLE_TEXT, + TEST_LINKTABLE_RO, +}; + +static struct miscdevice *dev_to_misc_dev(struct device *dev) +{ + return dev_get_drvdata(dev); +} + +static +struct linktable_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev) +{ + return container_of(misc_dev, struct linktable_test_device, misc_dev); +} + +static struct linktable_test_device *dev_to_test_dev(struct device *dev) +{ + struct miscdevice *misc_dev; + + misc_dev = dev_to_misc_dev(dev); + + return misc_dev_to_test_dev(misc_dev); +} + +static ssize_t config_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int len = 0; + + mutex_lock(&test_dev->config_mutex); + + len += snprintf(buf, PAGE_SIZE, + "Custom trigger configuration for: %s\n", + dev_name(dev)); + + if (config->section_name) + len += snprintf(buf+len, PAGE_SIZE, + "section name:\t%s\n", + config->section_name); + else + len += snprintf(buf+len, PAGE_SIZE, + "default name:\tEMTPY\n"); + + mutex_unlock(&test_dev->config_mutex); + + return len; +} +static DEVICE_ATTR_RO(config); + +static int write_test(struct test_linktable *test, int write_val) +{ + test->write_test = write_val; + if (test->write_test != write_val) { + pr_warn("Write test failed\n"); + return -EPERM; + } + return 0; +} + +static int __test_linktable(struct linktable_test_device *test_dev, + struct test_linktable *test) +{ + struct test_config *config = &test_dev->config; + int rc; + + if (test->expected != test_dev->num_called) { + pr_warn("test routine ID %d called on order %d\n", + test->expected, test_dev->num_called); + return -EINVAL; + } + + rc = write_test(test, test->expected+1); + if (rc) + return rc; + + rc = test->op(config->input); + test_dev->num_called++; + + return rc; +} + +static int __test_linktable_ro(struct linktable_test_device *test_dev, + const struct test_linktable *test) +{ + struct test_config *config = &test_dev->config; + int rc; + + if (test->expected != test_dev->num_called) { + pr_info("test routine ID %d called on order %d\n", + test->expected, test_dev->num_called); + return -EINVAL; + } + + /* + * Note, compiler would complain if we tried write_test() so + * no need to test that. + */ + + rc = test->op(config->input); + test_dev->num_called++; + + return rc; +} + +static enum linktable_test_case get_test_case(const char *section_name) +{ + if (strcmp(".init.text", section_name) == 0) + return TEST_LINKTABLE_INIT; + if (strcmp(".init.data", section_name) == 0) + return TEST_LINKTABLE_INIT_DATA; + if (strcmp(".data", section_name) == 0) + return TEST_LINKTABLE; + if (strcmp(".text", section_name) == 0) + return TEST_LINKTABLE_TEXT; + if (strcmp(".rodata", section_name) == 0) + return TEST_LINKTABLE_TEXT; + + return __TEST_LINKTABLE_INVALID; +} + +static int __run_sanity_test(struct linktable_test_device *test_dev, + int num_entries) +{ + if (!num_entries) { + pr_warn("no tests -- this is invalid\n"); + return -EINVAL; + } + + pr_debug("number of tests: %d\n", num_entries); + + if (num_entries != NUM_TESTS) { + pr_warn("expected: %d test\n", NUM_TESTS); + return -EINVAL; + } + + return 0; +} + +static int __init run_init_text_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_text); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_init_text) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int __init run_init_data_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_data); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_init_data) + total += __test_linktable(test_dev, test); + + return total; +} + +static int run_data_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_data); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_data) + total += __test_linktable(test_dev, test); + + return total; +} + +static int run_text_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_text); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_text) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int run_rodata_test(struct linktable_test_device *test_dev) +{ + int ret, total = 0; + const struct test_linktable *test; + unsigned int num_entries = LINKTABLE_SIZE(test_fns_rodata); + + ret = __run_sanity_test(test_dev, num_entries); + if (ret) + return ret; + + LINKTABLE_FOR_EACH(test, test_fns_rodata) + total += __test_linktable_ro(test_dev, test); + + return total; +} + +static int __ref __trigger_config_run(struct linktable_test_device *test_dev) +{ + enum linktable_test_case test_case; + struct test_config *config = &test_dev->config; + + test_dev->num_called = 0; + test_case = get_test_case(config->section_name); + + switch (test_case) { + case TEST_LINKTABLE_INIT: + if (!init_completed) + return run_init_text_test(test_dev); + else + return -EACCES; + case TEST_LINKTABLE_INIT_DATA: + if (!init_completed) + return run_init_data_test(test_dev); + else + return -EACCES; + case TEST_LINKTABLE: + return run_data_test(test_dev); + case TEST_LINKTABLE_TEXT: + return run_text_test(test_dev); + case TEST_LINKTABLE_RO: + return run_rodata_test(test_dev); + default: + pr_warn("Invalid test case requested: %s\n", + config->section_name); + return -EINVAL; + } +} + +static int trigger_config_run(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + int rc; + + mutex_lock(&test_dev->trigger_mutex); + mutex_lock(&test_dev->config_mutex); + + pr_debug("running test on '%s'\n", config->section_name); + + rc = __trigger_config_run(test_dev); + + config->test_result = rc; + pr_debug("result: %d\n", rc); + + if (rc < 0) { + rc = -EINVAL; + goto out; + } + + rc = 0; + +out: + mutex_unlock(&test_dev->config_mutex); + mutex_unlock(&test_dev->trigger_mutex); + + return rc; +} + +static ssize_t +trigger_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + int rc; + + rc = trigger_config_run(test_dev); + if (rc) + goto out; + + rc = count; +out: + return rc; +} +static DEVICE_ATTR_WO(trigger_config); + +/* + * XXX: move to kstrncpy() once merged. + * + * Users should use kfree_const() when freeing these. + */ +static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) +{ + *dst = kstrndup(name, count, gfp); + if (!*dst) + return -ENOSPC; + return count; +} + +static int config_copy_section_name(struct test_config *config, + const char *name, + size_t count) +{ + return __kstrncpy(&config->section_name, name, count, GFP_KERNEL); +} + +static void __linktable_config_free(struct test_config *config) +{ + kfree_const(config->section_name); + config->section_name = NULL; +} + +static void linktable_config_free(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + + mutex_lock(&test_dev->config_mutex); + __linktable_config_free(config); + mutex_unlock(&test_dev->config_mutex); +} + +static ssize_t config_section_name_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int rc; + + mutex_lock(&test_dev->config_mutex); + rc = config_copy_section_name(config, buf, count); + mutex_unlock(&test_dev->config_mutex); + + return rc; +} + +/* + * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE. + */ +static ssize_t config_test_show_str(struct mutex *config_mutex, + char *dst, + char *src) +{ + int len; + + mutex_lock(config_mutex); + len = snprintf(dst, PAGE_SIZE, "%s\n", src); + mutex_unlock(config_mutex); + + return len; +} + +static ssize_t config_section_name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return config_test_show_str(&test_dev->config_mutex, buf, + config->section_name); +} +static DEVICE_ATTR(config_section_name, 0644, config_section_name_show, + config_section_name_store); + +static int trigger_config_run_named(struct linktable_test_device *test_dev, + const char *section_name) +{ + int copied; + struct test_config *config = &test_dev->config; + + mutex_lock(&test_dev->config_mutex); + copied = config_copy_section_name(config, section_name, + strlen(section_name)); + mutex_unlock(&test_dev->config_mutex); + + if (copied <=0 || copied != strlen(section_name)) + return -EINVAL; + + return trigger_config_run(test_dev); +} + +static int __linktable_config_init(struct test_config *config) +{ + int ret; + + ret = config_copy_section_name(config, TEST_SECTION_START, + strlen(TEST_SECTION_START)); + if (ret < 0) + goto out; + + config->input = 3; + config->test_result = 0; + +out: + return ret; +} + +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + int ret; + + mutex_lock(&test_dev->trigger_mutex); + mutex_lock(&test_dev->config_mutex); + + __linktable_config_free(config); + + ret = __linktable_config_init(config); + if (ret < 0) { + ret = -ENOMEM; + dev_err(dev, "could not alloc settings for config trigger: %d\n", + ret); + goto out; + } + + dev_info(dev, "reset\n"); + ret = count; + +out: + mutex_unlock(&test_dev->config_mutex); + mutex_unlock(&test_dev->trigger_mutex); + + return ret; +} +static DEVICE_ATTR_WO(reset); + +static int test_dev_config_update_int(struct linktable_test_device *test_dev, + const char *buf, size_t size, + int *config) +{ + char *end; + long new = simple_strtol(buf, &end, 0); + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + mutex_lock(&test_dev->config_mutex); + *config = new; + mutex_unlock(&test_dev->config_mutex); + /* Always return full write size even if we didn't consume all */ + return size; +} + +static ssize_t test_dev_config_show_int(struct linktable_test_device *test_dev, + char *buf, + int config) +{ + int val; + + mutex_lock(&test_dev->config_mutex); + val = config; + mutex_unlock(&test_dev->config_mutex); + + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t test_result_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_update_int(test_dev, buf, count, + &config->test_result); +} + +static ssize_t config_input_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_update_int(test_dev, buf, count, + &config->input); +} + +static ssize_t config_input_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_show_int(test_dev, buf, config->input); +} +static DEVICE_ATTR(config_input, 0644, config_input_show, config_input_store); + +static ssize_t test_result_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct linktable_test_device *test_dev = dev_to_test_dev(dev); + struct test_config *config = &test_dev->config; + + return test_dev_config_show_int(test_dev, buf, config->test_result); +} +static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store); + +#define LINKTABLE_DEV_ATTR(name) &dev_attr_##name.attr + +static struct attribute *test_dev_attrs[] = { + LINKTABLE_DEV_ATTR(trigger_config), + LINKTABLE_DEV_ATTR(config), + LINKTABLE_DEV_ATTR(reset), + + LINKTABLE_DEV_ATTR(config_section_name), + LINKTABLE_DEV_ATTR(config_input), + LINKTABLE_DEV_ATTR(test_result), + + NULL, +}; + +ATTRIBUTE_GROUPS(test_dev); + +static int linktable_config_init(struct linktable_test_device *test_dev) +{ + struct test_config *config = &test_dev->config; + int ret; + + mutex_lock(&test_dev->config_mutex); + ret = __linktable_config_init(config); + mutex_unlock(&test_dev->config_mutex); + + return ret; +} + +static struct linktable_test_device *alloc_test_dev_linktable(void) +{ + int rc; + struct linktable_test_device *test_dev; + struct miscdevice *misc_dev; + + test_dev = vmalloc(sizeof(struct linktable_test_device)); + if (!test_dev) { + pr_err("Cannot alloc test_dev\n"); + goto err_out; + } + + memset(test_dev, 0, sizeof(struct linktable_test_device)); + + mutex_init(&test_dev->config_mutex); + mutex_init(&test_dev->trigger_mutex); + + rc = linktable_config_init(test_dev); + if (rc < 0) { + pr_err("Cannot alloc linktable_config_init()\n"); + goto err_out_free; + } + + misc_dev = &test_dev->misc_dev; + + misc_dev->minor = MISC_DYNAMIC_MINOR; + misc_dev->name = test_dev_name; + misc_dev->groups = test_dev_groups; + + return test_dev; + +err_out_free: + kfree(test_dev); +err_out: + return NULL; +} + +static void free_test_dev_linktable(struct linktable_test_device *test_dev) +{ + test_dev->misc_dev.name = NULL; + vfree(test_dev); + test_dev = NULL; + linktable_config_free(test_dev); +} + +static struct linktable_test_device *register_test_dev_linktable(void) +{ + struct linktable_test_device *test_dev = NULL; + int rc; + + test_dev = alloc_test_dev_linktable(); + if (!test_dev) { + return NULL; + } + + rc = misc_register(&test_dev->misc_dev); + if (rc) { + pr_err("could not register misc device: %d\n", rc); + free_test_dev_linktable(test_dev); + return NULL; + } + + test_dev->dev = test_dev->misc_dev.this_device; + dev_dbg(test_dev->dev, "interface ready\n"); + + return test_dev; +} + +static int __init test_linktable_init(void) +{ + struct linktable_test_device *test_dev; + int rc; + + test_dev = register_test_dev_linktable(); + if (!test_dev) { + pr_err("Cannot add test linktable device\n"); + return -ENODEV; + } + + rc = trigger_config_run_named(test_dev, ".init.text"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".init.data"); + if (WARN_ON(rc)) + return rc; + + init_completed = true; + + rc = trigger_config_run_named(test_dev, ".data"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".text"); + if (WARN_ON(rc)) + return rc; + rc = trigger_config_run_named(test_dev, ".rodata"); + if (WARN_ON(rc)) + return rc; + + pr_info("linker table tests: OK!\n"); + + return 0; +} +late_initcall(test_linktable_init); + +static +void unregister_test_dev_linktable(struct linktable_test_device *test_dev) +{ + dev_info(test_dev->dev, "removing interface\n"); + misc_deregister(&test_dev->misc_dev); + free_test_dev_linktable(test_dev); +} + +static void __exit test_linktable_exit(void) +{ + struct linktable_test_device *test_dev = __test_dev; + + unregister_test_dev_linktable(test_dev); +} +module_exit(test_linktable_exit); + +MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>"); +MODULE_LICENSE("GPL"); diff --git a/lib/test_linktables/test-linktables.h b/lib/test_linktables/test-linktables.h new file mode 100644 index 000000000000..c9c9d5c87263 --- /dev/null +++ b/lib/test_linktables/test-linktables.h @@ -0,0 +1,48 @@ +#include <linux/tables.h> + +struct test_linktable { + int expected; + int write_test; + int (*op)(int input_digit); +}; + +#define test_linktable_init_text(__level, __op) \ + static LINKTABLE_INIT(test_fns_init_text, __level) \ + __test_fn_init_text_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_init_data(__level, __op) \ + static LINKTABLE_INIT_DATA(test_fns_init_data, __level) \ + __test_fn_init_data_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable(__level, __op) \ + static LINKTABLE(test_fns_data, __level) \ + __test_fn_data_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_text(__level, __op) \ + static LINKTABLE_TEXT(test_fns_text, __level) \ + __test_fn_text_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +#define test_linktable_rodata(__level, __op) \ + static LINKTABLE_RO(test_fns_rodata, __level) \ + __test_fn_rodata_##__op = { \ + .expected = __level, \ + .op = __op, \ +}; + +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_init_text); +DECLARE_LINKTABLE(struct test_linktable, test_fns_init_data); +DECLARE_LINKTABLE(struct test_linktable, test_fns_data); +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_text); +DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_rodata); -- 2.10.1
next prev parent reply other threads:[~2016-12-22 2:38 UTC|newest] Thread overview: 288+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-08-19 21:33 [PATCH v4 00/16] linux: generalize sections, ranges and linker tables mcgrof 2016-08-19 21:33 ` mcgrof 2016-08-19 21:33 ` [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL() mcgrof 2016-08-19 21:33 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 02/16] dell-smo8800: include uaccess.h mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 03/16] scripts/module-common.lds: enable generation mcgrof 2016-08-19 21:34 ` [PATCH v4 04/16] generic-sections: add section core helpers mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-23 1:26 ` Nicholas Piggin 2016-08-23 1:26 ` Nicholas Piggin 2016-08-23 17:33 ` Luis R. Rodriguez 2016-08-23 17:33 ` Luis R. Rodriguez 2016-08-24 3:51 ` Nicholas Piggin 2016-08-24 3:51 ` Nicholas Piggin 2016-08-24 20:12 ` Luis R. Rodriguez 2016-08-24 20:12 ` Luis R. Rodriguez 2016-08-25 2:06 ` Nicholas Piggin 2016-08-25 2:06 ` Nicholas Piggin 2016-08-25 6:05 ` Luis R. Rodriguez 2016-08-25 6:05 ` Luis R. Rodriguez 2016-08-25 6:51 ` Nicholas Piggin 2016-08-25 6:51 ` Nicholas Piggin 2016-08-25 17:52 ` Luis R. Rodriguez 2016-08-25 17:52 ` Luis R. Rodriguez 2016-08-26 3:00 ` Nicholas Piggin 2016-08-26 6:38 ` Luis R. Rodriguez 2016-08-26 7:33 ` Nicholas Piggin 2016-08-26 7:33 ` Nicholas Piggin 2016-08-26 13:22 ` Luis R. Rodriguez 2016-08-26 13:22 ` Luis R. Rodriguez 2016-08-26 13:28 ` Nicholas Piggin 2016-08-26 13:28 ` Nicholas Piggin 2016-08-19 21:34 ` [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 07/16] tables.h: add linker table support mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 10/16] firmware: port built-in section to linker table mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 11/16] jump_label: move guard #endif down where it belongs mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 12/16] jump_label: port __jump_table to linker tables mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 13/16] dynamic_debug: port to use " mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-22 15:11 ` Masami Hiramatsu 2016-08-22 15:11 ` Masami Hiramatsu 2016-08-23 16:31 ` Luis R. Rodriguez 2016-08-23 16:31 ` Luis R. Rodriguez 2016-08-29 14:04 ` Masami Hiramatsu 2016-08-29 14:04 ` Masami Hiramatsu 2016-08-30 20:07 ` Luis R. Rodriguez 2016-08-30 20:07 ` Luis R. Rodriguez 2017-02-01 20:02 ` Luis R. Rodriguez 2017-02-01 20:02 ` Luis R. Rodriguez 2016-08-19 21:34 ` [PATCH v4 15/16] kprobes: port .kprobes.text to section range mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:34 ` [PATCH v4 16/16] kprobes: port blacklist kprobes to linker table mcgrof 2016-08-19 21:34 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 0/7] tools: add linker table userspace sandbox mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 1/7] tools: add a userspace tools bug.h mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 2/7] tools: add a basic tools printk.h mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 3/7] tools: add init.h for tools mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 4/7] tools: add __used and enable to override mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 5/7] tools: expand export.h with VMLINUX_SYMBOL() mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 6/7] tools: add __section() to compiler.h mcgrof 2016-08-19 21:41 ` mcgrof 2016-08-19 21:41 ` [PATCH v1 7/7] tools: add userspace linker table sandbox mcgrof 2016-08-19 22:31 ` Kees Cook 2016-08-23 0:07 ` Luis R. Rodriguez 2016-08-23 0:28 ` H. Peter Anvin 2016-08-23 0:28 ` H. Peter Anvin 2016-08-23 14:30 ` Arnaldo Carvalho de Melo 2016-08-23 14:30 ` Arnaldo Carvalho de Melo 2016-08-24 2:28 ` Kees Cook 2016-08-24 2:28 ` Kees Cook 2016-08-24 12:39 ` Arnaldo Carvalho de Melo 2016-08-24 12:39 ` Arnaldo Carvalho de Melo 2016-08-24 16:20 ` Luis R. Rodriguez 2016-08-24 16:20 ` Luis R. Rodriguez 2016-08-24 19:17 ` Arnaldo Carvalho de Melo 2016-08-24 19:17 ` Arnaldo Carvalho de Melo 2016-08-20 4:57 ` [PATCH v1 0/7] tools: add linker table userspace sandbox Rob Landley 2016-08-20 4:57 ` Rob Landley 2016-08-21 4:59 ` Rich Felker 2016-08-21 4:59 ` Rich Felker 2016-08-22 4:04 ` H. Peter Anvin 2016-08-22 4:04 ` H. Peter Anvin 2016-08-22 9:59 ` Vegard Nossum 2016-08-22 9:59 ` Vegard Nossum 2016-08-23 15:49 ` Luis R. Rodriguez 2016-08-23 15:49 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 0/6] " Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 2/6] tools: add init.h for tools Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 3/6] tools: add __used and enable to override Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 5/6] tools: add __section() to compiler.h Luis R. Rodriguez 2016-12-22 2:39 ` Luis R. Rodriguez 2016-12-22 2:39 ` [PATCH v2 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 0/6] tools: add linker table userspace sandbox Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 2/6] tools: add init.h for tools Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 3/6] tools: add __used and enable to override Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 5/6] tools: add __section() to compiler.h Luis R. Rodriguez 2017-01-09 15:02 ` Luis R. Rodriguez 2017-01-09 15:02 ` [PATCH v3 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez 2017-01-15 21:12 ` [PATCH v4 0/6] tools: add linker table userspace sandbox Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-15 21:12 ` [PATCH v4 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-19 11:01 ` Greg KH 2017-01-19 11:01 ` Greg KH 2017-01-15 21:12 ` [PATCH v4 2/6] tools: add init.h for tools Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-19 11:02 ` Greg KH 2017-01-19 11:02 ` Greg KH 2017-01-15 21:12 ` [PATCH v4 3/6] tools: add __used and enable to override Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-19 11:02 ` Greg KH 2017-01-19 11:02 ` Greg KH 2017-01-15 21:12 ` [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-19 11:03 ` Greg KH 2017-01-19 11:03 ` Greg KH 2017-01-19 11:04 ` Greg KH 2017-01-19 11:04 ` Greg KH 2017-01-15 21:12 ` [PATCH v4 5/6] tools: add __section() to compiler.h Luis R. Rodriguez 2017-01-15 21:12 ` Luis R. Rodriguez 2017-01-19 11:04 ` Greg KH 2017-01-19 11:04 ` Greg KH 2017-01-15 21:12 ` [PATCH v4 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez 2017-01-19 11:07 ` Greg KH 2016-12-22 2:37 ` [PATCH v5 00/14] linux: generalize sections, ranges and linker tables Luis R. Rodriguez 2016-12-22 2:37 ` Luis R. Rodriguez 2016-12-22 2:37 ` [PATCH v5 01/14] generic-sections: add section core helpers Luis R. Rodriguez 2016-12-22 2:37 ` Luis R. Rodriguez 2016-12-22 2:37 ` [PATCH v5 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez 2016-12-22 2:37 ` Luis R. Rodriguez 2016-12-22 2:37 ` [PATCH v5 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez 2016-12-22 2:37 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 04/14] tables.h: add linker table support Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 13:58 ` Andy Shevchenko 2016-12-22 13:58 ` Andy Shevchenko 2017-01-03 21:25 ` Luis R. Rodriguez 2017-01-03 21:25 ` Luis R. Rodriguez 2017-01-04 9:47 ` Andy Shevchenko 2017-01-06 20:00 ` Luis R. Rodriguez 2017-01-06 20:43 ` Andy Shevchenko 2017-01-09 14:22 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 07/14] firmware: port built-in section to linker table Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 14:08 ` Andy Shevchenko 2016-12-22 14:08 ` Andy Shevchenko 2017-01-03 21:27 ` Luis R. Rodriguez 2017-01-03 21:27 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 10/14] dynamic_debug: port to use " Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` [PATCH v5 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez 2016-12-22 2:38 ` Luis R. Rodriguez [this message] 2016-12-22 2:38 ` [PATCH v5 14/14] lib: add linker tables test driver Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 00/14] linux: generalize sections, ranges and linker tables Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 01/14] generic-sections: add section core helpers Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-16 14:46 ` Borislav Petkov 2017-01-16 14:46 ` Borislav Petkov 2017-01-09 14:58 ` [PATCH v6 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 04/14] tables.h: add linker table support Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 07/14] firmware: port built-in section to linker table Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 10/14] dynamic_debug: port to use " Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 14:58 ` [PATCH v6 14/14] lib: add linker tables test driver Luis R. Rodriguez 2017-01-09 14:58 ` Luis R. Rodriguez 2017-01-09 16:27 ` [PATCH v6 00/14] linux: generalize sections, ranges and linker tables Andy Shevchenko 2017-01-09 16:27 ` Andy Shevchenko 2017-01-09 16:36 ` Luis R. Rodriguez 2017-01-09 17:12 ` Shevchenko, Andriy 2017-01-09 17:16 ` Luis R. Rodriguez 2017-01-09 18:29 ` Andy Shevchenko 2017-01-09 18:29 ` Andy Shevchenko 2017-01-11 14:37 ` Luis R. Rodriguez 2017-01-11 14:37 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 " Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 01/14] generic-sections: add section core helpers Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:09 ` Greg KH 2017-01-19 11:09 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-18 11:29 ` Borislav Petkov 2017-01-18 11:29 ` Borislav Petkov 2017-01-15 21:10 ` [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:11 ` Greg KH 2017-01-19 11:11 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 04/14] tables.h: add linker table support Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:13 ` Greg KH 2017-01-19 11:13 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:18 ` Greg KH 2017-01-19 11:18 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:19 ` Greg KH 2017-01-19 11:19 ` Greg KH 2017-01-23 16:12 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 07/14] firmware: port built-in section to linker table Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:20 ` Greg KH 2017-01-19 11:20 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-19 11:24 ` Greg KH 2017-01-19 11:24 ` Greg KH 2017-01-15 21:10 ` [PATCH v7 10/14] dynamic_debug: port to use " Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez 2017-01-15 21:10 ` [PATCH v7 14/14] lib: add linker tables test driver Luis R. Rodriguez 2017-01-15 21:10 ` Luis R. Rodriguez
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20161222023811.21246-15-mcgrof@kernel.org \ --to=mcgrof@kernel.org \ --cc=acme@redhat.com \ --cc=ak@linux.intel.com \ --cc=alan@linux.intel.com \ --cc=ananth@linux.vnet.ibm.com \ --cc=andrew.cooper3@citrix.com \ --cc=andriy.shevchenko@linux.intel.com \ --cc=anil.s.keshavamurthy@intel.com \ --cc=arnd@arndb.de \ --cc=benh@kernel.crashing.org \ --cc=bp@alien8.de \ --cc=dalias@libc.org \ --cc=davem@davemloft.net \ --cc=david.vrabel@citrix.com \ --cc=dvhart@infradead.org \ --cc=dwmw2@infradead.org \ --cc=fontana@sharpeleven.org \ --cc=gnomes@lxorguk.ukuu.org.uk \ --cc=gregkh@linuxfoundation.org \ --cc=heiko.carstens@de.ibm.com \ --cc=hpa@zytor.com \ --cc=jbaron@akamai.com \ --cc=jgross@suse.com \ --cc=jkosina@suse.cz \ --cc=jpoimboe@redhat.com \ --cc=keescook@chromium.org \ --cc=konrad.wilk@oracle.com \ --cc=korea.drzix@gmail.com \ --cc=linux-arch@vger.kernel.org \ --cc=linux-kbuild@vger.kernel \ --cc=linux@arm.linux.org.uk \ --cc=linux@rasmusvillemoes.dk \ --cc=linux@roeck-us.net \ --cc=luto@amacapital.net \ --cc=masami.hiramatsu.pt@hitachi.com \ --cc=mcb30@ipxe.org \ --cc=mhiramat@kernel.org \ --cc=ming.lei@canonical.com \ --cc=mingo@redhat.com \ --cc=mmarek@suse.com \ --cc=npiggin@gmail.com \ --cc=pali.rohar@gmail.com \ --cc=paul.gortmaker@windriver.com \ --cc=pebolle@tiscali.nl \ --cc=platform-driver-x86@vger.kernel.org \ --cc=realmz6@gmail.com \ --cc=rusty@rustcorp.com.au \ --cc=tglx@linutronix.de \ --cc=torvalds@linux-foundation.org \ --cc=x86@kernel.org \ --cc=xen-devel@lists.xensource.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).