linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: hpa@zytor.com, acme@redhat.com, tglx@linutronix.de,
	mingo@redhat.com, jpoimboe@redhat.com, bp@alien8.de,
	npiggin@gmail.com, mhiramat@kernel.org,
	masami.hiramatsu.pt@hitachi.com, jbaron@akamai.com,
	heiko.carstens@de.ibm.com, ananth@linux.vnet.ibm.com,
	anil.s.keshavamurthy@intel.com, davem@davemloft.net,
	realmz6@gmail.com, dalias@libc.org, linux@arm.linux.org.uk
Cc: x86@kernel.org, luto@amacapital.net, keescook@chromium.org,
	linux@roeck-us.net, torvalds@linux-foundation.org,
	gregkh@linuxfoundation.org, rusty@rustcorp.com.au,
	gnomes@lxorguk.ukuu.org.uk, alan@linux.intel.com,
	dwmw2@infradead.org, arnd@arndb.de, ming.lei@canonical.com,
	linux-arch@vger.kernel.org, benh@kernel.crashing.org,
	pebolle@tiscali.nl, fontana@sharpeleven.org,
	david.vrabel@citrix.com, konrad.wilk@oracle.com, mcb30@ipxe.org,
	jgross@suse.com, andrew.cooper3@citrix.com,
	andriy.shevchenko@linux.intel.com, paul.gortmaker@windriver.com,
	xen-devel@lists.xensource.com, ak@linux.intel.com,
	pali.rohar@gmail.com, dvhart@infradead.org,
	platform-driver-x86@vger.kernel.org, mmarek@suse.com,
	linux@rasmusvillemoes.dk, jkosina@suse.cz, korea.drzix@gmail.com,
	linux-kbuild@vger.kernel
Subject: [PATCH v5 14/14] lib: add linker tables test driver
Date: Wed, 21 Dec 2016 18:38:10 -0800	[thread overview]
Message-ID: <20161222023811.21246-15-mcgrof@kernel.org> (raw)
In-Reply-To: <20161222023811.21246-1-mcgrof@kernel.org>

Add a test drivers for linker tables.

v5: added this commit for the first time in this series.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 lib/Kconfig.debug                        |   6 +
 lib/Makefile                             |   1 +
 lib/test_linktables/Makefile             |  13 +
 lib/test_linktables/test-linktables-00.c |  27 ++
 lib/test_linktables/test-linktables-01.c |  27 ++
 lib/test_linktables/test-linktables-02.c |  27 ++
 lib/test_linktables/test-linktables-03.c |  27 ++
 lib/test_linktables/test-linktables-04.c |  27 ++
 lib/test_linktables/test-linktables.c    | 801 +++++++++++++++++++++++++++++++
 lib/test_linktables/test-linktables.h    |  48 ++
 10 files changed, 1004 insertions(+)
 create mode 100644 lib/test_linktables/Makefile
 create mode 100644 lib/test_linktables/test-linktables-00.c
 create mode 100644 lib/test_linktables/test-linktables-01.c
 create mode 100644 lib/test_linktables/test-linktables-02.c
 create mode 100644 lib/test_linktables/test-linktables-03.c
 create mode 100644 lib/test_linktables/test-linktables-04.c
 create mode 100644 lib/test_linktables/test-linktables.c
 create mode 100644 lib/test_linktables/test-linktables.h

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index cb66a4648840..eca09bba2e8d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1850,6 +1850,12 @@ config TEST_HASH
 	  This is intended to help people writing architecture-specific
 	  optimized versions.  If unsure, say N.
 
+config TEST_LINKTABLES
+	bool "Test linker table functionality"
+	default n
+	help
+	  Enable this option to test the kernel's linker table functionality.
+
 endmenu # runtime tests
 
 config PROVIDE_OHCI1394_DMA_INIT
diff --git a/lib/Makefile b/lib/Makefile
index d15e235f72ea..4fce4aceb2a0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
 obj-$(CONFIG_TEST_UUID) += test_uuid.o
