@@ -10,3 +10,4 @@ used throughout the kernel to help declare and define them.
section-core
ranges
+ linker-tables
new file mode 100644
@@ -0,0 +1,187 @@
+===================
+Linux linker tables
+===================
+
+This documents Linux linker tables, it explains what they are, where they
+came from, how they work, the benefits of using them and more importantly
+how you can use them.
+
+About Linker tables
+===================
+.. kernel-doc:: include/linux/tables.h
+ :doc: Introduction
+
+Linker table provenance
+---------------------------------------------
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Linker table provenance
+
+Benefits of using Linker tables
+===============================
+
+Avoids modifying architecture linker scripts
+----------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+ :doc: Avoids modifying architecture linker scripts
+
+How linker tables simplify initialization code
+----------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+ :doc: How linker tables simplify initialization code
+
+Using linker tables in Linux
+============================
+
+Linker table module support
+---------------------------
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Linker table module support
+
+Linker table helpers
+====================
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Linker table helpers
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_ADDR_WITHIN
+
+Constructing linker tables
+==========================
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Constructing linker tables
+
+Weak linker tables constructors
+-------------------------------
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Weak linker tables constructors
+
+LINKTABLE_WEAK
+--------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_WEAK
+
+LINKTABLE_TEXT_WEAK
+-------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_TEXT_WEAK
+
+LINKTABLE_RO_WEAK
+-----------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_RO_WEAK
+
+LINKTABLE_INIT_WEAK
+-------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_INIT_WEAK
+
+LINKTABLE_INIT_DATA_WEAK
+------------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_INIT_DATA_WEAK
+
+Regular linker linker table constructors
+----------------------------------------
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Regular linker linker table constructors
+
+LINKTABLE
+---------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE
+
+LINKTABLE_TEXT
+--------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_TEXT
+
+LINKTABLE_RO
+------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_RO
+
+LINKTABLE_INIT
+--------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_INIT
+
+LINKTABLE_INIT_DATA
+-------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_INIT_DATA
+
+Declaring Linker tables
+=======================
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Declaring Linker tables
+
+DECLARE_LINKTABLE
+----------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DECLARE_LINKTABLE
+
+DECLARE_LINKTABLE_RO
+--------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DECLARE_LINKTABLE_RO
+
+Defining Linker tables
+======================
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Defining Linker tables
+
+DEFINE_LINKTABLE
+----------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DEFINE_LINKTABLE
+
+DEFINE_LINKTABLE_TEXT
+---------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DEFINE_LINKTABLE_TEXT
+
+DEFINE_LINKTABLE_RO
+-------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DEFINE_LINKTABLE_RO
+
+DEFINE_LINKTABLE_INIT
+---------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DEFINE_LINKTABLE_INIT
+
+DEFINE_LINKTABLE_INIT_DATA
+--------------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: DEFINE_LINKTABLE_INIT_DATA
+
+Iterating over Linker tables
+============================
+
+.. kernel-doc:: include/linux/tables.h
+ :doc: Iterating over Linker tables
+
+LINKTABLE_FOR_EACH
+------------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_FOR_EACH
+
+LINKTABLE_RUN_ALL
+-----------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_RUN_ALL
+
+LINKTABLE_RUN_ERR
+-----------------
+.. kernel-doc:: include/linux/tables.h
+ :functions: LINKTABLE_RUN_ERR
@@ -5200,6 +5200,18 @@ S: Maintained
F: include/asm-generic/
F: include/uapi/asm-generic/
+GENERIC LINKER TABLES
+M: "Luis R. Rodriguez" <mcgrof@kernel.org>
+M: "H. Peter Anvin" <hpa@zytor.com>
+L: linux-arch@vger.kernel.org
+L: linux-kernel@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git sections
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git sections
+S: Supported
+F: include/asm-generic/tables.h
+F: include/linux/tables.h
+F: Documentation/sections/linker-tables.rst
+
GENERIC PHY FRAMEWORK
M: Kishon Vijay Abraham I <kishon@ti.com>
L: linux-kernel@vger.kernel.org
@@ -12,3 +12,4 @@ generic-y += sections.h
generic-y += trace_clock.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -52,3 +52,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
generic-y += unaligned.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -54,3 +54,4 @@ generic-y += vga.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -24,3 +24,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -50,3 +50,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
new file mode 100644
@@ -0,0 +1,26 @@
+#ifndef _ASM_C6X_ASM_TABLES_H
+#define _ASM_C6X_ASM_TABLES_H
+/*
+ * 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/.
+ */
+
+/*
+ * The c6x toolchain has a bug present even on gcc-6 when non-weak attributes
+ * are used and sends them to .rodata even though const data with weak
+ * attributes are put in .const, this forces the linker to believe the address
+ * is relative relative to the a base + offset and you end up with SB-relative
+ * reloc error upon linking. Work around this by by forcing both start and
+ * ending const RO waek linker table entry to be .const to fix this for now.
+ *
+ * [0] https://lkml.kernel.org/r/1470798247.3551.94.camel@redhat.com
+ */
+
+#define SECTION_TBL_RO .const
+
+#include <asm-generic/tables.h>
+
+#endif /* _ASM_C6X_ASM_TABLES_H */
@@ -47,3 +47,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -77,3 +77,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -62,3 +62,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -11,3 +11,4 @@ generic-y += vtime.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -37,3 +37,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -58,3 +58,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -22,3 +22,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -12,3 +12,4 @@ generic-y += trace_clock.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -65,3 +65,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -73,3 +73,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -31,3 +31,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -9,3 +9,4 @@ generic-y += rwsem.h
generic-y += vtime.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -16,3 +16,4 @@ generic-y += serial.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -41,3 +41,4 @@ generic-y += ucontext.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -24,3 +24,4 @@ generic-y += types.h
generic-y += word-at-a-time.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -43,3 +43,4 @@ generic-y += types.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -29,3 +29,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -65,3 +65,4 @@ generic-y += vga.h
generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += ranges.h
+generic-y += tables.h
@@ -18,3 +18,4 @@ generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -69,7 +69,9 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
"__initramfs_start|"
"(jiffies|jiffies_64)|"
".rodata.rng.*|"
+ ".rodata.tbl.*|"
".init.text.rng.*|"
+ ".init.text.tbl.*|"
#if ELF_BITS == 64
"__per_cpu_load|"
"init_per_cpu__.*|"
@@ -33,3 +33,4 @@ generic-y += word-at-a-time.h
generic-y += xor.h
generic-y += section-core.h
generic-y += ranges.h
+generic-y += tables.h
@@ -86,4 +86,18 @@
#endif /* __ASSEMBLY__ */
+#ifdef __ASSEMBLER__
+
+#ifndef DEFINE_SECTION_RANGE
+#define DEFINE_SECTION_RANGE(section, name) \
+ push_section_rng_level(section, name,,) ; \
+ .globl name ; \
+name: ; \
+ .popsection \
+ \
+ push_section_rng_level(section, name, ~,) ; \
+ .popsection
+#endif
+#endif /* __ASSEMBLER__ */
+
#endif /* _ASM_GENERIC_RANGES_H_ */
new file mode 100644
@@ -0,0 +1,50 @@
+#ifndef _ASM_GENERIC_TABLES_H_
+#define _ASM_GENERIC_TABLES_H_
+/*
+ * Linux linker tables
+ *
+ * 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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_TBL(section, name, level) \
+ SECTION_CORE(section, tbl, name, level)
+
+#define SECTION_TBL_ALL(section) \
+ SECTION_CORE_ALL(section,tbl)
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO SECTION_RODATA
+#endif
+
+#ifndef set_section_tbl
+# define set_section_tbl(section, name, level, flags) \
+ set_section_core(section, tbl, name, level, flags)
+#endif
+
+#ifndef set_section_tbl_any
+# define set_section_tbl_any(section, name, flags) \
+ set_section_core(section, tbl, name, SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_tbl_type
+# define set_section_tbl_type(section, name, level, flags, type) \
+ set_section_core_type(section, tbl, name, level, flags, type)
+#endif
+
+#ifndef push_section_tbl
+# define push_section_tbl(section, name, level, flags) \
+ push_section_core(section, tbl, name, level, flags)
+#endif
+
+#ifndef push_section_tbl_any
+# define push_section_tbl_any(section, name, flags) \
+ push_section_core(section, tbl, name, SECTION_ORDER_ANY, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
@@ -57,6 +57,7 @@
#include <linux/export.h>
#include <asm/section-core.h>
#include <asm/ranges.h>
+#include <asm/tables.h>
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)
@@ -202,6 +203,7 @@
#define DATA_DATA \
*(SECTION_DATA) \
*(SORT(SECTION_RNG_ALL(SECTION_DATA))) \
+ *(SORT(SECTION_TBL_ALL(SECTION_DATA))) \
*(SECTION_REF_DATA) \
*(.data..shared_aligned) /* percpu related */ \
MEM_KEEP(init.data) \
@@ -269,6 +271,7 @@
VMLINUX_SYMBOL(__start_rodata) = .; \
*(SECTION_RODATA) \
*(SORT(SECTION_RNG_ALL(SECTION_RODATA))) \
+ *(SORT(SECTION_TBL_ALL(SECTION_RODATA))) \
*(SECTION_ALL(SECTION_RODATA)) \
RO_AFTER_INIT_DATA /* Read only after init */ \
*(__vermagic) /* Kernel version magic */ \
@@ -439,6 +442,7 @@
ALIGN_FUNCTION(); \
*(.text.hot SECTION_TEXT) \
*(SORT(SECTION_RNG_ALL(SECTION_TEXT))) \
+ *(SORT(SECTION_TBL_ALL(SECTION_TEXT))) \
*(.text.fixup .text.unlikely) \
*(SECTION_REF) \
MEM_KEEP(init.text) \
@@ -536,6 +540,7 @@
#define INIT_DATA \
*(SECTION_INIT_DATA) \
*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA))) \
+ *(SORT(SECTION_TBL_ALL(SECTION_INIT_DATA))) \
MEM_DISCARD(init.data) \
KERNEL_CTORS() \
MCOUNT_REC() \
@@ -559,6 +564,7 @@
#define INIT_TEXT \
*(SECTION_INIT) \
*(SORT(SECTION_RNG_ALL(SECTION_INIT))) \
+ *(SORT(SECTION_TBL_ALL(SECTION_INIT))) \
*(.text.startup) \
MEM_DISCARD(init.text)
new file mode 100644
@@ -0,0 +1,567 @@
+#ifndef _LINUX_LINKER_TABLES_H
+#define _LINUX_LINKER_TABLES_H
+/*
+ * Linux linker tables
+ *
+ * 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/.
+ */
+#include <linux/export.h>
+#include <linux/sections.h>
+#include <asm/tables.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A linker table is a data structure that is stitched together from items in
+ * multiple object files for the purpose of selective placement into standard
+ * or architecture specific ELF sections. What section is used is utility
+ * specific. Linux has historically implicitly used linker tables, however they
+ * were all built in an adhoc manner which requires linker script modifications
+ * per architecture. The linker table API provides a general facility so that
+ * data structures can be stitched together and placed into Linux ELF sections
+ * by only changing C or asm code in an architecture agnostic form.
+ *
+ * Linker tables help you group together related data and code in an efficient
+ * way. Linker tables can be used to help simplify init sequences, they
+ * enable linker build time selective sorting (disabled options get ignored),
+ * and can optionally also be used to help you avoid code bit-rot due to
+ * overuse of #ifdef.
+ */
+
+/**
+ * DOC: Linker table provenance
+ *
+ * The Linux implementation of linker tables was inspired by the iPXE linker
+ * table's solution (iPXE commit 67a10ef000cb7 "[contrib] Add rom-o-matic to
+ * contrib "[0]). To see how this code evolved refer to the out of tree
+ * userspace linker-table tree [1].
+ *
+ * Contrary to iPXE's solution which strives to force compilation of
+ * everything using linker tables, Linux's solution allows for developers to be
+ * selective over where one wishes to force compilation, this then is just an
+ * optional feature for the Linux linker table solution. The main advantages
+ * of using linker-tables then are:
+ *
+ * - Avoiding modifying architecture linker scripts
+ * - Simplifying initialization code
+ * - Avoiding the code bit-rot problem
+ *
+ * [0] git://git.ipxe.org/ipxe.git
+ *
+ * [1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+ */
+
+/**
+ * DOC: Avoids modifying architecture linker scripts
+ *
+ * Linker tables enable you to avoid modifying architecture linker scripts
+ * since it has its has extended each core Linux section with a respective
+ * linker table entry in `include/asm-generic/vmlinux.lds.h`. When you add new
+ * linker table entry you aggregate them `into` the existing linker table core
+ * section.
+ */
+
+/**
+ * DOC: How linker tables simplify initialization code
+ *
+ * Traditionally, we would implement features in C code as follows:
+ *
+ * foo_init();
+ *
+ * You'd then have a foo.h which would have::
+ *
+ * #ifndef CONFIG_FOO
+ * static inline void foo_init(void) { }
+ * #endif
+ *
+ * With linker tables this is no longer necessary as your init routines would
+ * be implicit, you'd instead call:
+ *
+ * call_init_fns();
+ *
+ * call_init_fns() would call all functions present in your init table and if
+ * and only if foo.o gets linked in, then its initialisation function will be
+ * called.
+ *
+ * The linker script takes care of assembling the tables for us. All of our
+ * table sections have names of the format `SECTION_NAME.tbl.NAME.N`. Here
+ * `SECTION_NAME` is one of the standard sections in::
+ *
+ * include/asm-generic/section-core.h
+ *
+ * and `NAME` designates the specific use case for the linker table, the table.
+ * `N` is a digit used to help sort entries in the section. `N=` (empty string)
+ * is reserved for the symbol indicating `table start`, and `N=~` is reserved
+ * for the symbol indicating `table end`. In order for the call_init_fns() to
+ * work behind the scenes the custom linker script would need to define the
+ * beginning of the table, the end of the table, and in between it should use
+ * ``SORT()`` to give order to the section. Typically this would require custom
+ * linker script modifications however since linker table are already defined
+ * in ``include/asm-generic/vmlinux.lds.h`` as documented above each new linker
+ * table definition added in C code folds into the respective core Linux
+ * section linker table.
+ *
+ * This is also done to support all architectures. All that is needed then is
+ * to ensure a respective common linker table entry is added to the shared
+ * ``include/asm-generic/vmlinux.lds.h``. There should be a respective::
+ *
+ * *(SORT(SECTION_TBL_ALL(SECTION_NAME)))
+ *
+ * entry for each type of supported section there. If your `SECTION_NAME`
+ * is not yet supported, consider adding support for it.
+ *
+ * Linker tables support ordering entries, it does this using a digit which
+ * is eventually added as a postfix to a section entry name, we refer to this
+ * as the linker table ``order-level``. If order is not important to your
+ * linker table entry you can use the special ``SECTION_ORDER_ANY``. After
+ * ``order-level``, the next contributing factor to order is the order of the
+ * code in the C file, and the order of the objects in the Makefile. Using an
+ * ``order-level`` then should not really be needed in most cases, its use
+ * however enables to compartamentalize code into tables where ordering through
+ * C file or through the Makefile would otherwise be very difficult or if one
+ * wanted to enable very specific initialization semantics.
+ *
+ * As an example, suppose that we want to create a "frobnicator"
+ * feature framework, and allow for several independent modules to
+ * provide frobnicating services. Then we would create a frob.h
+ * header file containing e.g.::
+ *
+ * struct frobnicator {
+ * const char *name;
+ * void (*frob) (void);
+ * };
+ *
+ * DECLARE_LINKTABLE(struct frobnicator, frobnicator_fns);
+ *
+ * Any module providing frobnicating services would look something
+ * like::
+ *
+ * #include "frob.h"
+ *
+ * static void my_frob(void) {
+ * ... Do my frobnicating
+ * }
+ *
+ * LINKTABLE_INIT_DATA(frobnicator_fns, all) my_frobnicator = {
+ * .name = "my_frob",
+ * .frob = my_frob,
+ * };
+ *
+ * The central frobnicator code, say in frob.c, would use the frobnicating
+ * modules as follows::
+ *
+ * #include "frob.h"
+ *
+ * void frob_all(void) {
+ * struct frobnicator *f;
+ *
+ * LINKTABLE_FOR_EACH(f, frobnicator_fns) {
+ * pr_info("Calling frobnicator %s\n", frob->name);
+ * f->frob();
+ * }
+ * }
+ */
+
+/**
+ * DOC: Linker table module support
+ *
+ * Modules can use linker tables, however the linker table definition
+ * must be built-in to the kernel. That is, the code that implements
+ * ``DEFINE_LINKTABLE*()`` must be built-in, and modular code cannot add
+ * more items in to the table, unless ``kernel/module.c`` find_module_sections()
+ * and module-common.lds.S are updated accordingly with a respective
+ * module notifier to account for updates. This restriction may be enhanced
+ * in the future.
+ */
+
+/**
+ * DOC: Linker table helpers
+ *
+ * These are helpers for linker tables.
+ */
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in range
+ *
+ * @tbl: linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(tbl, addr) \
+ (addr >= (unsigned long) LINUX_SECTION_START(tbl) && \
+ addr < (unsigned long) LINUX_SECTION_END(tbl))
+
+/**
+ * DOC: Constructing linker tables
+ *
+ * Linker tables constructors are used to build an entry into a linker table.
+ * Linker table constructors exist for each type of supported section.
+ *
+ * You have weak and regular type of link table entry constructors.
+ */
+
+/**
+ * DOC: Weak linker tables constructors
+ *
+ * The weak attribute is desirable if you want an entry you can replace at
+ * link time. A very special use case for linker tables is the first entry.
+ * A weak attribute is used for the first entry to ensure that this entry's
+ * address matches the end address of the table when the linker table is
+ * emtpy, but will also point to the first real entry of the table once not
+ * empty. When the first entry is linked in, it takes place of the first entry.
+ */
+
+/**
+ * LINKTABLE_WEAK - Constructs a weak linker table entry for data
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Constructs a weak linker table for data.
+ */
+#define LINKTABLE_WEAK(name, level) \
+ __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ weak, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_DATA, \
+ name, level))))
+
+/**
+ * LINKTABLE_TEXT_WEAK - Constructs a weak linker table entry for execution
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Constructs a weak linker table for code execution. These will be
+ * read-only.
+ */
+#define LINKTABLE_TEXT_WEAK(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ weak, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_TEXT, \
+ name, level))))
+
+/**
+ * LINKTABLE_RO_WEAK - Constructs a weak read-only linker table entry
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Constructs a weak linker table which only requires read-only access.
+ */
+#define LINKTABLE_RO_WEAK(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ weak, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_TBL_RO, \
+ name, level))))
+
+/**
+ * LINKTABLE_INIT_WEAK - Constructs a weak linker table entry for init code
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Constructs a weak linker table for execution. use at init.
+ */
+#define LINKTABLE_INIT_WEAK(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ weak, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_INIT, \
+ name, level))))
+
+/**
+ * LINKTABLE_INIT_DATA_WEAK - Constructs a weak linker table entry for initdata
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Constructs a weak linker table for data during init.
+ */
+#define LINKTABLE_INIT_DATA_WEAK(name, level) \
+ __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ weak, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_INIT_DATA, \
+ name, level))))
+
+/**
+ * DOC: Regular linker linker table constructors
+ *
+ * Regular constructors are expected to be used for valid linker table entries.
+ * Valid uses of weak entries other than the beginning and is currently
+ * untested but should in theory work.
+ */
+
+/**
+ * LINKTABLE - Declares a data linker table entry
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Declares a data linker table entry. These are read-write.
+ */
+#define LINKTABLE(name, level) \
+ __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_DATA, \
+ name, level))))
+
+/**
+ * LINKTABLE_TEXT - Declares a linker table entry for execution
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Declares a linker table to be used for execution.
+ */
+#define LINKTABLE_TEXT(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_TEXT, \
+ name, level))))
+
+/**
+ * LINKTABLE_RO - Declares a read-only linker table entry.
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Declares a linker table which only requires read-only access. Contrary
+ * to LINKTABLE_RO_WEAK() which uses SECTION_RODATA this helper uses the
+ * section SECTION_TBL_RO here due to possible toolchains bug on some
+ * architectures, for instance the c6x architicture stuffs non-weak data
+ * into different sections other than the one intended.
+ */
+#define LINKTABLE_RO(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_TBL_RO, \
+ name, level))))
+
+/**
+ * LINKTABLE_INIT - Declares a linker table entry to be used on init.
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Declares a linker table entry for execution use during init.
+ */
+#define LINKTABLE_INIT(name, level) \
+ const __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ __aligned__(LINUX_SECTION_ALIGN_FUNC), \
+ section(SECTION_TBL(SECTION_INIT, \
+ name, level))))
+
+/**
+ * LINKTABLE_INIT_DATA - Declares a linker table entry to be used on init data.
+ *
+ * @name: linker table name
+ * @level: order level
+ *
+ * Declares a linker table entry for data during init.
+ */
+#define LINKTABLE_INIT_DATA(name, level) \
+ __typeof__(VMLINUX_SYMBOL(name)[0]) \
+ __attribute__((used, \
+ __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+ section(SECTION_TBL(SECTION_INIT_DATA, \
+ name, level))))
+
+/**
+ * DOC: Declaring Linker tables
+ *
+ * Declarers are used to help code access the linker tables. Typically
+ * header files for subsystems would declare the linker tables to enable
+ * easy access to add new entries, and to iterate over the list of table.
+ * There are only two declarers needed given that the section association
+ * is done by the definition of the linker table using ``DEFINE_LINKTABLE*()``
+ * helpers.
+ */
+
+
+/**
+ * DECLARE_LINKTABLE - Declares a data linker table entry
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Declares a data linker table entry.
+ */
+#define DECLARE_LINKTABLE(type, name) \
+ DECLARE_LINUX_SECTION(type, name)
+
+/**
+ * DECLARE_LINKTABLE_RO - Declares a read-only linker table entry
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Declares a read-only linker table entry.
+ */
+#define DECLARE_LINKTABLE_RO(type, name) \
+ DECLARE_LINUX_SECTION_RO(type, name)
+
+/**
+ * DOC: Defining Linker tables
+ *
+ * Linker tables are defined in the code that takes ownership over
+ * the linker table. This is typically done in the same code that is in
+ * charge of iterating over the linker table as well.
+ */
+
+/**
+ * DEFINE_LINKTABLE - Defines a linker table for data
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Defines a linker table which used for data.
+ */
+#define DEFINE_LINKTABLE(type, name) \
+ DECLARE_LINKTABLE(type, name); \
+ LINKTABLE_WEAK(name,) VMLINUX_SYMBOL(name)[0] = {}; \
+ LINKTABLE(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * DEFINE_LINKTABLE_TEXT - Declares linker table entry for exectuion
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Declares a linker table entry for execution.
+ */
+#define DEFINE_LINKTABLE_TEXT(type, name) \
+ DECLARE_LINKTABLE_RO(type, name); \
+ LINKTABLE_TEXT_WEAK(name,) VMLINUX_SYMBOL(name)[0] = {}; \
+ LINKTABLE_TEXT(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * DEFINE_LINKTABLE_RO - Defines a read-only linker table
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Defines a linker table which we know only requires read-only access.
+ */
+#define DEFINE_LINKTABLE_RO(type, name) \
+ DECLARE_LINKTABLE_RO(type, name); \
+ LINKTABLE_RO_WEAK(name,) VMLINUX_SYMBOL(name)[0] = {}; \
+ LINKTABLE_RO(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * DEFINE_LINKTABLE_INIT - Defines an init time linker table for execution
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Defines a linker table. If you are adding a new type you should
+ * enable ``CONFIG_DEBUG_SECTION_MISMATCH`` and ensure routines that make
+ * use of the linker tables get a respective __ref tag.
+ */
+#define DEFINE_LINKTABLE_INIT(type, name) \
+ DECLARE_LINKTABLE(type, name); \
+ LINKTABLE_INIT_WEAK(name,) VMLINUX_SYMBOL(name)[0] = {}; \
+ LINKTABLE_INIT(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * DEFINE_LINKTABLE_INIT_DATA - Defines an init time linker table for data
+ *
+ * @type: data type
+ * @name: table name
+ *
+ * Defines a linker table for init data. If you are adding a new type you
+ * should enable ``CONFIG_DEBUG_SECTION_MISMATCH`` and ensure routines that
+ * make use of the linker tables get a respective __ref tag.
+ */
+#define DEFINE_LINKTABLE_INIT_DATA(type, name) \
+ DECLARE_LINKTABLE(type, name); \
+ LINKTABLE_INIT_DATA_WEAK(name,) VMLINUX_SYMBOL(name)[0] = {}; \
+ LINKTABLE_INIT_DATA(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * DOC: Iterating over Linker tables
+ *
+ * To make use of the linker tables you want to be able to iterate over
+ * them. This section documents the different iterators available.
+ */
+
+/**
+ * LINKTABLE_FOR_EACH - iterate through all entries within a linker table
+ *
+ * @pointer: entry pointer
+ * @tbl: linker table
+ *
+ * Example usage::
+ *
+ * struct frobnicator *frob;
+ *
+ * LINKTABLE_FOR_EACH(frob, frobnicator_fns) {
+ * ...
+ * }
+ */
+
+#define LINKTABLE_FOR_EACH(pointer, tbl) \
+ for (pointer = LINUX_SECTION_START(tbl); \
+ pointer < LINUX_SECTION_END(tbl); \
+ pointer++)
+
+/**
+ * LINKTABLE_RUN_ALL - iterate and run through all entries on a linker table
+ *
+ * @tbl: linker table
+ * @func: structure name for the function name we want to call.
+ * @args...: arguments to pass to func
+ *
+ * Example usage::
+ *
+ * LINKTABLE_RUN_ALL(frobnicator_fns, some_run,);
+ */
+#define LINKTABLE_RUN_ALL(tbl, func, args...) \
+do { \
+ size_t i; \
+ for (i = 0; i < LINUX_SECTION_SIZE(tbl); i++) \
+ (VMLINUX_SYMBOL(tbl)[i]).func (args); \
+} while (0)
+
+/**
+ * LINKTABLE_RUN_ERR - run each linker table entry func and return error if any
+ *
+ * @tbl: linker table
+ * @func: structure name for the function name we want to call.
+ * @args...: arguments to pass to func
+ *
+ * Example usage::
+ *
+ * unsigned int err = LINKTABLE_RUN_ERR(frobnicator_fns, some_run,);
+ */
+#define LINKTABLE_RUN_ERR(tbl, func, args...) \
+({ \
+ size_t i; \
+ int err = 0; \
+ for (i = 0; !err && i < LINUX_SECTION_SIZE(tbl); i++) \
+ err = (VMLINUX_SYMBOL(tbl)[i]).func (args); \
+ err; \
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
@@ -36,6 +36,8 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
# directory
__clean-files := $(extra-y) $(extra-m) $(extra-) \
+ $(force-obj-y) $(force-obj-m) $(force-obj-) \
+ $(force-lib-y) $(force-lib-m) $(force-lib-) \
$(always) $(targets) $(clean-files) \
$(host-progs) \
$(hostprogs-y) $(hostprogs-m) $(hostprogs-) \