All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: bp@alien8.de, bp@suse.de, hpa@zytor.com, acme@redhat.com,
	tglx@linutronix.de, mingo@redhat.com, jpoimboe@redhat.com,
	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 v7 14/14] lib: add linker tables test driver
Date: Sun, 15 Jan 2017 21:10:57 +0000	[thread overview]
Message-ID: <20170115211057.17167-15-mcgrof@kernel.org> (raw)
In-Reply-To: <20170115211057.17167-1-mcgrof@kernel.org>

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
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 643bce5a5b02..dbbcbb16951d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1839,6 +1839,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 f5e72a728285..899b2f363ef1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -56,6 +56,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..77029c346294
--- /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;
+static bool init_completed;
+
+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)
+{
+	long new;
+	int ret;
+
+	ret = kstrtol(buf, 10, &new);
+		return ret;
+	if (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)
+		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.11.0


WARNING: multiple messages have this Message-ID (diff)
From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: bp@alien8.de, bp@suse.de, hpa@zytor.com, acme@redhat.com,
	tglx@linutronix.de, mingo@redhat.com, jpoimboe@redhat.com,
	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 v7 14/14] lib: add linker tables test driver
Date: Sun, 15 Jan 2017 13:10:57 -0800	[thread overview]
Message-ID: <20170115211057.17167-15-mcgrof@kernel.org> (raw)
In-Reply-To: <20170115211057.17167-1-mcgrof@kernel.org>

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
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 643bce5a5b02..dbbcbb16951d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1839,6 +1839,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 f5e72a728285..899b2f363ef1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -56,6 +56,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..77029c346294
--- /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;
+static bool init_completed;
+
+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)
+{
+	long new;
+	int ret;
+
+	ret = kstrtol(buf, 10, &new);
+		return ret;
+	if (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)
+		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.11.0

WARNING: multiple messages have this Message-ID (diff)
From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: bp@alien8.de, bp@suse.de, hpa@zytor.com, acme@redhat.com,
	tglx@linutronix.de, mingo@redhat.com, jpoimboe@redhat.com,
	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 v7 14/14] lib: add linker tables test driver