+obj-$(CONFIG_TEST_LINKTABLES) += test_linktables/
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_linktables/Makefile b/lib/test_linktables/Makefile
new file mode 100644
index 000000000000..a1a67d7fd57a
--- /dev/null
+++ b/lib/test_linktables/Makefile
@@ -0,0 +1,13 @@
+__LINKTABLE_TESTS := $(shell find ./ -name test-linktables-\*.c | wc -l)
+ccflags-y += -D__LINKTABLE_TESTS=$(__LINKTABLE_TESTS)
+
+# Keep these disorganized, if linker tables did not work then
+# things would not be ordered for us automatically at link time.
+# Linker tables grants us the ability to be explicit about
+# order.
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-04.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-02.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-01.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-03.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-00.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables.o
diff --git a/lib/test_linktables/test-linktables-00.c b/lib/test_linktables/test-linktables-00.c
new file mode 100644
index 000000000000..ea162bd69179
--- /dev/null
+++ b/lib/test_linktables/test-linktables-00.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_00_init(int input)
+{
+	return 0 * input;
+}
+
+static int __initdata test_linktable_00_init_data(int input)
+{
+	return 0 * input;
+}
+
+static int test_linktable_00(int input)
+{
+	return 0 * input;
+}
+
+test_linktable_init_data(00, test_linktable_00_init_data); /* .init.data */
+test_linktable_init_text(00, test_linktable_00_init); /* .init.text */
+test_linktable(00, test_linktable_00); /* .data */
+test_linktable_text(00, test_linktable_00); /* .text */
+test_linktable_rodata(00, test_linktable_00); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-01.c b/lib/test_linktables/test-linktables-01.c
new file mode 100644
index 000000000000..39578990fd59
--- /dev/null
+++ b/lib/test_linktables/test-linktables-01.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_01_init(int input)
+{
+	return 1 * input;
+}
+
+static int __initdata test_linktable_01_init_data(int input)
+{
+	return 1 * input;
+}
+
+static int test_linktable_01(int input)
+{
+	return 1 * input;
+}
+
+test_linktable_init_data(01, test_linktable_01_init_data); /* .init.data */
+test_linktable_init_text(01, test_linktable_01_init); /* .init.text */
+test_linktable(01, test_linktable_01); /* .data */
+test_linktable_text(01, test_linktable_01); /* .text */
+test_linktable_rodata(01, test_linktable_01); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-02.c b/lib/test_linktables/test-linktables-02.c
new file mode 100644
index 000000000000..7f4b34240ecb
--- /dev/null
+++ b/lib/test_linktables/test-linktables-02.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_02_init(int input)
+{
+	return 2 * input;
+}
+
+static int __initdata test_linktable_02_init_data(int input)
+{
+	return 2 * input;
+}
+
+static int test_linktable_02(int input)
+{
+	return 2 * input;
+}
+
+test_linktable_init_data(02, test_linktable_02_init_data); /* .init.data */
+test_linktable_init_text(02, test_linktable_02_init); /* .init.text */
+test_linktable(02, test_linktable_02); /* .data */
+test_linktable_text(02, test_linktable_02); /* .text */
+test_linktable_rodata(02, test_linktable_02); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-03.c b/lib/test_linktables/test-linktables-03.c
new file mode 100644
index 000000000000..47ca77e30c24
--- /dev/null
+++ b/lib/test_linktables/test-linktables-03.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_03_init(int input)
+{
+	return 3 * input;
+}
+
+static int __initdata test_linktable_03_init_data(int input)
+{
+	return 3 * input;
+}
+
+static int test_linktable_03(int input)
+{
+	return 3 * input;
+}
+
+test_linktable_init_data(03, test_linktable_03_init_data); /* .init.data */
+test_linktable_init_text(03, test_linktable_03_init); /* .init.text */
+test_linktable(03, test_linktable_03); /* .data */
+test_linktable_text(03, test_linktable_03); /* .text */
+test_linktable_rodata(03, test_linktable_03); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-04.c b/lib/test_linktables/test-linktables-04.c
new file mode 100644
index 000000000000..4123e0e16715
--- /dev/null
+++ b/lib/test_linktables/test-linktables-04.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_04_init(int input)
+{
+	return 4 * input;
+}
+
+static int __initdata test_linktable_04_init_data(int input)
+{
+	return 4 * input;
+}
+
+static int test_linktable_04(int input)
+{
+	return 4 * input;
+}
+
+test_linktable_init_data(04, test_linktable_04_init_data); /* .init.data */
+test_linktable_init_text(04, test_linktable_04_init); /* .init.text */
+test_linktable(04, test_linktable_04); /* .data */
+test_linktable_text(04, test_linktable_04); /* .text */
+test_linktable_rodata(04, test_linktable_04); /* .rodata */
diff --git a/lib/test_linktables/test-linktables.c b/lib/test_linktables/test-linktables.c
new file mode 100644
index 000000000000..e41cb09ee573
--- /dev/null
+++ b/lib/test_linktables/test-linktables.c
@@ -0,0 +1,801 @@
+/*
+ * Linker table test driver
+ *
+ * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of copyleft-next (version 0.3.1 or later) as published
+ * at http://copyleft-next.org/.
+ */
+
+/*
+ * This driver provides an interface to trigger and test the linker table API
+ * through a series of configurations and a few triggers. This driver
+ * must be built-in as linker tables currently lack generalized modular
+ * support -- additional work is required on each module right now if you
+ * want to use linker tables, in the future we may make this much easier.
+ * For now just build this into your kernel.
+ *
+ * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n 3 > /sys/devices/virtual/misc/test_linktable/config_input
+ * echo 1 > /sys/devices/virtual/misc/test_linktable/trigger_config
+ * cat /sys/devices/virtual/misc/test_linktable/test_result
+ * 30
+ *
+ * echo -n .data > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n .rodata > /sys/devices/virtual/misc/test_linktable/config_section_name
+ *
+ * To check the configuration:
+ *
+ * cat /sys/devices/virtual/misc/test_linktable/config
+ *
+ * NUM_TESTS
+ *    ∑        test(n, input)
+ *   n=0
+ *
+ * Each linker table entry on each section has a series of entries. Each entry
+ * has a function which just multiplies the test case number by input value.
+ *
+ * ...
+ * test-linktables-03.c multiplies (3 * input)
+ * test-linktables-04.c multiplies (4 * input)
+ * ...
+ *
+ * A full run on a section produces the sum of these values. So with input set
+ * to 3 we have:
+ *
+ * (0 * 3) + (1 * 3) + (2 * 3) + (3 * 3) + (4 * 3)
+ *    0    +    3    +    6    +   9     +  12
+ *                    30
+ *
+ * This is nothing important, its just a basic test. We had to pick something.
+ * Other than the above tests, this also demos and shows proper const use on
+ * all sections which we need as read-only: .text, .init.text, .rodata.
+ * Furthermore it does a silly write test to ensure write works on .data and
+ * init.data. Since the read-only sections use const we obviously are forced
+ * by the compiler to not be able to write to these sections.
+ *
+ * One of the more important items, the order, is tested. We could develop
+ * a fancy simple math algorithm that depends on order for correctness but
+ * instead we just annotate the expected order as we run. If the order listed
+ * on test->expected does not match with the actual order a routine was run
+ * in then we fail and complain.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "test-linktables.h"
+
+#define NUM_TESTS __LINKTABLE_TESTS
+
+struct linktable_test_device *__test_dev = NULL;
+static bool init_completed = false;
+
+static const char *test_dev_name = "test_linktable";
+
+/*
+ * Used for the default test to start configuration with if we reset the
+ * test from scratch. Don't use .init.* sections given we can only test
+ * these on init, when init_completed is true we can't .init.* section
+ * code anymore.
+ */
+#define TEST_SECTION_START ".data"
+
+DEFINE_LINKTABLE(struct test_linktable, test_fns_data);
+DEFINE_LINKTABLE_TEXT(struct test_linktable, test_fns_text);
+DEFINE_LINKTABLE_RO(struct test_linktable, test_fns_rodata);
+DEFINE_LINKTABLE_INIT(struct test_linktable, test_fns_init_text);
+DEFINE_LINKTABLE_INIT_DATA(struct test_linktable, test_fns_init_data);
+
+struct test_config {
+	char *section_name;
+	int input;
+	int test_result;
+};
+
+/**
+ * linktable_test_device - test device to help test linker tables
+ *
+ * @dev_idx: unique ID for test device
+ * @misc_dev: we use a misc device under the hood
+ * @dev: pointer to misc_dev's own struct device
+ * @config_mutex: protects configuration of test
+ * @trigger_mutex: the test trigger can only be fired once at a time
+ */
+struct linktable_test_device {
+	struct test_config config;
+	struct miscdevice misc_dev;
+	struct device *dev;
+	struct mutex config_mutex;
+	struct mutex trigger_mutex;
+	unsigned int num_called;
+};
+
+/**
+ * enum linktable_test_case - linker table test case
+ *
+ * @TEST_LINKTABLE_INIT: tests .init.text (this is all const)
+ * @TEST_LINKTABLE_INIT_DATA: tests .init.data
+ * @TEST_LINKTABLE: tests .data
+ * @TEST_LINKTABLE_TEXT: tests .text (this is all const)
+ * @TEST_LINKTABLE_RO: tests .rodata (this is all const)
+ */
+enum linktable_test_case {
+	__TEST_LINKTABLE_INVALID = 0,
+
+	TEST_LINKTABLE_INIT,
+	TEST_LINKTABLE_INIT_DATA,
+	TEST_LINKTABLE,
+	TEST_LINKTABLE_TEXT,
+	TEST_LINKTABLE_RO,
+};
+
+static struct miscdevice *dev_to_misc_dev(struct device *dev)
+{
+	return dev_get_drvdata(dev);
+}
+
+static
+struct linktable_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev)
+{
+	return container_of(misc_dev, struct linktable_test_device, misc_dev);
+}
+
+static struct linktable_test_device *dev_to_test_dev(struct device *dev)
+{
+	struct miscdevice *misc_dev;
+
+	misc_dev = dev_to_misc_dev(dev);
+
+	return misc_dev_to_test_dev(misc_dev);
+}
+
+static ssize_t config_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int len = 0;
+
+	mutex_lock(&test_dev->config_mutex);
+
+	len += snprintf(buf, PAGE_SIZE,
+			"Custom trigger configuration for: %s\n",
+			dev_name(dev));
+
+	if (config->section_name)
+		len += snprintf(buf+len, PAGE_SIZE,
+				"section name:\t%s\n",
+				config->section_name);
+	else
+		len += snprintf(buf+len, PAGE_SIZE,
+				"default name:\tEMTPY\n");
+
+	mutex_unlock(&test_dev->config_mutex);
+
+	return len;
+}
+static DEVICE_ATTR_RO(config);
+
+static int write_test(struct test_linktable *test, int write_val)
+{
+	test->write_test = write_val;
+	if (test->write_test != write_val) {
+		pr_warn("Write test failed\n");
+		return -EPERM;
+	}
+	return 0;
+}
+
+static int __test_linktable(struct linktable_test_device *test_dev,
+			    struct test_linktable *test)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	if (test->expected != test_dev->num_called) {
+		pr_warn("test routine ID %d called on order %d\n",
+			test->expected, test_dev->num_called);
+		return -EINVAL;
+	}
+
+	rc = write_test(test, test->expected+1);
+	if (rc)
+		return rc;
+
+	rc = test->op(config->input);
+	test_dev->num_called++;
+
+	return rc;
+}
+
+static int __test_linktable_ro(struct linktable_test_device *test_dev,
+			       const struct test_linktable *test)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	if (test->expected != test_dev->num_called) {
+		pr_info("test routine ID %d called on order %d\n",
+			test->expected, test_dev->num_called);
+		return -EINVAL;
+	}
+
+	/*
+	 * Note, compiler would complain if we tried write_test() so
+	 * no need to test that.
+	 */
+
+	rc = test->op(config->input);
+	test_dev->num_called++;
+
+	return rc;
+}
+
+static enum linktable_test_case get_test_case(const char *section_name)
+{
+	if (strcmp(".init.text", section_name) == 0)
+		return TEST_LINKTABLE_INIT;
+	if (strcmp(".init.data", section_name) == 0)
+		return TEST_LINKTABLE_INIT_DATA;
+	if (strcmp(".data", section_name) == 0)
+		return TEST_LINKTABLE;
+	if (strcmp(".text", section_name) == 0)
+		return TEST_LINKTABLE_TEXT;
+	if (strcmp(".rodata", section_name) == 0)
+		return TEST_LINKTABLE_TEXT;
+
+	return __TEST_LINKTABLE_INVALID;
+}
+
+static int __run_sanity_test(struct linktable_test_device *test_dev,
+			     int num_entries)
+{
+	if (!num_entries) {
+		pr_warn("no tests -- this is invalid\n");
+		return -EINVAL;
+	}
+
+	pr_debug("number of tests: %d\n", num_entries);
+
+	if (num_entries != NUM_TESTS) {
+		pr_warn("expected: %d test\n", NUM_TESTS);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __init run_init_text_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_text);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_init_text)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int __init run_init_data_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_data);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_init_data)
+		total += __test_linktable(test_dev, test);
+
+	return total;
+}
+
+static int run_data_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_data);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_data)
+		total += __test_linktable(test_dev, test);
+
+	return total;
+}
+
+static int run_text_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_text);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_text)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int run_rodata_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_rodata);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_rodata)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int __ref __trigger_config_run(struct linktable_test_device *test_dev)
+{
+	enum linktable_test_case test_case;
+	struct test_config *config = &test_dev->config;
+
+	test_dev->num_called = 0;
+	test_case = get_test_case(config->section_name);
+
+	switch (test_case) {
+	case TEST_LINKTABLE_INIT:
+		if (!init_completed)
+			return run_init_text_test(test_dev);
+		else
+			return -EACCES;
+	case TEST_LINKTABLE_INIT_DATA:
+		if (!init_completed)
+			return run_init_data_test(test_dev);
+		else
+			return -EACCES;
+	case TEST_LINKTABLE:
+		return run_data_test(test_dev);
+	case TEST_LINKTABLE_TEXT:
+		return run_text_test(test_dev);
+	case TEST_LINKTABLE_RO:
+		return run_rodata_test(test_dev);
+	default:
+		pr_warn("Invalid test case requested: %s\n",
+			config->section_name);
+		return -EINVAL;
+	}
+}
+
+static int trigger_config_run(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	mutex_lock(&test_dev->trigger_mutex);
+	mutex_lock(&test_dev->config_mutex);
+
+	pr_debug("running test on '%s'\n", config->section_name);
+
+	rc = __trigger_config_run(test_dev);
+
+	config->test_result = rc;
+	pr_debug("result: %d\n", rc);
+
+	if (rc < 0) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = 0;
+
+out:
+	mutex_unlock(&test_dev->config_mutex);
+	mutex_unlock(&test_dev->trigger_mutex);
+
+	return rc;
+}
+
+static ssize_t
+trigger_config_store(struct device *dev,
+		     struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	int rc;
+
+	rc = trigger_config_run(test_dev);
+	if (rc)
+		goto out;
+
+	rc = count;
+out:
+	return rc;
+}
+static DEVICE_ATTR_WO(trigger_config);
+
+/*
+ * XXX: move to kstrncpy() once merged.
+ *
+ * Users should use kfree_const() when freeing these.
+ */
+static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
+{
+	*dst = kstrndup(name, count, gfp);
+	if (!*dst)
+		return -ENOSPC;
+	return count;
+}
+
+static int config_copy_section_name(struct test_config *config,
+				    const char *name,
+				    size_t count)
+{
+	return __kstrncpy(&config->section_name, name, count, GFP_KERNEL);
+}
+
+static void __linktable_config_free(struct test_config *config)
+{
+	kfree_const(config->section_name);
+	config->section_name = NULL;
+}
+
+static void linktable_config_free(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+
+	mutex_lock(&test_dev->config_mutex);
+	__linktable_config_free(config);
+	mutex_unlock(&test_dev->config_mutex);
+}
+
+static ssize_t config_section_name_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	mutex_lock(&test_dev->config_mutex);
+	rc = config_copy_section_name(config, buf, count);
+	mutex_unlock(&test_dev->config_mutex);
+
+	return rc;
+}
+
+/*
+ * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
+ */
+static ssize_t config_test_show_str(struct mutex *config_mutex,
+				    char *dst,
+				    char *src)
+{
+	int len;
+
+	mutex_lock(config_mutex);
+	len = snprintf(dst, PAGE_SIZE, "%s\n", src);
+	mutex_unlock(config_mutex);
+
+	return len;
+}
+
+static ssize_t config_section_name_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return config_test_show_str(&test_dev->config_mutex, buf,
+				    config->section_name);
+}
+static DEVICE_ATTR(config_section_name, 0644, config_section_name_show,
+		   config_section_name_store);
+
+static int trigger_config_run_named(struct linktable_test_device *test_dev,
+				    const char *section_name)
+{
+	int copied;
+	struct test_config *config = &test_dev->config;
+
+	mutex_lock(&test_dev->config_mutex);
+	copied = config_copy_section_name(config, section_name,
+					  strlen(section_name));
+	mutex_unlock(&test_dev->config_mutex);
+
+	if (copied <=0 || copied != strlen(section_name))
+		return -EINVAL;
+
+	return trigger_config_run(test_dev);
+}
+
+static int __linktable_config_init(struct test_config *config)
+{
+	int ret;
+
+	ret = config_copy_section_name(config, TEST_SECTION_START,
+				       strlen(TEST_SECTION_START));
+	if (ret < 0)
+		goto out;
+
+	config->input = 3;
+	config->test_result = 0;
+
+out:
+	return ret;
+}
+
+static ssize_t reset_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int ret;
+
+	mutex_lock(&test_dev->trigger_mutex);
+	mutex_lock(&test_dev->config_mutex);
+
+	__linktable_config_free(config);
+
+	ret = __linktable_config_init(config);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		dev_err(dev, "could not alloc settings for config trigger: %d\n",
+		       ret);
+		goto out;
+	}
+
+	dev_info(dev, "reset\n");
+	ret = count;
+
+out:
+	mutex_unlock(&test_dev->config_mutex);
+	mutex_unlock(&test_dev->trigger_mutex);
+
+	return ret;
+}
+static DEVICE_ATTR_WO(reset);
+
+static int test_dev_config_update_int(struct linktable_test_device *test_dev,
+				      const char *buf, size_t size,
+				      int *config)
+{
+	char *end;
+	long new = simple_strtol(buf, &end, 0);
+	if (end == buf || new > INT_MAX || new < INT_MIN)
+		return -EINVAL;
+	mutex_lock(&test_dev->config_mutex);
+	*config = new;
+	mutex_unlock(&test_dev->config_mutex);
+	/* Always return full write size even if we didn't consume all */
+	return size;
+}
+
+static ssize_t test_dev_config_show_int(struct linktable_test_device *test_dev,
+					char *buf,
+					int config)
+{
+	int val;
+
+	mutex_lock(&test_dev->config_mutex);
+	val = config;
+	mutex_unlock(&test_dev->config_mutex);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t test_result_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_update_int(test_dev, buf, count,
+					  &config->test_result);
+}
+
+static ssize_t config_input_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_update_int(test_dev, buf, count,
+					  &config->input);
+}
+
+static ssize_t config_input_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_show_int(test_dev, buf, config->input);
+}
+static DEVICE_ATTR(config_input, 0644, config_input_show, config_input_store);
+
+static ssize_t test_result_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_show_int(test_dev, buf, config->test_result);
+}
+static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store);
+
+#define LINKTABLE_DEV_ATTR(name)		&dev_attr_##name.attr
+
+static struct attribute *test_dev_attrs[] = {
+	LINKTABLE_DEV_ATTR(trigger_config),
+	LINKTABLE_DEV_ATTR(config),
+	LINKTABLE_DEV_ATTR(reset),
+
+	LINKTABLE_DEV_ATTR(config_section_name),
+	LINKTABLE_DEV_ATTR(config_input),
+	LINKTABLE_DEV_ATTR(test_result),
+
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(test_dev);
+
+static int linktable_config_init(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+	int ret;
+
+	mutex_lock(&test_dev->config_mutex);
+	ret = __linktable_config_init(config);
+	mutex_unlock(&test_dev->config_mutex);
+
+	return ret;
+}
+
+static struct linktable_test_device *alloc_test_dev_linktable(void)
+{
+	int rc;
+	struct linktable_test_device *test_dev;
+	struct miscdevice *misc_dev;
+
+	test_dev = vmalloc(sizeof(struct linktable_test_device));
+	if (!test_dev) {
+		pr_err("Cannot alloc test_dev\n");
+		goto err_out;
+	}
+
+	memset(test_dev, 0, sizeof(struct linktable_test_device));
+
+	mutex_init(&test_dev->config_mutex);
+	mutex_init(&test_dev->trigger_mutex);
+
+	rc = linktable_config_init(test_dev);
+	if (rc < 0) {
+		pr_err("Cannot alloc linktable_config_init()\n");
+		goto err_out_free;
+	}
+
+	misc_dev = &test_dev->misc_dev;
+
+	misc_dev->minor = MISC_DYNAMIC_MINOR;
+	misc_dev->name = test_dev_name;
+	misc_dev->groups = test_dev_groups;
+
+	return test_dev;
+
+err_out_free:
+	kfree(test_dev);
+err_out:
+	return NULL;
+}
+
+static void free_test_dev_linktable(struct linktable_test_device *test_dev)
+{
+	test_dev->misc_dev.name = NULL;
+	vfree(test_dev);
+	test_dev = NULL;
+	linktable_config_free(test_dev);
+}
+
+static struct linktable_test_device *register_test_dev_linktable(void)
+{
+	struct linktable_test_device *test_dev = NULL;
+	int rc;
+
+	test_dev = alloc_test_dev_linktable();
+	if (!test_dev) {
+		return NULL;
+	}
+
+	rc = misc_register(&test_dev->misc_dev);
+	if (rc) {
+		pr_err("could not register misc device: %d\n", rc);
+		free_test_dev_linktable(test_dev);
+		return NULL;
+	}
+
+	test_dev->dev = test_dev->misc_dev.this_device;
+	dev_dbg(test_dev->dev, "interface ready\n");
+
+	return test_dev;
+}
+
+static int __init test_linktable_init(void)
+{
+	struct linktable_test_device *test_dev;
+	int rc;
+
+	test_dev = register_test_dev_linktable();
+	if (!test_dev) {
+		pr_err("Cannot add test linktable device\n");
+		return -ENODEV;
+	}
+
+	rc = trigger_config_run_named(test_dev, ".init.text");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".init.data");
+	if (WARN_ON(rc))
+		return rc;
+
+	init_completed = true;
+
+	rc = trigger_config_run_named(test_dev, ".data");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".text");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".rodata");
+	if (WARN_ON(rc))
+		return rc;
+
+	pr_info("linker table tests: OK!\n");
+
+	return 0;
+}
+late_initcall(test_linktable_init);
+
+static
+void unregister_test_dev_linktable(struct linktable_test_device *test_dev)
+{
+	dev_info(test_dev->dev, "removing interface\n");
+	misc_deregister(&test_dev->misc_dev);
+	free_test_dev_linktable(test_dev);
+}
+
+static void __exit test_linktable_exit(void)
+{
+	struct linktable_test_device *test_dev = __test_dev;
+
+	unregister_test_dev_linktable(test_dev);
+}
+module_exit(test_linktable_exit);
+
+MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/lib/test_linktables/test-linktables.h b/lib/test_linktables/test-linktables.h
new file mode 100644
index 000000000000..c9c9d5c87263
--- /dev/null
+++ b/lib/test_linktables/test-linktables.h
@@ -0,0 +1,48 @@
+#include <linux/tables.h>
+
+struct test_linktable {
+	int expected;
+	int write_test;
+	int (*op)(int input_digit);
+};
+
+#define test_linktable_init_text(__level, __op)				\
+	static LINKTABLE_INIT(test_fns_init_text, __level)		\
+	__test_fn_init_text_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_init_data(__level, __op)				\
+	static LINKTABLE_INIT_DATA(test_fns_init_data, __level)		\
+	__test_fn_init_data_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable(__level, __op)					\
+	static LINKTABLE(test_fns_data, __level)			\
+	__test_fn_data_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_text(__level, __op)				\
+	static LINKTABLE_TEXT(test_fns_text, __level)			\
+	__test_fn_text_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_rodata(__level, __op)				\
+	static LINKTABLE_RO(test_fns_rodata, __level)			\
+	__test_fn_rodata_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_init_text);
+DECLARE_LINKTABLE(struct test_linktable, test_fns_init_data);
+DECLARE_LINKTABLE(struct test_linktable, test_fns_data);
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_text);
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_rodata);
-- 
2.10.1


