[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v4 07/16] tables.h: add linker table support



On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@xxxxxxxxxx> wrote:
> From: "Luis R. Rodriguez" <mcgrof@xxxxxxxxxx>
>
> A linker table is a data structure that is stitched together from items
> in multiple object files. Linux has historically implicitly used linker
> tables for ages, however they were all built in an adhoc manner which
> requires linker script modifications, per architecture. This adds a
> general linker table solution so that a new linker table can be
> implemented by changing C code only. The Linux linker table was
> inspired by Michael Brown's iPXE's linker table solution, it has been
> been completely re-written and adapted for integration and use on Linux.
>
> The same philosophy is borrowed, extended and further simplified:
>
> Linker tables enable an extremely light weight linker build time
> solution for feature ordering and selection, this can help to both
> simplify init sequences in a generic fashion and helps avoiding code
> bit-rotting when desirable. Further changes will be added later
> which will make more evident how code bit rot can be avoided using
> linker tables.
>
> v4:
>
> o Split out kbuild additions to help with code bit rot into
>   its own patch
> o tons of documentation love
> o fix arch/x86/tools/relocs.c typo - which caused compilation issues
>   on old toolchains
> o add c6x toolchain work around as discussed with Mark Salter
> o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
>   compilation on blackfin
> o suggested name changes by boris:
> - %s/SECTION_TYPE_RANGES/rng/g
> - %s/SECTION_TYPE/SECTION_CORE/g
> - %s/section_type_asmtype/section_core_type/g
> - %s/section_type/section_core/g
> - %s/section_rng/set_section_rng/g
> - Drop DECLARE_SECTION_TBL() -- this is an asm equivalent
>   DEFINE_LINKTABLE() -- this however is not used yet, and it requires
>   a bit more work to match the C code definitions.
> o drop tools/include/linux/sections.h in favor of the more popular open
>   coding the names for tools
> o expand documentation to include module support
> o add maintaners
> o Use generic-y
> o move .text.tbl before unlikely to match the other sections
>
> v3:
>
> o addressed initial modular support test cases
> o added generic asm macros so linker tables can be used in
>   asm code / C asm calls
> o section ranges are now split up into their own set of files
> o use asm/sections.h instead of linux/sections.h for the linker
>   script
> o add a sections.h file for each architecture that was missing one,
>   this is needed now as we'll be relying on sections.h for custom
>   section types in code rather than custom architecture specific
>   linker script hacks.
> o full rewrite at this point, decided to pick copyleft-next license
>   for this work
>
> v2:
>
> o modified completely to match feedback by community, made equivalent
>   modifications to userspace solution. This is pretty much a complete
>   rewrite of how we present and use linker tables. By using standard
>   sections we no longer have to make custom linker script extensions
>   for each new linker table solution, you just pick a linker table
>   type by section type.
> o extend documention considerably, including use of kdoc
> o drop ICC hacks per popular request to ignore such issues for now
> o use sections.h - this lets us streamline a clean use case of
>   well documented sections. To help further with this make use of
>   SECTION_TBL() to allow use of these in code and SECTION_TBL_ALL()
>   on linker scripts, as well as SECTION_TBL_ALL_STR() on relocs.c
>   when needed.
>
> Cc: Michael Brown <mcb30@xxxxxxxx>
> Signed-off-by: Luis R. Rodriguez <mcgrof@xxxxxxxxxx>
> ---
>  Documentation/sections/index.rst         |   1 +
>  Documentation/sections/linker-tables.rst | 187 ++++++++++
>  MAINTAINERS                              |  12 +
>  arch/alpha/include/asm/Kbuild            |   1 +
>  arch/arc/include/asm/Kbuild              |   1 +
>  arch/arm/include/asm/Kbuild              |   1 +
>  arch/arm64/include/asm/Kbuild            |   1 +
>  arch/avr32/include/asm/Kbuild            |   1 +
>  arch/blackfin/include/asm/Kbuild         |   1 +
>  arch/c6x/include/asm/tables.h            |  26 ++
>  arch/cris/include/asm/Kbuild             |   1 +
>  arch/frv/include/asm/Kbuild              |   1 +
>  arch/h8300/include/asm/Kbuild            |   1 +
>  arch/hexagon/include/asm/Kbuild          |   1 +
>  arch/ia64/include/asm/Kbuild             |   1 +
>  arch/m32r/include/asm/Kbuild             |   1 +
>  arch/m68k/include/asm/Kbuild             |   1 +
>  arch/metag/include/asm/Kbuild            |   1 +
>  arch/microblaze/include/asm/Kbuild       |   1 +
>  arch/mips/include/asm/Kbuild             |   1 +
>  arch/mn10300/include/asm/Kbuild          |   1 +
>  arch/nios2/include/asm/Kbuild            |   1 +
>  arch/openrisc/include/asm/Kbuild         |   1 +
>  arch/parisc/include/asm/Kbuild           |   1 +
>  arch/powerpc/include/asm/Kbuild          |   1 +
>  arch/s390/include/asm/Kbuild             |   1 +
>  arch/score/include/asm/Kbuild            |   1 +
>  arch/sh/include/asm/Kbuild               |   1 +
>  arch/sparc/include/asm/Kbuild            |   1 +
>  arch/tile/include/asm/Kbuild             |   1 +
>  arch/um/include/asm/Kbuild               |   1 +
>  arch/unicore32/include/asm/Kbuild        |   1 +
>  arch/x86/include/asm/Kbuild              |   1 +
>  arch/x86/tools/relocs.c                  |   2 +
>  arch/xtensa/include/asm/Kbuild           |   1 +
>  include/asm-generic/ranges.h             |  14 +
>  include/asm-generic/tables.h             |  50 +++
>  include/asm-generic/vmlinux.lds.h        |   6 +
>  include/linux/tables.h                   | 567 
> +++++++++++++++++++++++++++++++
>  scripts/Makefile.clean                   |   2 +
>  40 files changed, 897 insertions(+)
>  create mode 100644 Documentation/sections/linker-tables.rst
>  create mode 100644 arch/c6x/include/asm/tables.h
>  create mode 100644 include/asm-generic/tables.h
>  create mode 100644 include/linux/tables.h
>
> diff --git a/Documentation/sections/index.rst 
> b/Documentation/sections/index.rst
> index 6dd93ddd5dbe..4514c5738b33 100644
> --- a/Documentation/sections/index.rst
> +++ b/Documentation/sections/index.rst
> @@ -10,3 +10,4 @@ used throughout the kernel to help declare and define them.
>
>     section-core
>     ranges
> +   linker-tables
> diff --git a/Documentation/sections/linker-tables.rst 
> b/Documentation/sections/linker-tables.rst
> new file mode 100644
> index 000000000000..df11c632dca7
> --- /dev/null
> +++ b/Documentation/sections/linker-tables.rst
> @@ -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
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1a217751aa8a..e3569ed12c86 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5200,6 +5200,18 @@ S:       Maintained
>  F:     include/asm-generic/
>  F:     include/uapi/asm-generic/
>
> +GENERIC LINKER TABLES
> +M:     "Luis R. Rodriguez" <mcgrof@xxxxxxxxxx>
> +M:     "H. Peter Anvin" <hpa@xxxxxxxxx>
> +L:     linux-arch@xxxxxxxxxxxxxxx
> +L:     linux-kernel@xxxxxxxxxxxxxxx
> +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@xxxxxx>
>  L:     linux-kernel@xxxxxxxxxxxxxxx
> diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
> index e44c896b91c4..f3bdc31d3c97 100644
> --- a/arch/alpha/include/asm/Kbuild
> +++ b/arch/alpha/include/asm/Kbuild
> @@ -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
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index e5295413fdf8..70f252472cb9 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -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
> diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
> index 8e52300e1eed..d13700f573d0 100644
> --- a/arch/arm/include/asm/Kbuild
> +++ b/arch/arm/include/asm/Kbuild
> @@ -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
> diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
> index 5ff184574976..a1991517aad6 100644
> --- a/arch/arm64/include/asm/Kbuild
> +++ b/arch/arm64/include/asm/Kbuild
> @@ -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
> diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
> index edc176348d7c..a6cd145515ae 100644
> --- a/arch/avr32/include/asm/Kbuild
> +++ b/arch/avr32/include/asm/Kbuild
> @@ -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
> diff --git a/arch/blackfin/include/asm/Kbuild 
> b/arch/blackfin/include/asm/Kbuild
> index 35b7752e65c0..b71893b1cd53 100644
> --- a/arch/blackfin/include/asm/Kbuild
> +++ b/arch/blackfin/include/asm/Kbuild
> @@ -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
> diff --git a/arch/c6x/include/asm/tables.h b/arch/c6x/include/asm/tables.h
> new file mode 100644
> index 000000000000..09a9e31c573a
> --- /dev/null
> +++ b/arch/c6x/include/asm/tables.h
> @@ -0,0 +1,26 @@
> +#ifndef _ASM_C6X_ASM_TABLES_H
> +#define _ASM_C6X_ASM_TABLES_H
> +/*
> + * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@xxxxxxxxxx>
> + *
> + * 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.

Type: waek -> weak

> + *
> + * [0] https://lkml.kernel.org/r/1470798247.3551.94.camel@xxxxxxxxxx
> + */
> +
> +#define SECTION_TBL_RO         .const
> +
> +#include <asm-generic/tables.h>
> +
> +#endif /* _ASM_C6X_ASM_TABLES_H */
> diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
> index fb8bb4112773..7062c1be7913 100644
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -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
> diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
> index 5191fec655d7..4a59cbda5091 100644
> --- a/arch/frv/include/asm/Kbuild
> +++ b/arch/frv/include/asm/Kbuild
> @@ -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
> diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
> index 7929a992566c..d79968d93c12 100644
> --- a/arch/h8300/include/asm/Kbuild
> +++ b/arch/h8300/include/asm/Kbuild
> @@ -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
> diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
> index af17ee334788..d59ac1c1858b 100644
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -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
> diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
> index d8f226b35a0a..76540f143473 100644
> --- a/arch/ia64/include/asm/Kbuild
> +++ b/arch/ia64/include/asm/Kbuild
> @@ -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
> diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
> index 1c6504d29312..24088f3c733c 100644
> --- a/arch/m32r/include/asm/Kbuild
> +++ b/arch/m32r/include/asm/Kbuild
> @@ -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
> diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
> index d465f51c2088..65c0df17f70e 100644
> --- a/arch/m68k/include/asm/Kbuild
> +++ b/arch/m68k/include/asm/Kbuild
> @@ -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
> diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
> index c869b1ebd583..2538224899fd 100644
> --- a/arch/metag/include/asm/Kbuild
> +++ b/arch/metag/include/asm/Kbuild
> @@ -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
> diff --git a/arch/microblaze/include/asm/Kbuild 
> b/arch/microblaze/include/asm/Kbuild
> index 63c083a1f8da..01afb1b420f5 100644
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -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
> diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
> index ed225600c8a4..07009c0863f6 100644
> --- a/arch/mips/include/asm/Kbuild
> +++ b/arch/mips/include/asm/Kbuild
> @@ -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
> diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
> index 656af7b69940..6c8d12f3fe44 100644
> --- a/arch/mn10300/include/asm/Kbuild
> +++ b/arch/mn10300/include/asm/Kbuild
> @@ -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
> diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
> index c55880659d67..ee6220dac1e8 100644
> --- a/arch/nios2/include/asm/Kbuild
> +++ b/arch/nios2/include/asm/Kbuild
> @@ -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
> diff --git a/arch/openrisc/include/asm/Kbuild 
> b/arch/openrisc/include/asm/Kbuild
> index 7d6a704b808c..ceafe458e295 100644
> --- a/arch/openrisc/include/asm/Kbuild
> +++ b/arch/openrisc/include/asm/Kbuild
> @@ -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
> diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
> index 1a263a7158e2..99211477bfb2 100644
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -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
> diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
> index 065c6e84fb67..bbd54aa1571e 100644
> --- a/arch/powerpc/include/asm/Kbuild
> +++ b/arch/powerpc/include/asm/Kbuild
> @@ -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
> diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
> index 3e8b95927cb5..92c2250a1521 100644
> --- a/arch/s390/include/asm/Kbuild
> +++ b/arch/s390/include/asm/Kbuild
> @@ -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
> diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
> index f0cdb2cbca4d..16ea15a3e432 100644
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -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
> diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
> index c9bb7932a3d1..d0ea768d15ae 100644
> --- a/arch/sh/include/asm/Kbuild
> +++ b/arch/sh/include/asm/Kbuild
> @@ -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
> diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
> index 79664d10e63b..0e7663749c97 100644
> --- a/arch/sparc/include/asm/Kbuild
> +++ b/arch/sparc/include/asm/Kbuild
> @@ -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
> diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
> index 951fa4be571d..8f3e38c981cd 100644
> --- a/arch/tile/include/asm/Kbuild
> +++ b/arch/tile/include/asm/Kbuild
> @@ -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
> diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> index 99be54949b99..eea5dd842992 100644
> --- a/arch/um/include/asm/Kbuild
> +++ b/arch/um/include/asm/Kbuild
> @@ -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
> diff --git a/arch/unicore32/include/asm/Kbuild 
> b/arch/unicore32/include/asm/Kbuild
> index 6c35905fe371..5c31eafbf1fd 100644
> --- a/arch/unicore32/include/asm/Kbuild
> +++ b/arch/unicore32/include/asm/Kbuild
> @@ -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
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index f790756fdb48..cd0fa76b32a3 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -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
> diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
> index c215db049920..45733a182ac2 100644
> --- a/arch/x86/tools/relocs.c
> +++ b/arch/x86/tools/relocs.c
> @@ -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__.*|"
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index 221b6b652500..ae48f8fd9212 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -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
> diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
> index 74cd941aa2f8..8cf21a1497c6 100644
> --- a/include/asm-generic/ranges.h
> +++ b/include/asm-generic/ranges.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_ */
> diff --git a/include/asm-generic/tables.h b/include/asm-generic/tables.h
> new file mode 100644
> index 000000000000..43cd03a83bd2
> --- /dev/null
> +++ b/include/asm-generic/tables.h
> @@ -0,0 +1,50 @@
> +#ifndef _ASM_GENERIC_TABLES_H_
> +#define _ASM_GENERIC_TABLES_H_
> +/*
> + * Linux linker tables
> + *
> + * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@xxxxxxxxxx>
> + *
> + * 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_ */
> diff --git a/include/asm-generic/vmlinux.lds.h 
> b/include/asm-generic/vmlinux.lds.h
> index ad843555e6a4..4b6a3d820883 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.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)
>
> diff --git a/include/linux/tables.h b/include/linux/tables.h
> new file mode 100644
> index 000000000000..423827eafb52
> --- /dev/null
> +++ b/include/linux/tables.h
> @@ -0,0 +1,567 @@
> +#ifndef _LINUX_LINKER_TABLES_H
> +#define _LINUX_LINKER_TABLES_H
> +/*
> + * Linux linker tables
> + *
> + * Copyright (C) 2016 Luis R. Rodriguez <mcgrof@xxxxxxxxxx>
> + *
> + * 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 */
> diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> index 50616ea25131..2b54546237d6 100644
> --- a/scripts/Makefile.clean
> +++ b/scripts/Makefile.clean
> @@ -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-) \
> --
> 2.9.2
>



-- 
Kees Cook
Nexus Security

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.