Date: Sun, 15 Jan 2017 13:10:57 -0800	[thread overview]
Message-ID: <20170115211057.17167-15-mcgrof@kernel.org> (raw)
In-Reply-To: <20170115211057.17167-1-mcgrof@kernel.org>

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
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 643bce5a5b02..dbbcbb16951d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1839,6 +1839,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 f5e72a728285..899b2f363ef1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -56,6 +56,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..77029c346294
--- /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;
+static bool init_completed;
+
+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)
+{
+	long new;
+	int ret;
+
+	ret = kstrtol(buf, 10, &new);
+		return ret;
+	if (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)
+		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.11.0


  parent reply	other threads:[~2017-01-15 21:10 UTC|newest]

Thread overview: 480+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-19 21:32 [PATCH v4 00/16] linux: generalize sections, ranges and linker tables mcgrof
2016-08-19 21:32 ` mcgrof
2016-08-19 21:32 ` mcgrof
2016-08-19 21:32 ` [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL() mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32 ` [PATCH v4 02/16] dell-smo8800: include uaccess.h mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32 ` [PATCH v4 03/16] scripts/module-common.lds: enable generation mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32 ` [PATCH v4 04/16] generic-sections: add section core helpers mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:47   ` Kees Cook
2016-08-22 23:13     ` Luis R. Rodriguez
2016-08-19 21:32 ` [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32 ` [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:55   ` Kees Cook
2016-08-22 23:48     ` Luis R. Rodriguez
2016-08-19 21:32 ` [PATCH v4 07/16] tables.h: add linker table support mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 22:02   ` Kees Cook
2016-08-22 23:53     ` Luis R. Rodriguez
2016-08-19 21:32 ` [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 22:10   ` Kees Cook
2016-08-22 23:59     ` Luis R. Rodriguez
2016-08-30 20:15       ` Luis R. Rodriguez
2016-08-19 21:32 ` [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32 ` [PATCH v4 10/16] firmware: port built-in section to linker table mcgrof
2016-08-19 21:32   ` mcgrof
2016-08-19 21:32   ` mcgrof
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   ` 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: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     ` 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     ` mcgrof
2016-08-19 21:34     ` 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-19 21:34     ` mcgrof
2016-08-23  1:26     ` Nicholas Piggin
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-23 17:33         ` Luis R. Rodriguez
2016-08-24  3:51         ` Nicholas Piggin
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-24 20:12             ` Luis R. Rodriguez
2016-08-25  2:06             ` Nicholas Piggin
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:05                 ` Luis R. Rodriguez
2016-08-25  6:51                 ` Nicholas Piggin
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-25 17:52                     ` Luis R. Rodriguez
2016-08-26  3:00                     ` Nicholas Piggin
2016-08-26  3:00                       ` Nicholas Piggin
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  7:33                           ` Nicholas Piggin
2016-08-26 13:22                           ` Luis R. Rodriguez
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-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     ` 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     ` 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     ` 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     ` 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     ` 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     ` 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     ` 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     ` 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     ` 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-19 21:34     ` mcgrof
2016-08-22 15:11     ` Masami Hiramatsu
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-23 16:31         ` Luis R. Rodriguez
2016-08-29 14:04         ` Masami Hiramatsu
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
2016-08-30 20:07             ` Luis R. Rodriguez
2017-02-01 20:02           ` 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     ` 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: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     ` 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       ` 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       ` 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       ` 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       ` 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       ` 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       ` mcgrof
2016-08-19 21:41     ` [PATCH v1 7/7] tools: add userspace linker table sandbox mcgrof
2016-08-19 21:41       ` 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  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-23  0:28           ` H. Peter Anvin
2016-08-23  0:28           ` H. Peter Anvin
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-20  4:57       ` Rob Landley
2016-08-21  4:59       ` Rich Felker
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  4:04         ` H. Peter Anvin
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-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       ` 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         ` 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         ` 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         ` 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         ` 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         ` Luis R. Rodriguez
2016-12-22  2:39       ` [PATCH v2 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez
2016-12-22  2:39         ` 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         ` 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           ` 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           ` 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           ` 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           ` 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           ` Luis R. Rodriguez
2017-01-09 15:02         ` [PATCH v3 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez
2017-01-09 15:02           ` 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           ` 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-15 21:12             ` Luis R. Rodriguez
2017-01-19 11:01             ` Greg KH
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-15 21:12             ` Luis R. Rodriguez
2017-01-19 11:02             ` Greg KH
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-15 21:12             ` Luis R. Rodriguez
2017-01-19 11:02             ` Greg KH
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-15 21:12             ` Luis R. Rodriguez
2017-01-19 11:03             ` Greg KH
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-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-15 21:12             ` Luis R. Rodriguez
2017-01-19 11:04             ` Greg KH
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-15 21:12             ` 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     ` 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       ` Luis R. Rodriguez
2016-12-22  2:37       ` 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       ` 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: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  2:38       ` Luis R. Rodriguez
2016-12-22 13:58       ` Andy Shevchenko
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-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       ` 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       ` 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       ` 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       ` 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  2:38       ` Luis R. Rodriguez
2016-12-22 14:08       ` Andy Shevchenko
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
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       ` 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       ` 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       ` 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
2016-12-22  2:38     ` [PATCH v5 14/14] lib: add linker tables test driver Luis R. Rodriguez
2016-12-22  2:38       ` Luis R. Rodriguez
2016-12-22  2:38       ` 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       ` 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-09 14:58         ` Luis R. Rodriguez
2017-01-09 14:58         ` 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-16 14:46           ` Borislav Petkov
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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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         ` 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 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: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-09 18:29             ` Andy Shevchenko
2017-01-11 14:37             ` Luis R. Rodriguez
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         ` 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-15 21:10           ` Luis R. Rodriguez
2017-01-15 21:10           ` 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-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-15 21:10           ` Luis R. Rodriguez
2017-01-18 11:29           ` Borislav Petkov
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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:11           ` Greg KH
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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:13           ` Greg KH
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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:18           ` Greg KH
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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:19           ` Greg KH
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           ` 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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:20           ` Greg KH
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-15 21:10           ` Luis R. Rodriguez
2017-01-19 11:24           ` Greg KH
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           ` 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           ` 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           ` 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           ` Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez [this message]
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
2016-08-19 22:29 ` [PATCH v4 00/16] linux: generalize sections, ranges and linker tables Kees Cook
2016-08-22 23:06   ` 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=20170115211057.17167-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=bp@suse.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: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.