WARNING: multiple messages have this Message-ID (diff)
From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: hpa@zytor.com, acme@redhat.com, tglx@linutronix.de,
	mingo@redhat.com, jpoimboe@redhat.com, bp@alien8.de,
	npiggin@gmail.com, mhiramat@kernel.org,
	masami.hiramatsu.pt@hitachi.com, jbaron@akamai.com,
	heiko.carstens@de.ibm.com, ananth@linux.vnet.ibm.com,
	anil.s.keshavamurthy@intel.com, davem@davemloft.net,
	realmz6@gmail.com, dalias@libc.org, linux@arm.linux.org.uk
Cc: x86@kernel.org, luto@amacapital.net, keescook@chromium.org,
	linux@roeck-us.net, torvalds@linux-foundation.org,
	gregkh@linuxfoundation.org, rusty@rustcorp.com.au,
	gnomes@lxorguk.ukuu.org.uk, alan@linux.intel.com,
	dwmw2@infradead.org, arnd@arndb.de, ming.lei@canonical.com,
	linux-arch@vger.kernel.org, benh@kernel.crashing.org,
	pebolle@tiscali.nl, fontana@sharpeleven.org,
	david.vrabel@citrix.com, konrad.wilk@oracle.com, mcb30@ipxe.org,
	jgross@suse.com, andrew.cooper3@citrix.com,
	andriy.shevchenko@linux.intel.com, paul.gortmaker@windriver.com,
	xen-devel@lists.xensource.com, ak@linux.intel.com,
	pali.rohar@gmail.com, dvhart@infradead.org,
	platform-driver-x86@vger.kernel.org, mmarek@suse.com,
	linux@rasmusvillemoes.dk, jkosina@suse.cz, korea.drzix@gmail.com,
	linux-kbuild@vger.kernel.org, tony.luck@intel.com,
	akpm@linux-foundation.org, linux-ia64@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-sh@vger.kernel.org,
	sparclinux@vger.kernel.org, catalin.marinas@arm.com,
	will.deacon@arm.com, rostedt@goodmis.org, jani.nikula@intel.com,
	mchehab@osg.samsung.com, markus.heiser@darmarit.de,
	jolsa@kernel.org, msalter@redhat.com, chris@zankel.net,
	jcmvbkbc@gmail.com, linux-xtensa@linux-xtensa.org,
	adrian.hunter@intel.com, dsahern@gmail.com, namhyung@kernel.org,
	wangnan0@huawei.com, dmitry.torokhov@gmail.com, joro@8bytes.org,
	paulus@samba.org, mpe@ellerman.id.au,
	James.Bottomley@HansenPartnership.com,
	"Luis R. Rodriguez" <mcgrof@kernel.org>
Subject: [PATCH v5 14/14] lib: add linker tables test driver
Date: Wed, 21 Dec 2016 18:38:10 -0800	[thread overview]
Message-ID: <20161222023811.21246-15-mcgrof@kernel.org> (raw)
Message-ID: <20161222023810.JLQXYHLl_syeBitngCCkwRZqiYHyS1zvtr1mwQDOxV4@z> (raw)
In-Reply-To: <20161222023811.21246-1-mcgrof@kernel.org>

Add a test drivers for linker tables.

v5: added this commit for the first time in this series.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 lib/Kconfig.debug                        |   6 +
 lib/Makefile                             |   1 +
 lib/test_linktables/Makefile             |  13 +
 lib/test_linktables/test-linktables-00.c |  27 ++
 lib/test_linktables/test-linktables-01.c |  27 ++
 lib/test_linktables/test-linktables-02.c |  27 ++
 lib/test_linktables/test-linktables-03.c |  27 ++
 lib/test_linktables/test-linktables-04.c |  27 ++
 lib/test_linktables/test-linktables.c    | 801 +++++++++++++++++++++++++++++++
 lib/test_linktables/test-linktables.h    |  48 ++
 10 files changed, 1004 insertions(+)
 create mode 100644 lib/test_linktables/Makefile
 create mode 100644 lib/test_linktables/test-linktables-00.c
 create mode 100644 lib/test_linktables/test-linktables-01.c
 create mode 100644 lib/test_linktables/test-linktables-02.c
 create mode 100644 lib/test_linktables/test-linktables-03.c
 create mode 100644 lib/test_linktables/test-linktables-04.c
 create mode 100644 lib/test_linktables/test-linktables.c
 create mode 100644 lib/test_linktables/test-linktables.h

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index cb66a4648840..eca09bba2e8d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1850,6 +1850,12 @@ config TEST_HASH
 	  This is intended to help people writing architecture-specific
 	  optimized versions.  If unsure, say N.
 
+config TEST_LINKTABLES
+	bool "Test linker table functionality"
+	default n
+	help
+	  Enable this option to test the kernel's linker table functionality.
+
 endmenu # runtime tests
 
 config PROVIDE_OHCI1394_DMA_INIT
diff --git a/lib/Makefile b/lib/Makefile
index d15e235f72ea..4fce4aceb2a0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
 obj-$(CONFIG_TEST_UUID) += test_uuid.o
+obj-$(CONFIG_TEST_LINKTABLES) += test_linktables/
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_linktables/Makefile b/lib/test_linktables/Makefile
new file mode 100644
index 000000000000..a1a67d7fd57a
--- /dev/null
+++ b/lib/test_linktables/Makefile
@@ -0,0 +1,13 @@
+__LINKTABLE_TESTS := $(shell find ./ -name test-linktables-\*.c | wc -l)
+ccflags-y += -D__LINKTABLE_TESTS=$(__LINKTABLE_TESTS)
+
+# Keep these disorganized, if linker tables did not work then
+# things would not be ordered for us automatically at link time.
+# Linker tables grants us the ability to be explicit about
+# order.
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-04.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-02.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-01.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-03.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables-00.o
+obj-$(CONFIG_TEST_LINKTABLES) += test-linktables.o
diff --git a/lib/test_linktables/test-linktables-00.c b/lib/test_linktables/test-linktables-00.c
new file mode 100644
index 000000000000..ea162bd69179
--- /dev/null
+++ b/lib/test_linktables/test-linktables-00.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_00_init(int input)
+{
+	return 0 * input;
+}
+
+static int __initdata test_linktable_00_init_data(int input)
+{
+	return 0 * input;
+}
+
+static int test_linktable_00(int input)
+{
+	return 0 * input;
+}
+
+test_linktable_init_data(00, test_linktable_00_init_data); /* .init.data */
+test_linktable_init_text(00, test_linktable_00_init); /* .init.text */
+test_linktable(00, test_linktable_00); /* .data */
+test_linktable_text(00, test_linktable_00); /* .text */
+test_linktable_rodata(00, test_linktable_00); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-01.c b/lib/test_linktables/test-linktables-01.c
new file mode 100644
index 000000000000..39578990fd59
--- /dev/null
+++ b/lib/test_linktables/test-linktables-01.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_01_init(int input)
+{
+	return 1 * input;
+}
+
+static int __initdata test_linktable_01_init_data(int input)
+{
+	return 1 * input;
+}
+
+static int test_linktable_01(int input)
+{
+	return 1 * input;
+}
+
+test_linktable_init_data(01, test_linktable_01_init_data); /* .init.data */
+test_linktable_init_text(01, test_linktable_01_init); /* .init.text */
+test_linktable(01, test_linktable_01); /* .data */
+test_linktable_text(01, test_linktable_01); /* .text */
+test_linktable_rodata(01, test_linktable_01); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-02.c b/lib/test_linktables/test-linktables-02.c
new file mode 100644
index 000000000000..7f4b34240ecb
--- /dev/null
+++ b/lib/test_linktables/test-linktables-02.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_02_init(int input)
+{
+	return 2 * input;
+}
+
+static int __initdata test_linktable_02_init_data(int input)
+{
+	return 2 * input;
+}
+
+static int test_linktable_02(int input)
+{
+	return 2 * input;
+}
+
+test_linktable_init_data(02, test_linktable_02_init_data); /* .init.data */
+test_linktable_init_text(02, test_linktable_02_init); /* .init.text */
+test_linktable(02, test_linktable_02); /* .data */
+test_linktable_text(02, test_linktable_02); /* .text */
+test_linktable_rodata(02, test_linktable_02); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-03.c b/lib/test_linktables/test-linktables-03.c
new file mode 100644
index 000000000000..47ca77e30c24
--- /dev/null
+++ b/lib/test_linktables/test-linktables-03.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_03_init(int input)
+{
+	return 3 * input;
+}
+
+static int __initdata test_linktable_03_init_data(int input)
+{
+	return 3 * input;
+}
+
+static int test_linktable_03(int input)
+{
+	return 3 * input;
+}
+
+test_linktable_init_data(03, test_linktable_03_init_data); /* .init.data */
+test_linktable_init_text(03, test_linktable_03_init); /* .init.text */
+test_linktable(03, test_linktable_03); /* .data */
+test_linktable_text(03, test_linktable_03); /* .text */
+test_linktable_rodata(03, test_linktable_03); /* .rodata */
diff --git a/lib/test_linktables/test-linktables-04.c b/lib/test_linktables/test-linktables-04.c
new file mode 100644
index 000000000000..4123e0e16715
--- /dev/null
+++ b/lib/test_linktables/test-linktables-04.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+
+#include "test-linktables.h"
+
+static int __init test_linktable_04_init(int input)
+{
+	return 4 * input;
+}
+
+static int __initdata test_linktable_04_init_data(int input)
+{
+	return 4 * input;
+}
+
+static int test_linktable_04(int input)
+{
+	return 4 * input;
+}
+
+test_linktable_init_data(04, test_linktable_04_init_data); /* .init.data */
+test_linktable_init_text(04, test_linktable_04_init); /* .init.text */
+test_linktable(04, test_linktable_04); /* .data */
+test_linktable_text(04, test_linktable_04); /* .text */
+test_linktable_rodata(04, test_linktable_04); /* .rodata */
diff --git a/lib/test_linktables/test-linktables.c b/lib/test_linktables/test-linktables.c
new file mode 100644
index 000000000000..e41cb09ee573
--- /dev/null
+++ b/lib/test_linktables/test-linktables.c
@@ -0,0 +1,801 @@
+/*
+ * Linker table test driver
+ *
+ * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of copyleft-next (version 0.3.1 or later) as published
+ * at http://copyleft-next.org/.
+ */
+
+/*
+ * This driver provides an interface to trigger and test the linker table API
+ * through a series of configurations and a few triggers. This driver
+ * must be built-in as linker tables currently lack generalized modular
+ * support -- additional work is required on each module right now if you
+ * want to use linker tables, in the future we may make this much easier.
+ * For now just build this into your kernel.
+ *
+ * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n 3 > /sys/devices/virtual/misc/test_linktable/config_input
+ * echo 1 > /sys/devices/virtual/misc/test_linktable/trigger_config
+ * cat /sys/devices/virtual/misc/test_linktable/test_result
+ * 30
+ *
+ * echo -n .data > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n .text > /sys/devices/virtual/misc/test_linktable/config_section_name
+ * echo -n .rodata > /sys/devices/virtual/misc/test_linktable/config_section_name
+ *
+ * To check the configuration:
+ *
+ * cat /sys/devices/virtual/misc/test_linktable/config
+ *
+ * NUM_TESTS
+ *    ∑        test(n, input)
+ *   n=0
+ *
+ * Each linker table entry on each section has a series of entries. Each entry
+ * has a function which just multiplies the test case number by input value.
+ *
+ * ...
+ * test-linktables-03.c multiplies (3 * input)
+ * test-linktables-04.c multiplies (4 * input)
+ * ...
+ *
+ * A full run on a section produces the sum of these values. So with input set
+ * to 3 we have:
+ *
+ * (0 * 3) + (1 * 3) + (2 * 3) + (3 * 3) + (4 * 3)
+ *    0    +    3    +    6    +   9     +  12
+ *                    30
+ *
+ * This is nothing important, its just a basic test. We had to pick something.
+ * Other than the above tests, this also demos and shows proper const use on
+ * all sections which we need as read-only: .text, .init.text, .rodata.
+ * Furthermore it does a silly write test to ensure write works on .data and
+ * init.data. Since the read-only sections use const we obviously are forced
+ * by the compiler to not be able to write to these sections.
+ *
+ * One of the more important items, the order, is tested. We could develop
+ * a fancy simple math algorithm that depends on order for correctness but
+ * instead we just annotate the expected order as we run. If the order listed
+ * on test->expected does not match with the actual order a routine was run
+ * in then we fail and complain.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/tables.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "test-linktables.h"
+
+#define NUM_TESTS __LINKTABLE_TESTS
+
+struct linktable_test_device *__test_dev = NULL;
+static bool init_completed = false;
+
+static const char *test_dev_name = "test_linktable";
+
+/*
+ * Used for the default test to start configuration with if we reset the
+ * test from scratch. Don't use .init.* sections given we can only test
+ * these on init, when init_completed is true we can't .init.* section
+ * code anymore.
+ */
+#define TEST_SECTION_START ".data"
+
+DEFINE_LINKTABLE(struct test_linktable, test_fns_data);
+DEFINE_LINKTABLE_TEXT(struct test_linktable, test_fns_text);
+DEFINE_LINKTABLE_RO(struct test_linktable, test_fns_rodata);
+DEFINE_LINKTABLE_INIT(struct test_linktable, test_fns_init_text);
+DEFINE_LINKTABLE_INIT_DATA(struct test_linktable, test_fns_init_data);
+
+struct test_config {
+	char *section_name;
+	int input;
+	int test_result;
+};
+
+/**
+ * linktable_test_device - test device to help test linker tables
+ *
+ * @dev_idx: unique ID for test device
+ * @misc_dev: we use a misc device under the hood
+ * @dev: pointer to misc_dev's own struct device
+ * @config_mutex: protects configuration of test
+ * @trigger_mutex: the test trigger can only be fired once at a time
+ */
+struct linktable_test_device {
+	struct test_config config;
+	struct miscdevice misc_dev;
+	struct device *dev;
+	struct mutex config_mutex;
+	struct mutex trigger_mutex;
+	unsigned int num_called;
+};
+
+/**
+ * enum linktable_test_case - linker table test case
+ *
+ * @TEST_LINKTABLE_INIT: tests .init.text (this is all const)
+ * @TEST_LINKTABLE_INIT_DATA: tests .init.data
+ * @TEST_LINKTABLE: tests .data
+ * @TEST_LINKTABLE_TEXT: tests .text (this is all const)
+ * @TEST_LINKTABLE_RO: tests .rodata (this is all const)
+ */
+enum linktable_test_case {
+	__TEST_LINKTABLE_INVALID = 0,
+
+	TEST_LINKTABLE_INIT,
+	TEST_LINKTABLE_INIT_DATA,
+	TEST_LINKTABLE,
+	TEST_LINKTABLE_TEXT,
+	TEST_LINKTABLE_RO,
+};
+
+static struct miscdevice *dev_to_misc_dev(struct device *dev)
+{
+	return dev_get_drvdata(dev);
+}
+
+static
+struct linktable_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev)
+{
+	return container_of(misc_dev, struct linktable_test_device, misc_dev);
+}
+
+static struct linktable_test_device *dev_to_test_dev(struct device *dev)
+{
+	struct miscdevice *misc_dev;
+
+	misc_dev = dev_to_misc_dev(dev);
+
+	return misc_dev_to_test_dev(misc_dev);
+}
+
+static ssize_t config_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int len = 0;
+
+	mutex_lock(&test_dev->config_mutex);
+
+	len += snprintf(buf, PAGE_SIZE,
+			"Custom trigger configuration for: %s\n",
+			dev_name(dev));
+
+	if (config->section_name)
+		len += snprintf(buf+len, PAGE_SIZE,
+				"section name:\t%s\n",
+				config->section_name);
+	else
+		len += snprintf(buf+len, PAGE_SIZE,
+				"default name:\tEMTPY\n");
+
+	mutex_unlock(&test_dev->config_mutex);
+
+	return len;
+}
+static DEVICE_ATTR_RO(config);
+
+static int write_test(struct test_linktable *test, int write_val)
+{
+	test->write_test = write_val;
+	if (test->write_test != write_val) {
+		pr_warn("Write test failed\n");
+		return -EPERM;
+	}
+	return 0;
+}
+
+static int __test_linktable(struct linktable_test_device *test_dev,
+			    struct test_linktable *test)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	if (test->expected != test_dev->num_called) {
+		pr_warn("test routine ID %d called on order %d\n",
+			test->expected, test_dev->num_called);
+		return -EINVAL;
+	}
+
+	rc = write_test(test, test->expected+1);
+	if (rc)
+		return rc;
+
+	rc = test->op(config->input);
+	test_dev->num_called++;
+
+	return rc;
+}
+
+static int __test_linktable_ro(struct linktable_test_device *test_dev,
+			       const struct test_linktable *test)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	if (test->expected != test_dev->num_called) {
+		pr_info("test routine ID %d called on order %d\n",
+			test->expected, test_dev->num_called);
+		return -EINVAL;
+	}
+
+	/*
+	 * Note, compiler would complain if we tried write_test() so
+	 * no need to test that.
+	 */
+
+	rc = test->op(config->input);
+	test_dev->num_called++;
+
+	return rc;
+}
+
+static enum linktable_test_case get_test_case(const char *section_name)
+{
+	if (strcmp(".init.text", section_name) == 0)
+		return TEST_LINKTABLE_INIT;
+	if (strcmp(".init.data", section_name) == 0)
+		return TEST_LINKTABLE_INIT_DATA;
+	if (strcmp(".data", section_name) == 0)
+		return TEST_LINKTABLE;
+	if (strcmp(".text", section_name) == 0)
+		return TEST_LINKTABLE_TEXT;
+	if (strcmp(".rodata", section_name) == 0)
+		return TEST_LINKTABLE_TEXT;
+
+	return __TEST_LINKTABLE_INVALID;
+}
+
+static int __run_sanity_test(struct linktable_test_device *test_dev,
+			     int num_entries)
+{
+	if (!num_entries) {
+		pr_warn("no tests -- this is invalid\n");
+		return -EINVAL;
+	}
+
+	pr_debug("number of tests: %d\n", num_entries);
+
+	if (num_entries != NUM_TESTS) {
+		pr_warn("expected: %d test\n", NUM_TESTS);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __init run_init_text_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_text);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_init_text)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int __init run_init_data_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_init_data);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_init_data)
+		total += __test_linktable(test_dev, test);
+
+	return total;
+}
+
+static int run_data_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_data);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_data)
+		total += __test_linktable(test_dev, test);
+
+	return total;
+}
+
+static int run_text_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_text);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_text)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int run_rodata_test(struct linktable_test_device *test_dev)
+{
+	int ret, total = 0;
+	const struct test_linktable *test;
+	unsigned int num_entries = LINKTABLE_SIZE(test_fns_rodata);
+
+	ret = __run_sanity_test(test_dev, num_entries);
+	if (ret)
+		return ret;
+
+	LINKTABLE_FOR_EACH(test, test_fns_rodata)
+		total += __test_linktable_ro(test_dev, test);
+
+	return total;
+}
+
+static int __ref __trigger_config_run(struct linktable_test_device *test_dev)
+{
+	enum linktable_test_case test_case;
+	struct test_config *config = &test_dev->config;
+
+	test_dev->num_called = 0;
+	test_case = get_test_case(config->section_name);
+
+	switch (test_case) {
+	case TEST_LINKTABLE_INIT:
+		if (!init_completed)
+			return run_init_text_test(test_dev);
+		else
+			return -EACCES;
+	case TEST_LINKTABLE_INIT_DATA:
+		if (!init_completed)
+			return run_init_data_test(test_dev);
+		else
+			return -EACCES;
+	case TEST_LINKTABLE:
+		return run_data_test(test_dev);
+	case TEST_LINKTABLE_TEXT:
+		return run_text_test(test_dev);
+	case TEST_LINKTABLE_RO:
+		return run_rodata_test(test_dev);
+	default:
+		pr_warn("Invalid test case requested: %s\n",
+			config->section_name);
+		return -EINVAL;
+	}
+}
+
+static int trigger_config_run(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	mutex_lock(&test_dev->trigger_mutex);
+	mutex_lock(&test_dev->config_mutex);
+
+	pr_debug("running test on '%s'\n", config->section_name);
+
+	rc = __trigger_config_run(test_dev);
+
+	config->test_result = rc;
+	pr_debug("result: %d\n", rc);
+
+	if (rc < 0) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = 0;
+
+out:
+	mutex_unlock(&test_dev->config_mutex);
+	mutex_unlock(&test_dev->trigger_mutex);
+
+	return rc;
+}
+
+static ssize_t
+trigger_config_store(struct device *dev,
+		     struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	int rc;
+
+	rc = trigger_config_run(test_dev);
+	if (rc)
+		goto out;
+
+	rc = count;
+out:
+	return rc;
+}
+static DEVICE_ATTR_WO(trigger_config);
+
+/*
+ * XXX: move to kstrncpy() once merged.
+ *
+ * Users should use kfree_const() when freeing these.
+ */
+static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
+{
+	*dst = kstrndup(name, count, gfp);
+	if (!*dst)
+		return -ENOSPC;
+	return count;
+}
+
+static int config_copy_section_name(struct test_config *config,
+				    const char *name,
+				    size_t count)
+{
+	return __kstrncpy(&config->section_name, name, count, GFP_KERNEL);
+}
+
+static void __linktable_config_free(struct test_config *config)
+{
+	kfree_const(config->section_name);
+	config->section_name = NULL;
+}
+
+static void linktable_config_free(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+
+	mutex_lock(&test_dev->config_mutex);
+	__linktable_config_free(config);
+	mutex_unlock(&test_dev->config_mutex);
+}
+
+static ssize_t config_section_name_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int rc;
+
+	mutex_lock(&test_dev->config_mutex);
+	rc = config_copy_section_name(config, buf, count);
+	mutex_unlock(&test_dev->config_mutex);
+
+	return rc;
+}
+
+/*
+ * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
+ */
+static ssize_t config_test_show_str(struct mutex *config_mutex,
+				    char *dst,
+				    char *src)
+{
+	int len;
+
+	mutex_lock(config_mutex);
+	len = snprintf(dst, PAGE_SIZE, "%s\n", src);
+	mutex_unlock(config_mutex);
+
+	return len;
+}
+
+static ssize_t config_section_name_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return config_test_show_str(&test_dev->config_mutex, buf,
+				    config->section_name);
+}
+static DEVICE_ATTR(config_section_name, 0644, config_section_name_show,
+		   config_section_name_store);
+
+static int trigger_config_run_named(struct linktable_test_device *test_dev,
+				    const char *section_name)
+{
+	int copied;
+	struct test_config *config = &test_dev->config;
+
+	mutex_lock(&test_dev->config_mutex);
+	copied = config_copy_section_name(config, section_name,
+					  strlen(section_name));
+	mutex_unlock(&test_dev->config_mutex);
+
+	if (copied <=0 || copied != strlen(section_name))
+		return -EINVAL;
+
+	return trigger_config_run(test_dev);
+}
+
+static int __linktable_config_init(struct test_config *config)
+{
+	int ret;
+
+	ret = config_copy_section_name(config, TEST_SECTION_START,
+				       strlen(TEST_SECTION_START));
+	if (ret < 0)
+		goto out;
+
+	config->input = 3;
+	config->test_result = 0;
+
+out:
+	return ret;
+}
+
+static ssize_t reset_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+	int ret;
+
+	mutex_lock(&test_dev->trigger_mutex);
+	mutex_lock(&test_dev->config_mutex);
+
+	__linktable_config_free(config);
+
+	ret = __linktable_config_init(config);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		dev_err(dev, "could not alloc settings for config trigger: %d\n",
+		       ret);
+		goto out;
+	}
+
+	dev_info(dev, "reset\n");
+	ret = count;
+
+out:
+	mutex_unlock(&test_dev->config_mutex);
+	mutex_unlock(&test_dev->trigger_mutex);
+
+	return ret;
+}
+static DEVICE_ATTR_WO(reset);
+
+static int test_dev_config_update_int(struct linktable_test_device *test_dev,
+				      const char *buf, size_t size,
+				      int *config)
+{
+	char *end;
+	long new = simple_strtol(buf, &end, 0);
+	if (end == buf || new > INT_MAX || new < INT_MIN)
+		return -EINVAL;
+	mutex_lock(&test_dev->config_mutex);
+	*config = new;
+	mutex_unlock(&test_dev->config_mutex);
+	/* Always return full write size even if we didn't consume all */
+	return size;
+}
+
+static ssize_t test_dev_config_show_int(struct linktable_test_device *test_dev,
+					char *buf,
+					int config)
+{
+	int val;
+
+	mutex_lock(&test_dev->config_mutex);
+	val = config;
+	mutex_unlock(&test_dev->config_mutex);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t test_result_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_update_int(test_dev, buf, count,
+					  &config->test_result);
+}
+
+static ssize_t config_input_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_update_int(test_dev, buf, count,
+					  &config->input);
+}
+
+static ssize_t config_input_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_show_int(test_dev, buf, config->input);
+}
+static DEVICE_ATTR(config_input, 0644, config_input_show, config_input_store);
+
+static ssize_t test_result_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct linktable_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_show_int(test_dev, buf, config->test_result);
+}
+static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store);
+
+#define LINKTABLE_DEV_ATTR(name)		&dev_attr_##name.attr
+
+static struct attribute *test_dev_attrs[] = {
+	LINKTABLE_DEV_ATTR(trigger_config),
+	LINKTABLE_DEV_ATTR(config),
+	LINKTABLE_DEV_ATTR(reset),
+
+	LINKTABLE_DEV_ATTR(config_section_name),
+	LINKTABLE_DEV_ATTR(config_input),
+	LINKTABLE_DEV_ATTR(test_result),
+
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(test_dev);
+
+static int linktable_config_init(struct linktable_test_device *test_dev)
+{
+	struct test_config *config = &test_dev->config;
+	int ret;
+
+	mutex_lock(&test_dev->config_mutex);
+	ret = __linktable_config_init(config);
+	mutex_unlock(&test_dev->config_mutex);
+
+	return ret;
+}
+
+static struct linktable_test_device *alloc_test_dev_linktable(void)
+{
+	int rc;
+	struct linktable_test_device *test_dev;
+	struct miscdevice *misc_dev;
+
+	test_dev = vmalloc(sizeof(struct linktable_test_device));
+	if (!test_dev) {
+		pr_err("Cannot alloc test_dev\n");
+		goto err_out;
+	}
+
+	memset(test_dev, 0, sizeof(struct linktable_test_device));
+
+	mutex_init(&test_dev->config_mutex);
+	mutex_init(&test_dev->trigger_mutex);
+
+	rc = linktable_config_init(test_dev);
+	if (rc < 0) {
+		pr_err("Cannot alloc linktable_config_init()\n");
+		goto err_out_free;
+	}
+
+	misc_dev = &test_dev->misc_dev;
+
+	misc_dev->minor = MISC_DYNAMIC_MINOR;
+	misc_dev->name = test_dev_name;
+	misc_dev->groups = test_dev_groups;
+
+	return test_dev;
+
+err_out_free:
+	kfree(test_dev);
+err_out:
+	return NULL;
+}
+
+static void free_test_dev_linktable(struct linktable_test_device *test_dev)
+{
+	test_dev->misc_dev.name = NULL;
+	vfree(test_dev);
+	test_dev = NULL;
+	linktable_config_free(test_dev);
+}
+
+static struct linktable_test_device *register_test_dev_linktable(void)
+{
+	struct linktable_test_device *test_dev = NULL;
+	int rc;
+
+	test_dev = alloc_test_dev_linktable();
+	if (!test_dev) {
+		return NULL;
+	}
+
+	rc = misc_register(&test_dev->misc_dev);
+	if (rc) {
+		pr_err("could not register misc device: %d\n", rc);
+		free_test_dev_linktable(test_dev);
+		return NULL;
+	}
+
+	test_dev->dev = test_dev->misc_dev.this_device;
+	dev_dbg(test_dev->dev, "interface ready\n");
+
+	return test_dev;
+}
+
+static int __init test_linktable_init(void)
+{
+	struct linktable_test_device *test_dev;
+	int rc;
+
+	test_dev = register_test_dev_linktable();
+	if (!test_dev) {
+		pr_err("Cannot add test linktable device\n");
+		return -ENODEV;
+	}
+
+	rc = trigger_config_run_named(test_dev, ".init.text");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".init.data");
+	if (WARN_ON(rc))
+		return rc;
+
+	init_completed = true;
+
+	rc = trigger_config_run_named(test_dev, ".data");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".text");
+	if (WARN_ON(rc))
+		return rc;
+	rc = trigger_config_run_named(test_dev, ".rodata");
+	if (WARN_ON(rc))
+		return rc;
+
+	pr_info("linker table tests: OK!\n");
+
+	return 0;
+}
+late_initcall(test_linktable_init);
+
+static
+void unregister_test_dev_linktable(struct linktable_test_device *test_dev)
+{
+	dev_info(test_dev->dev, "removing interface\n");
+	misc_deregister(&test_dev->misc_dev);
+	free_test_dev_linktable(test_dev);
+}
+
+static void __exit test_linktable_exit(void)
+{
+	struct linktable_test_device *test_dev = __test_dev;
+
+	unregister_test_dev_linktable(test_dev);
+}
+module_exit(test_linktable_exit);
+
+MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/lib/test_linktables/test-linktables.h b/lib/test_linktables/test-linktables.h
new file mode 100644
index 000000000000..c9c9d5c87263
--- /dev/null
+++ b/lib/test_linktables/test-linktables.h
@@ -0,0 +1,48 @@
+#include <linux/tables.h>
+
+struct test_linktable {
+	int expected;
+	int write_test;
+	int (*op)(int input_digit);
+};
+
+#define test_linktable_init_text(__level, __op)				\
+	static LINKTABLE_INIT(test_fns_init_text, __level)		\
+	__test_fn_init_text_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_init_data(__level, __op)				\
+	static LINKTABLE_INIT_DATA(test_fns_init_data, __level)		\
+	__test_fn_init_data_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable(__level, __op)					\
+	static LINKTABLE(test_fns_data, __level)			\
+	__test_fn_data_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_text(__level, __op)				\
+	static LINKTABLE_TEXT(test_fns_text, __level)			\
+	__test_fn_text_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+#define test_linktable_rodata(__level, __op)				\
+	static LINKTABLE_RO(test_fns_rodata, __level)			\
+	__test_fn_rodata_##__op = {					\
+		.expected = __level,					\
+		.op = __op,						\
+};
+
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_init_text);
+DECLARE_LINKTABLE(struct test_linktable, test_fns_init_data);
+DECLARE_LINKTABLE(struct test_linktable, test_fns_data);
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_text);
+DECLARE_LINKTABLE_RO(struct test_linktable, test_fns_rodata);
-- 
2.10.1


  parent reply	other threads:[~2016-12-22  2:38 UTC|newest]

Thread overview: 288+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-19 21:33 [PATCH v4 00/16] linux: generalize sections, ranges and linker tables mcgrof
2016-08-19 21:33 ` mcgrof
2016-08-19 21:33 ` [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL() mcgrof
2016-08-19 21:33   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 02/16] dell-smo8800: include uaccess.h mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 03/16] scripts/module-common.lds: enable generation mcgrof
2016-08-19 21:34 ` [PATCH v4 04/16] generic-sections: add section core helpers mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-23  1:26   ` Nicholas Piggin
2016-08-23  1:26     ` Nicholas Piggin
2016-08-23 17:33     ` Luis R. Rodriguez
2016-08-23 17:33       ` Luis R. Rodriguez
2016-08-24  3:51       ` Nicholas Piggin
2016-08-24  3:51         ` Nicholas Piggin
2016-08-24 20:12         ` Luis R. Rodriguez
2016-08-24 20:12           ` Luis R. Rodriguez
2016-08-25  2:06           ` Nicholas Piggin
2016-08-25  2:06             ` Nicholas Piggin
2016-08-25  6:05             ` Luis R. Rodriguez
2016-08-25  6:05               ` Luis R. Rodriguez
2016-08-25  6:51               ` Nicholas Piggin
2016-08-25  6:51                 ` Nicholas Piggin
2016-08-25 17:52                 ` Luis R. Rodriguez
2016-08-25 17:52                   ` Luis R. Rodriguez
2016-08-26  3:00                   ` Nicholas Piggin
2016-08-26  6:38                     ` Luis R. Rodriguez
2016-08-26  7:33                       ` Nicholas Piggin
2016-08-26  7:33                         ` Nicholas Piggin
2016-08-26 13:22                         ` Luis R. Rodriguez
2016-08-26 13:22                           ` Luis R. Rodriguez
2016-08-26 13:28                           ` Nicholas Piggin
2016-08-26 13:28                             ` Nicholas Piggin
2016-08-19 21:34 ` [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 07/16] tables.h: add linker table support mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 10/16] firmware: port built-in section to linker table mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 11/16] jump_label: move guard #endif down where it belongs mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 12/16] jump_label: port __jump_table to linker tables mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 13/16] dynamic_debug: port to use " mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-22 15:11   ` Masami Hiramatsu
2016-08-22 15:11     ` Masami Hiramatsu
2016-08-23 16:31     ` Luis R. Rodriguez
2016-08-23 16:31       ` Luis R. Rodriguez
2016-08-29 14:04       ` Masami Hiramatsu
2016-08-29 14:04         ` Masami Hiramatsu
2016-08-30 20:07         ` Luis R. Rodriguez
2016-08-30 20:07           ` Luis R. Rodriguez
2017-02-01 20:02         ` Luis R. Rodriguez
2017-02-01 20:02           ` Luis R. Rodriguez
2016-08-19 21:34 ` [PATCH v4 15/16] kprobes: port .kprobes.text to section range mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:34 ` [PATCH v4 16/16] kprobes: port blacklist kprobes to linker table mcgrof
2016-08-19 21:34   ` mcgrof
2016-08-19 21:41 ` [PATCH v1 0/7] tools: add linker table userspace sandbox mcgrof
2016-08-19 21:41   ` mcgrof
2016-08-19 21:41   ` [PATCH v1 1/7] tools: add a userspace tools bug.h mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 2/7] tools: add a basic tools printk.h mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 3/7] tools: add init.h for tools mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 4/7] tools: add __used and enable to override mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 5/7] tools: expand export.h with VMLINUX_SYMBOL() mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 6/7] tools: add __section() to compiler.h mcgrof
2016-08-19 21:41     ` mcgrof
2016-08-19 21:41   ` [PATCH v1 7/7] tools: add userspace linker table sandbox mcgrof
2016-08-19 22:31     ` Kees Cook
2016-08-23  0:07       ` Luis R. Rodriguez
2016-08-23  0:28         ` H. Peter Anvin
2016-08-23  0:28           ` H. Peter Anvin
2016-08-23 14:30           ` Arnaldo Carvalho de Melo
2016-08-23 14:30             ` Arnaldo Carvalho de Melo
2016-08-24  2:28             ` Kees Cook
2016-08-24  2:28               ` Kees Cook
2016-08-24 12:39               ` Arnaldo Carvalho de Melo
2016-08-24 12:39                 ` Arnaldo Carvalho de Melo
2016-08-24 16:20                 ` Luis R. Rodriguez
2016-08-24 16:20                   ` Luis R. Rodriguez
2016-08-24 19:17                   ` Arnaldo Carvalho de Melo
2016-08-24 19:17                     ` Arnaldo Carvalho de Melo
2016-08-20  4:57   ` [PATCH v1 0/7] tools: add linker table userspace sandbox Rob Landley
2016-08-20  4:57     ` Rob Landley
2016-08-21  4:59     ` Rich Felker
2016-08-21  4:59       ` Rich Felker
2016-08-22  4:04       ` H. Peter Anvin
2016-08-22  4:04       ` H. Peter Anvin
2016-08-22  9:59   ` Vegard Nossum
2016-08-22  9:59     ` Vegard Nossum
2016-08-23 15:49     ` Luis R. Rodriguez
2016-08-23 15:49       ` Luis R. Rodriguez
2016-12-22  2:39   ` [PATCH v2 0/6] " Luis R. Rodriguez
2016-12-22  2:39     ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez
2016-12-22  2:39       ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 2/6] tools: add init.h for tools Luis R. Rodriguez
2016-12-22  2:39       ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 3/6] tools: add __used and enable to override Luis R. Rodriguez
2016-12-22  2:39       ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez
2016-12-22  2:39       ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 5/6] tools: add __section() to compiler.h Luis R. Rodriguez
2016-12-22  2:39       ` Luis R. Rodriguez
2016-12-22  2:39     ` [PATCH v2 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez
2017-01-09 15:02     ` [PATCH v3 0/6] tools: add linker table userspace sandbox Luis R. Rodriguez
2017-01-09 15:02       ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez
2017-01-09 15:02         ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 2/6] tools: add init.h for tools Luis R. Rodriguez
2017-01-09 15:02         ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 3/6] tools: add __used and enable to override Luis R. Rodriguez
2017-01-09 15:02         ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez
2017-01-09 15:02         ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 5/6] tools: add __section() to compiler.h Luis R. Rodriguez
2017-01-09 15:02         ` Luis R. Rodriguez
2017-01-09 15:02       ` [PATCH v3 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez
2017-01-15 21:12       ` [PATCH v4 0/6] tools: add linker table userspace sandbox Luis R. Rodriguez
2017-01-15 21:12         ` Luis R. Rodriguez
2017-01-15 21:12         ` [PATCH v4 1/6] tools: add a userspace tools bug.h Luis R. Rodriguez
2017-01-15 21:12           ` Luis R. Rodriguez
2017-01-19 11:01           ` Greg KH
2017-01-19 11:01             ` Greg KH
2017-01-15 21:12         ` [PATCH v4 2/6] tools: add init.h for tools Luis R. Rodriguez
2017-01-15 21:12           ` Luis R. Rodriguez
2017-01-19 11:02           ` Greg KH
2017-01-19 11:02             ` Greg KH
2017-01-15 21:12         ` [PATCH v4 3/6] tools: add __used and enable to override Luis R. Rodriguez
2017-01-15 21:12           ` Luis R. Rodriguez
2017-01-19 11:02           ` Greg KH
2017-01-19 11:02             ` Greg KH
2017-01-15 21:12         ` [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL() Luis R. Rodriguez
2017-01-15 21:12           ` Luis R. Rodriguez
2017-01-19 11:03           ` Greg KH
2017-01-19 11:03             ` Greg KH
2017-01-19 11:04           ` Greg KH
2017-01-19 11:04             ` Greg KH
2017-01-15 21:12         ` [PATCH v4 5/6] tools: add __section() to compiler.h Luis R. Rodriguez
2017-01-15 21:12           ` Luis R. Rodriguez
2017-01-19 11:04           ` Greg KH
2017-01-19 11:04             ` Greg KH
2017-01-15 21:12         ` [PATCH v4 6/6] tools: add userspace linker table sandbox Luis R. Rodriguez
2017-01-19 11:07           ` Greg KH
2016-12-22  2:37 ` [PATCH v5 00/14] linux: generalize sections, ranges and linker tables Luis R. Rodriguez
2016-12-22  2:37   ` Luis R. Rodriguez
2016-12-22  2:37   ` [PATCH v5 01/14] generic-sections: add section core helpers Luis R. Rodriguez
2016-12-22  2:37     ` Luis R. Rodriguez
2016-12-22  2:37   ` [PATCH v5 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez
2016-12-22  2:37     ` Luis R. Rodriguez
2016-12-22  2:37   ` [PATCH v5 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez
2016-12-22  2:37     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 04/14] tables.h: add linker table support Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22 13:58     ` Andy Shevchenko
2016-12-22 13:58       ` Andy Shevchenko
2017-01-03 21:25       ` Luis R. Rodriguez
2017-01-03 21:25         ` Luis R. Rodriguez
2017-01-04  9:47         ` Andy Shevchenko
2017-01-06 20:00           ` Luis R. Rodriguez
2017-01-06 20:43             ` Andy Shevchenko
2017-01-09 14:22               ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 07/14] firmware: port built-in section to linker table Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22 14:08     ` Andy Shevchenko
2016-12-22 14:08       ` Andy Shevchenko
2017-01-03 21:27       ` Luis R. Rodriguez
2017-01-03 21:27         ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 10/14] dynamic_debug: port to use " Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` [PATCH v5 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez
2016-12-22  2:38     ` Luis R. Rodriguez
2016-12-22  2:38   ` Luis R. Rodriguez [this message]
2016-12-22  2:38     ` [PATCH v5 14/14] lib: add linker tables test driver Luis R. Rodriguez
2017-01-09 14:58   ` [PATCH v6 00/14] linux: generalize sections, ranges and linker tables Luis R. Rodriguez
2017-01-09 14:58     ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 01/14] generic-sections: add section core helpers Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-16 14:46       ` Borislav Petkov
2017-01-16 14:46         ` Borislav Petkov
2017-01-09 14:58     ` [PATCH v6 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 04/14] tables.h: add linker table support Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 07/14] firmware: port built-in section to linker table Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 10/14] dynamic_debug: port to use " Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 14:58     ` [PATCH v6 14/14] lib: add linker tables test driver Luis R. Rodriguez
2017-01-09 14:58       ` Luis R. Rodriguez
2017-01-09 16:27     ` [PATCH v6 00/14] linux: generalize sections, ranges and linker tables Andy Shevchenko
2017-01-09 16:27       ` Andy Shevchenko
2017-01-09 16:36       ` Luis R. Rodriguez
2017-01-09 17:12       ` Shevchenko, Andriy
2017-01-09 17:16         ` Luis R. Rodriguez
2017-01-09 18:29         ` Andy Shevchenko
2017-01-09 18:29           ` Andy Shevchenko
2017-01-11 14:37           ` Luis R. Rodriguez
2017-01-11 14:37             ` Luis R. Rodriguez
2017-01-15 21:10     ` [PATCH v7 " Luis R. Rodriguez
2017-01-15 21:10       ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 01/14] generic-sections: add section core helpers Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:09         ` Greg KH
2017-01-19 11:09           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-18 11:29         ` Borislav Petkov
2017-01-18 11:29           ` Borislav Petkov
2017-01-15 21:10       ` [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:11         ` Greg KH
2017-01-19 11:11           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 04/14] tables.h: add linker table support Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:13         ` Greg KH
2017-01-19 11:13           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:18         ` Greg KH
2017-01-19 11:18           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:19         ` Greg KH
2017-01-19 11:19           ` Greg KH
2017-01-23 16:12           ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 07/14] firmware: port built-in section to linker table Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 08/14] jump_label: move guard #endif down where it belongs Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:20         ` Greg KH
2017-01-19 11:20           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 09/14] jump_label: port __jump_table to linker tables Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-19 11:24         ` Greg KH
2017-01-19 11:24           ` Greg KH
2017-01-15 21:10       ` [PATCH v7 10/14] dynamic_debug: port to use " Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 12/14] kprobes: port .kprobes.text to section range Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 13/14] kprobes: port blacklist kprobes to linker table Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez
2017-01-15 21:10       ` [PATCH v7 14/14] lib: add linker tables test driver Luis R. Rodriguez
2017-01-15 21:10         ` Luis R. Rodriguez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161222023811.21246-15-mcgrof@kernel.org \
    --to=mcgrof@kernel.org \
    --cc=acme@redhat.com \
    --cc=ak@linux.intel.com \
    --cc=alan@linux.intel.com \
    --cc=ananth@linux.vnet.ibm.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=anil.s.keshavamurthy@intel.com \
    --cc=arnd@arndb.de \
    --cc=benh@kernel.crashing.org \
    --cc=bp@alien8.de \
    --cc=dalias@libc.org \
    --cc=davem@davemloft.net \
    --cc=david.vrabel@citrix.com \
    --cc=dvhart@infradead.org \
    --cc=dwmw2@infradead.org \
    --cc=fontana@sharpeleven.org \
    --cc=gnomes@lxorguk.ukuu.org.uk \
    --cc=gregkh@linuxfoundation.org \
    --cc=heiko.carstens@de.ibm.com \
    --cc=hpa@zytor.com \
    --cc=jbaron@akamai.com \
    --cc=jgross@suse.com \
    --cc=jkosina@suse.cz \
    --cc=jpoimboe@redhat.com \
    --cc=keescook@chromium.org \
    --cc=konrad.wilk@oracle.com \
    --cc=korea.drzix@gmail.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kbuild@vger.kernel \
    --cc=linux@arm.linux.org.uk \
    --cc=linux@rasmusvillemoes.dk \
    --cc=linux@roeck-us.net \
    --cc=luto@amacapital.net \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mcb30@ipxe.org \
    --cc=mhiramat@kernel.org \
    --cc=ming.lei@canonical.com \
    --cc=mingo@redhat.com \
    --cc=mmarek@suse.com \
    --cc=npiggin@gmail.com \
    --cc=pali.rohar@gmail.com \
    --cc=paul.gortmaker@windriver.com \
    --cc=pebolle@tiscali.nl \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=realmz6@gmail.com \
    --cc=rusty@rustcorp.com.au \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).